Smaller Record; also, use u128/i128 when possible

This commit is contained in:
Tony Garnock-Jones 2020-06-15 12:48:53 +02:00
parent 1f4adc5ba6
commit bffbeb2f6e
10 changed files with 512 additions and 252 deletions

View File

@ -27,13 +27,15 @@ pub enum ExpectedKind {
Float,
Double,
SignedIntegerI128,
SignedIntegerU128,
SignedInteger,
String,
ByteString,
Symbol,
Record(Option<usize>),
SimpleRecord(&'static str, Option<usize>),
SimpleRecord(String, Option<usize>),
Sequence,
Set,
Dictionary,

View File

@ -147,8 +147,7 @@ mod ieee754_section_5_10_total_order_tests {
#[cfg(test)]
mod value_tests {
use crate::value::{Value, PlainValue};
use num::bigint::BigInt;
use crate::value::{Value, PlainValue, value::Record, signed_integer::SignedInteger};
use super::dom::Dom;
type VV = Value<PlainValue<Dom>, Dom>;
@ -179,11 +178,9 @@ mod value_tests {
#[test] fn signedinteger_mut() {
let mut i = VV::from(123);
assert!(i.is_signedinteger());
*(i.as_signedinteger_mut().unwrap()) = BigInt::from(234);
*(i.as_signedinteger_mut().unwrap()) = SignedInteger::from(234i128);
assert_eq!(i, VV::from(234));
use num::traits::cast::ToPrimitive;
assert_eq!(i.as_signedinteger().unwrap().to_i64().unwrap(), 234);
assert_eq!(i.as_i().unwrap(), 234);
}
#[test] fn string_mut() {
@ -209,13 +206,13 @@ mod value_tests {
#[test] fn record_mut() {
let says = VV::symbol("says").wrap();
let mut r = VV::record(says.clone(), vec![VV::from("Tony").wrap(), VV::from("Hello!").wrap()]);
let mut r = VV::Record(Record(vec![says.clone(), VV::from("Tony").wrap(), VV::from("Hello!").wrap()]));
assert_eq!(r.as_record_mut(Some(0)), None);
assert_eq!(r.as_record_mut(Some(1)), None);
assert!(r.as_record_mut(Some(2)).is_some());
assert_eq!(r.as_record_mut(Some(3)), None);
r.as_record_mut(None).unwrap().1[0] = VV::from("Alice").wrap();
assert_eq!(r, VV::record(says, vec![VV::from("Alice").wrap(), VV::from("Hello!").wrap()]));
r.as_record_mut(None).unwrap().fields_mut()[0] = VV::from("Alice").wrap();
assert_eq!(r, VV::Record(Record(vec![says, VV::from("Alice").wrap(), VV::from("Hello!").wrap()])));
}
#[test] fn sequence_mut() {
@ -275,9 +272,9 @@ mod decoder_tests {
assert_eq!(buf.len(), 12);
let mut d = decoder::from_bytes(&mut buf);
assert_eq!(d.read.source.index, 0);
assert_eq!(d.demand_next().unwrap().value(), &Value::simple_record("Ping", vec![]));
assert_eq!(d.demand_next().unwrap().value(), &Value::simple_record0("Ping"));
assert_eq!(d.read.source.index, 6);
assert_eq!(d.demand_next().unwrap().value(), &Value::simple_record("Pong", vec![]));
assert_eq!(d.demand_next().unwrap().value(), &Value::simple_record0("Pong"));
assert_eq!(d.read.source.index, 12);
assert!(d.next().is_none());
assert!(if let Err(e) = d.demand_next() { is_eof_io_error(&e) } else { false });

View File

@ -1,7 +1,6 @@
use crate::value::value::{Float, Double};
use crate::value::{Value, NestedValue, IOValue, UnwrappedIOValue, Map};
use crate::error::{Error, ExpectedKind, Received};
use num::traits::cast::ToPrimitive;
use serde::Deserialize;
use serde::de::{Visitor, SeqAccess, MapAccess, EnumAccess, VariantAccess, DeserializeSeed};
use std::iter::Iterator;
@ -43,14 +42,6 @@ impl<'de, 'a> serde::de::Deserializer<'de> for &'a mut Deserializer<'de>
Value::Boolean(b) => visitor.visit_bool(*b),
Value::Float(Float(f)) => visitor.visit_f32(*f),
Value::Double(Double(d)) => visitor.visit_f64(*d),
Value::SignedInteger(ref i) =>
match i.to_i64() {
None => match i.to_u64() {
None => Err(Error::NumberOutOfRange(i.clone())),
Some(n) => visitor.visit_u64(n),
}
Some(n) => visitor.visit_i64(n),
}
Value::String(ref s) => visitor.visit_str(&s),
Value::ByteString(_) => self.deserialize_bytes(visitor),
Value::Record(_) =>
@ -67,7 +58,16 @@ impl<'de, 'a> serde::de::Deserializer<'de> for &'a mut Deserializer<'de>
}
Value::Sequence(ref v) => visitor.visit_seq(VecSeq::new(self, v.iter())),
Value::Dictionary(ref d) => visitor.visit_map(DictMap::new(self, d)),
_ => Err(Error::CannotDeserializeAny),
_ => match v.as_i64() {
Some(i) => visitor.visit_i64(i),
None => match v.as_u64() {
Some(u) => visitor.visit_u64(u),
None => match v.as_signedinteger() {
Some(n) => Err(Error::NumberOutOfRange(n.into())),
None => Err(Error::CannotDeserializeAny),
}
}
}
}
}
@ -328,9 +328,9 @@ impl<'a, 'de> EnumAccess<'de> for &'a mut Deserializer<'de> {
fn variant_seed<V>(self, seed: V)
-> Result<(V::Value, Self::Variant)> where V: DeserializeSeed<'de>
{
let (lp, _) = self.check(|v| v.as_record(None), ExpectedKind::Record(None))?;
let r = self.check(|v| v.as_record(None), ExpectedKind::Record(None))?;
let v = self.input;
self.input = IOValue::boxunwrap(lp);
self.input = r.label();
let variant = seed.deserialize(&mut *self)?;
self.input = v;
Ok((variant, self))
@ -345,18 +345,18 @@ impl<'a, 'de> VariantAccess<'de> for &'a mut Deserializer<'de> {
}
fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value> where T: DeserializeSeed<'de> {
let (_, fs) = self.check(|v| v.as_record(Some(1)), ExpectedKind::Record(Some(1)))?;
self.input = &fs[0];
let r = self.check(|v| v.as_record(Some(1)), ExpectedKind::Record(Some(1)))?;
self.input = &r.fields()[0];
seed.deserialize(&mut *self)
}
fn tuple_variant<V>(self, _len: usize, visitor: V) -> Result<V::Value> where V: Visitor<'de> {
visitor.visit_seq(VecSeq::new(self, self.input.value().as_record(None).unwrap().1.iter()))
visitor.visit_seq(VecSeq::new(self, self.input.value().as_record(None).unwrap().fields().iter()))
}
fn struct_variant<V>(self, fields: &'static [&'static str], visitor: V)
-> Result<V::Value> where V: Visitor<'de>
{
visitor.visit_seq(VecSeq::new(self, self.input.value().as_record(Some(fields.len())).unwrap().1.iter()))
visitor.visit_seq(VecSeq::new(self, self.input.value().as_record(Some(fields.len())).unwrap().fields().iter()))
}
}

View File

@ -1,4 +1,5 @@
use super::value::{Value, NestedValue, Domain, IOValue, UnwrappedIOValue, Float, Double};
use super::signed_integer::SignedIntegerRepr;
use super::writer::Writer;
pub use super::writer::Result;
@ -31,14 +32,18 @@ impl<'a, W: Writer> Encoder<'a, W> {
Value::Boolean(b) => self.write.write_bool(*b),
Value::Float(Float(f)) => self.write.write_f32(*f),
Value::Double(Double(d)) => self.write.write_f64(*d),
Value::SignedInteger(ref b) => self.write.write_int(b),
Value::SignedInteger(n) => match n.repr() {
SignedIntegerRepr::I128(i) => self.write.write_i128(*i),
SignedIntegerRepr::U128(u) => self.write.write_u128(*u),
SignedIntegerRepr::Big(ref n) => self.write.write_int(n),
}
Value::String(ref s) => self.write.write_string(s),
Value::ByteString(ref bs) => self.write.write_bytes(bs),
Value::Symbol(ref s) => self.write.write_symbol(s),
Value::Record((ref l, ref fs)) => {
self.write.open_record(fs.len())?;
self.write(IOValue::boxunwrap(l))?;
for f in fs { self.write(f)?; }
Value::Record(r) => {
self.write.open_record(r.arity())?;
self.write(r.label())?;
for f in r.fields() { self.write(f)?; }
self.write.close_record()
}
Value::Sequence(ref vs) => {

View File

@ -4,6 +4,7 @@ pub mod decoder;
pub mod encoder;
pub mod reader;
pub mod ser;
pub mod signed_integer;
pub mod value;
pub mod writer;

View File

@ -6,7 +6,8 @@ use std::convert::TryInto;
use std::io::{Read, Error};
use std::marker::PhantomData;
use super::constants::{Op, InvalidOp, AtomMinor, CompoundMinor};
use super::value::{Value, NestedValue, IOValue, FALSE, TRUE, Map, Set};
use super::signed_integer::SignedInteger;
use super::value::{Value, NestedValue, IOValue, FALSE, TRUE, Map, Set, Record};
use crate::error::{self, ExpectedKind, Received, is_eof_io_error, io_eof, io_syntax_error};
pub type IOResult<T> = std::result::Result<T, Error>;
@ -138,6 +139,8 @@ pub trait Reader<'de> {
fn next_u32(&mut self) -> ReaderResult<u32> { self.demand_next(false)?.value().to_u32() }
fn next_i64(&mut self) -> ReaderResult<i64> { self.demand_next(false)?.value().to_i64() }
fn next_u64(&mut self) -> ReaderResult<u64> { self.demand_next(false)?.value().to_u64() }
fn next_i128(&mut self) -> ReaderResult<i128> { self.demand_next(false)?.value().to_i128() }
fn next_u128(&mut self) -> ReaderResult<u128> { self.demand_next(false)?.value().to_u128() }
fn next_float(&mut self) -> ReaderResult<f32> { self.demand_next(false)?.value().to_float() }
fn next_double(&mut self) -> ReaderResult<f64> { self.demand_next(false)?.value().to_double() }
fn next_char(&mut self) -> ReaderResult<char> { self.demand_next(false)?.value().to_char() }
@ -169,7 +172,7 @@ pub trait Reader<'de> {
}
}
fn open_simple_record(&mut self, name: &'static str, arity: Option<usize>) ->
fn open_simple_record(&mut self, name: &str, arity: Option<usize>) ->
ReaderResult<CompoundBody>
where
Self: Sized
@ -179,7 +182,7 @@ pub trait Reader<'de> {
if label == name {
Ok(compound_body)
} else {
Err(error::Error::Expected(ExpectedKind::SimpleRecord(name, arity),
Err(error::Error::Expected(ExpectedKind::SimpleRecord(name.to_owned(), arity),
Received::ReceivedRecordWithLabel(label.to_owned())))
}
}
@ -354,6 +357,10 @@ pub fn from_read<'de, 'a, IOR: std::io::Read>(read: &'a mut IOR) ->
BinaryReader::new(IOBinarySource::new(read))
}
fn out_of_range<I: Into<BigInt>>(i: I) -> error::Error {
error::Error::NumberOutOfRange(i.into())
}
impl<'de, S: BinarySource<'de>> BinaryReader<'de, S> {
pub fn new(source: S) -> Self {
BinaryReader { source, phantom: PhantomData }
@ -462,97 +469,94 @@ impl<'de, S: BinarySource<'de>> BinaryReader<'de, S> {
}
}
fn read_number_format_b(&mut self, count: usize) -> IOResult<SignedInteger> {
if count == 0 {
return Ok(SignedInteger::from(0 as i128));
}
if count > 16 {
let bs = self.readbytes(count)?;
if (bs[0] & 0x80) == 0 {
// Positive or zero.
let mut i = 0;
while i < count && bs[i] == 0 { i = i + 1; }
if count - i <= 16 {
Ok(SignedInteger::from(u128::from_be_bytes(bs[bs.len() - 16..].try_into().unwrap())))
} else {
Ok(SignedInteger::from(Cow::Owned(BigInt::from_bytes_be(num::bigint::Sign::Plus, &bs[i..]))))
}
} else {
// Negative.
let mut i = 0;
while i < count && bs[i] == 0xff { i = i + 1; }
if count - i <= 16 {
Ok(SignedInteger::from(i128::from_be_bytes(bs[bs.len() - 16..].try_into().unwrap())))
} else {
Ok(SignedInteger::from(Cow::Owned(BigInt::from_signed_bytes_be(&bs))))
}
}
} else {
let first_byte = self.read()?;
let prefix_byte = if (first_byte & 0x80) == 0 { 0x00 } else { 0xff };
let mut bs = [prefix_byte; 16];
bs[16 - count] = first_byte;
self.readbytes_into(&mut bs[16 - (count - 1)..])?;
Ok(SignedInteger::from(i128::from_be_bytes(bs)))
}
}
fn next_unsigned<T: FromPrimitive, F>(&mut self, f: F) -> ReaderResult<T>
where
F: FnOnce(u64) -> Option<T>
F: FnOnce(u128) -> Option<T>
{
match self.peek_next_nonannotation_op()? {
(Op::Misc(3), arg) => {
self.skip()?;
if arg > 12 {
Err(error::Error::NumberOutOfRange(decodeint(&[((arg as i8) - 16) as u8])))
Err(out_of_range((arg as i8) - 16))
} else {
f(arg as u64).ok_or_else(|| error::Error::NumberOutOfRange(decodeint(&[arg])))
f(arg as u128).ok_or_else(|| out_of_range(arg))
}
}
(Op::Atom(AtomMinor::SignedInteger), arg) => {
self.skip()?;
let mut count = self.wirelength(arg)?;
if count == 0 {
return f(0).ok_or_else(|| error::Error::NumberOutOfRange(BigInt::from(0)));
}
if count > 8 {
let prefix = self.readbytes(count - 8)?;
if !(&prefix).iter().all(|b| *b == 0x00) {
let mut total = prefix.into_owned();
total.extend_from_slice(&self.readbytes(8)?);
return Err(error::Error::NumberOutOfRange(decodeint(&total)));
}
count = 8;
} else {
if (self.peek()? & 0x80) != 0 {
return Err(error::Error::NumberOutOfRange(decodeint(&self.readbytes(count)?)))
}
}
let mut bs = [0; 8];
self.readbytes_into(&mut bs[8 - count..])?;
f(u64::from_be_bytes(bs))
.ok_or_else(|| error::Error::NumberOutOfRange(decodeint(&bs)))
let count = self.wirelength(arg)?;
let n = &self.read_number_format_b(count)?;
let i = n.try_into().or_else(|_| Err(out_of_range(n)))?;
f(i).ok_or_else(|| out_of_range(i))
}
_ => {
let i_value = self.demand_next(false)?;
let i = i_value.value().to_signedinteger()?;
let n = i.to_u64().ok_or_else(|| error::Error::NumberOutOfRange(i.clone()))?;
f(n).ok_or_else(|| error::Error::NumberOutOfRange(i.clone()))
let n_value = self.demand_next(false)?;
let n = n_value.value().to_signedinteger()?;
let i = n.try_into().or_else(|_| Err(out_of_range(n)))?;
f(i).ok_or_else(|| out_of_range(i))
}
}
}
fn next_signed<T: FromPrimitive, F>(&mut self, f: F) -> ReaderResult<T>
where
F: FnOnce(i64) -> Option<T>
F: FnOnce(i128) -> Option<T>
{
match self.peek_next_nonannotation_op()? {
(Op::Misc(3), arg) => {
self.skip()?;
let n = arg as i64;
let n = arg as i128;
let n = if n > 12 { n - 16 } else { n };
f(n).ok_or_else(|| error::Error::NumberOutOfRange(decodeint(&[n as u8])))
f(n).ok_or_else(|| out_of_range(n))
}
(Op::Atom(AtomMinor::SignedInteger), arg) => {
self.skip()?;
let mut count = self.wirelength(arg)?;
if count == 0 {
return f(0).ok_or_else(|| error::Error::NumberOutOfRange(BigInt::from(0)));
}
let fill_byte = if count > 8 {
let prefix = self.readbytes(count - 8)?;
let fill_byte = if (prefix[0] & 0x80) == 0 { 0x00 } else { 0xff };
if !(&prefix).iter().all(|b| *b == fill_byte) {
let mut total = prefix.into_owned();
total.extend_from_slice(&self.readbytes(8)?);
return Err(error::Error::NumberOutOfRange(decodeint(&total)));
}
count = 8;
if (self.peek()? & 0x80) != (fill_byte & 0x80) {
let mut total = vec![fill_byte];
total.extend_from_slice(&self.readbytes(8)?);
return Err(error::Error::NumberOutOfRange(decodeint(&total)));
}
fill_byte
} else {
if (self.peek()? & 0x80) == 0 { 0x00 } else { 0xff }
};
let mut bs = [fill_byte; 8];
self.readbytes_into(&mut bs[8 - count..])?;
f(i64::from_be_bytes(bs))
.ok_or_else(|| error::Error::NumberOutOfRange(decodeint(&bs)))
let count = self.wirelength(arg)?;
let n = &self.read_number_format_b(count)?;
let i = n.try_into().or_else(|_| Err(out_of_range(n)))?;
f(i).ok_or_else(|| out_of_range(i))
}
_ => {
let i_value = self.demand_next(false)?;
let i = i_value.value().to_signedinteger()?;
let n = i.to_i64().ok_or_else(|| error::Error::NumberOutOfRange(i.clone()))?;
f(n).ok_or_else(|| error::Error::NumberOutOfRange(i.clone()))
let n_value = self.demand_next(false)?;
let n = n_value.value().to_signedinteger()?;
let i = n.try_into().or_else(|_| Err(out_of_range(n)))?;
f(i).ok_or_else(|| out_of_range(i))
}
}
}
@ -612,6 +616,11 @@ impl<'de, S: BinarySource<'de>> Reader<'de> for BinaryReader<'de, S> {
Cow::Owned(Value::from(n).wrap())
}
(Op::Misc(_), _) => unreachable!(),
(Op::Atom(AtomMinor::SignedInteger), arg) => {
let count = self.wirelength(arg)?;
let n = self.read_number_format_b(count)?;
Cow::Owned(Value::SignedInteger(n).wrap())
}
(Op::Atom(minor), arg) => {
let count = self.wirelength(arg)?;
Cow::Owned(decodebinary(minor, self.readbytes(count)?)?)
@ -697,15 +706,17 @@ impl<'de, S: BinarySource<'de>> Reader<'de> for BinaryReader<'de, S> {
}
}
fn next_i8(&mut self) -> ReaderResult<i8> { self.next_signed(|n| n.to_i8()) }
fn next_i16(&mut self) -> ReaderResult<i16> { self.next_signed(|n| n.to_i16()) }
fn next_i32(&mut self) -> ReaderResult<i32> { self.next_signed(|n| n.to_i32()) }
fn next_i64(&mut self) -> ReaderResult<i64> { self.next_signed(|n| Some(n)) }
fn next_i8(&mut self) -> ReaderResult<i8> { self.next_signed(|n| n.to_i8()) }
fn next_i16(&mut self) -> ReaderResult<i16> { self.next_signed(|n| n.to_i16()) }
fn next_i32(&mut self) -> ReaderResult<i32> { self.next_signed(|n| n.to_i32()) }
fn next_i64(&mut self) -> ReaderResult<i64> { self.next_signed(|n| n.to_i64()) }
fn next_i128(&mut self) -> ReaderResult<i128> { self.next_signed(|n| n.to_i128()) }
fn next_u8(&mut self) -> ReaderResult<u8> { self.next_unsigned(|n| n.to_u8()) }
fn next_u16(&mut self) -> ReaderResult<u16> { self.next_unsigned(|n| n.to_u16()) }
fn next_u32(&mut self) -> ReaderResult<u32> { self.next_unsigned(|n| n.to_u32()) }
fn next_u64(&mut self) -> ReaderResult<u64> { self.next_unsigned(|n| Some(n)) }
fn next_u8(&mut self) -> ReaderResult<u8> { self.next_unsigned(|n| n.to_u8()) }
fn next_u16(&mut self) -> ReaderResult<u16> { self.next_unsigned(|n| n.to_u16()) }
fn next_u32(&mut self) -> ReaderResult<u32> { self.next_unsigned(|n| n.to_u32()) }
fn next_u64(&mut self) -> ReaderResult<u64> { self.next_unsigned(|n| n.to_u64()) }
fn next_u128(&mut self) -> ReaderResult<u128> { self.next_unsigned(|n| n.to_u128()) }
fn next_float(&mut self) -> ReaderResult<f32> {
match self.peek_next_nonannotation_op()? {
@ -793,10 +804,6 @@ pub fn decodeop(b: u8) -> IOResult<(Op, u8)> {
Ok((Op::try_from(b >> 4)?, b & 15))
}
pub fn decodeint(bs: &[u8]) -> BigInt {
BigInt::from_signed_bytes_be(bs)
}
pub fn decodestr<'de>(cow: Cow<'de, [u8]>) -> IOResult<Cow<'de, str>> {
match cow {
Cow::Borrowed(bs) =>
@ -808,7 +815,7 @@ pub fn decodestr<'de>(cow: Cow<'de, [u8]>) -> IOResult<Cow<'de, str>> {
pub fn decodebinary<'de>(minor: AtomMinor, bs: Cow<'de, [u8]>) -> IOResult<IOValue> {
Ok(match minor {
AtomMinor::SignedInteger => Value::from(decodeint(&bs)).wrap(),
AtomMinor::SignedInteger => Value::from(&BigInt::from_signed_bytes_be(&bs)).wrap(),
AtomMinor::String => Value::String(decodestr(bs)?.into_owned()).wrap(),
AtomMinor::ByteString => Value::ByteString(bs.into_owned()).wrap(),
AtomMinor::Symbol => Value::symbol(&decodestr(bs)?).wrap(),
@ -822,15 +829,14 @@ pub fn decodecompound<'de, I: Iterator<Item = IOResult<Cow<'de, IOValue>>>>(
IOResult<IOValue>
{
match minor {
CompoundMinor::Record =>
match iter.next() {
None => Err(io_syntax_error("Too few elements in encoded record")),
Some(labelres) => {
let label = labelres?.into_owned();
let fields = iter.map(|r| r.map(|c| c.into_owned())).collect::<IOResult<Vec<IOValue>>>()?;
Ok(Value::record(label, fields).wrap())
}
CompoundMinor::Record => {
let vs = iter.map(|r| r.map(|c| c.into_owned())).collect::<IOResult<Vec<IOValue>>>()?;
if vs.len() < 1 {
Err(io_syntax_error("Too few elements in encoded record"))
} else {
Ok(Value::Record(Record(vs)).wrap())
}
}
CompoundMinor::Sequence => {
let vs = iter.map(|r| r.map(|c| c.into_owned())).collect::<IOResult<Vec<IOValue>>>()?;
Ok(Value::Sequence(vs).wrap())

View File

@ -1,4 +1,4 @@
use crate::value::{Value, Map, IOValue};
use crate::value::{Value, value::Record, Map, IOValue};
use serde::Serialize;
#[derive(Debug)]
@ -25,8 +25,7 @@ pub struct SerializeDictionary {
}
pub struct SerializeRecord {
name: &'static str,
vec: Vec<IOValue>,
r: Record<IOValue>,
}
pub struct SerializeSequence {
@ -89,7 +88,7 @@ impl serde::Serializer for Serializer {
}
fn serialize_char(self, v: char) -> Result<Self::Ok> {
Ok(Value::simple_record("UnicodeScalar", vec![Value::from(v as u32).wrap()]).wrap())
Ok(Value::simple_record1("UnicodeScalar", Value::from(v as u32).wrap()).wrap())
}
fn serialize_str(self, v: &str) -> Result<Self::Ok> {
@ -101,19 +100,19 @@ impl serde::Serializer for Serializer {
}
fn serialize_none(self) -> Result<Self::Ok> {
Ok(Value::simple_record("None", vec![]).wrap())
Ok(Value::simple_record0("None").wrap())
}
fn serialize_some<T: ?Sized>(self, v: &T) -> Result<Self::Ok> where T: Serialize {
Ok(Value::simple_record("Some", vec![to_value(v)]).wrap())
Ok(Value::simple_record1("Some", to_value(v)).wrap())
}
fn serialize_unit(self) -> Result<Self::Ok> {
Ok(Value::simple_record("tuple", vec![]).wrap())
Ok(Value::simple_record0("tuple").wrap())
}
fn serialize_unit_struct(self, name: &'static str) -> Result<Self::Ok> {
Ok(Value::simple_record(name, vec![]).wrap())
Ok(Value::simple_record0(name).wrap())
}
fn serialize_unit_variant(self,
@ -122,7 +121,7 @@ impl serde::Serializer for Serializer {
variant_name: &'static str) ->
Result<Self::Ok>
{
Ok(Value::simple_record(variant_name, vec![]).wrap())
Ok(Value::simple_record0(variant_name).wrap())
}
fn serialize_newtype_struct<T: ?Sized>(self, name: &'static str, value: &T) ->
@ -132,7 +131,7 @@ impl serde::Serializer for Serializer {
Some(v) => Ok(v),
None => {
// TODO: This is apparently discouraged, and we should apparently just serialize `value`?
Ok(Value::simple_record(name, vec![to_value(value)]).wrap())
Ok(Value::simple_record1(name, to_value(value)).wrap())
}
}
}
@ -144,7 +143,7 @@ impl serde::Serializer for Serializer {
value: &T) ->
Result<Self::Ok> where T: Serialize
{
Ok(Value::simple_record(variant_name, vec![to_value(value)]).wrap())
Ok(Value::simple_record1(variant_name, to_value(value)).wrap())
}
fn serialize_seq(self, count: Option<usize>) -> Result<Self::SerializeSeq> {
@ -153,13 +152,13 @@ impl serde::Serializer for Serializer {
}
fn serialize_tuple(self, count: usize) -> Result<Self::SerializeTuple> {
Ok(SerializeRecord { name: "tuple", vec: Vec::with_capacity(count) })
Ok(SerializeRecord { r: Value::simple_record("tuple", count) })
}
fn serialize_tuple_struct(self, name: &'static str, count: usize) ->
Result<Self::SerializeTupleStruct>
{
Ok(SerializeRecord { name, vec: Vec::with_capacity(count) })
Ok(SerializeRecord { r: Value::simple_record(name, count) })
}
fn serialize_tuple_variant(self,
@ -169,7 +168,7 @@ impl serde::Serializer for Serializer {
count: usize) ->
Result<Self::SerializeTupleVariant>
{
Ok(SerializeRecord { name: variant_name, vec: Vec::with_capacity(count) })
Ok(SerializeRecord { r: Value::simple_record(variant_name, count) })
}
fn serialize_map(self, _count: Option<usize>) -> Result<Self::SerializeMap> {
@ -177,7 +176,7 @@ impl serde::Serializer for Serializer {
}
fn serialize_struct(self, name: &'static str, count: usize) -> Result<Self::SerializeStruct> {
Ok(SerializeRecord { name, vec: Vec::with_capacity(count) })
Ok(SerializeRecord { r: Value::simple_record(name, count) })
}
fn serialize_struct_variant(self,
@ -187,7 +186,7 @@ impl serde::Serializer for Serializer {
count: usize) ->
Result<Self::SerializeStructVariant>
{
Ok(SerializeRecord { name: variant_name, vec: Vec::with_capacity(count) })
Ok(SerializeRecord { r: Value::simple_record(variant_name, count) })
}
}
@ -213,12 +212,12 @@ impl serde::ser::SerializeMap for SerializeDictionary {
impl SerializeRecord {
fn push(&mut self, value: IOValue) -> Result<()> {
self.vec.push(value);
self.r.fields_vec_mut().push(value);
Ok(())
}
fn finish(self) -> Result<IOValue> {
Ok(Value::simple_record(self.name, self.vec).wrap())
Ok(self.r.finish().wrap())
}
}

View File

@ -0,0 +1,155 @@
use num::bigint::BigInt;
use num::traits::cast::ToPrimitive;
use num::traits::sign::Signed;
use std::borrow::Cow;
use std::cmp::{Ord, Ordering, PartialOrd};
use std::convert::TryFrom;
use std::convert::TryInto;
use std::fmt;
// Invariant: if I128 can be used, it will be; otherwise, if U128 can
// be used, it will be; otherwise, Big will be used.
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum SignedIntegerRepr {
I128(i128),
U128(u128),
Big(Box<BigInt>),
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct SignedInteger(SignedIntegerRepr);
impl fmt::Display for SignedInteger {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
match self.repr() {
SignedIntegerRepr::I128(i) => i.fmt(f),
SignedIntegerRepr::U128(u) => u.fmt(f),
SignedIntegerRepr::Big(n) => n.fmt(f),
}
}
}
impl Ord for SignedInteger {
fn cmp(&self, other: &Self) -> Ordering {
match self.repr() {
SignedIntegerRepr::I128(i1) => match other.repr() {
SignedIntegerRepr::I128(i2) => i1.cmp(i2),
SignedIntegerRepr::U128(_) => if *i1 < 0 { Ordering::Less } else { Ordering::Greater },
SignedIntegerRepr::Big(n) => if n.is_negative() { Ordering::Less } else { Ordering::Greater },
},
SignedIntegerRepr::U128(u1) => match other.repr() {
SignedIntegerRepr::I128(_) => Ordering::Greater,
SignedIntegerRepr::U128(u2) => u1.cmp(u2),
SignedIntegerRepr::Big(n) => if n.is_positive() { Ordering::Less } else { Ordering::Greater },
},
SignedIntegerRepr::Big(n1) => match other.repr() {
SignedIntegerRepr::I128(_) |
SignedIntegerRepr::U128(_) => if n1.is_negative() { Ordering::Less } else { Ordering::Greater },
SignedIntegerRepr::Big(n2) => n1.cmp(n2),
},
}
}
}
impl PartialOrd for SignedInteger {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl SignedInteger {
pub fn repr(&self) -> &SignedIntegerRepr {
&self.0
}
pub fn is_i(&self) -> bool {
match self.repr() {
SignedIntegerRepr::I128(_) => true,
_ => false,
}
}
pub fn is_u(&self) -> bool {
match self.0 {
SignedIntegerRepr::U128(_) => true,
_ => false,
}
}
pub fn is_big(&self) -> bool {
match self.0 {
SignedIntegerRepr::Big(_) => true,
_ => false,
}
}
}
impl From<i128> for SignedInteger {
fn from(v: i128) -> Self {
SignedInteger(SignedIntegerRepr::I128(v))
}
}
impl From<u128> for SignedInteger {
fn from(v: u128) -> Self {
if let Ok(w) = v.try_into() {
SignedInteger(SignedIntegerRepr::I128(w))
} else {
SignedInteger(SignedIntegerRepr::U128(v))
}
}
}
impl<'a> From<Cow<'a, BigInt>> for SignedInteger {
fn from(v: Cow<'a, BigInt>) -> Self {
if let Some(w) = v.to_i128() {
SignedInteger(SignedIntegerRepr::I128(w))
} else if let Some(w) = v.to_u128() {
SignedInteger(SignedIntegerRepr::U128(w))
} else {
SignedInteger(SignedIntegerRepr::Big(Box::new(v.into_owned())))
}
}
}
impl TryFrom<&SignedInteger> for i128 {
type Error = ();
fn try_from(v: &SignedInteger) -> Result<Self, Self::Error> {
match v.repr() {
SignedIntegerRepr::I128(i) => Ok(*i),
SignedIntegerRepr::U128(_) => Err(()),
SignedIntegerRepr::Big(_) => Err(()),
}
}
}
impl TryFrom<&SignedInteger> for u128 {
type Error = ();
fn try_from(v: &SignedInteger) -> Result<Self, Self::Error> {
match v.repr() {
SignedIntegerRepr::I128(i) => i.to_u128().ok_or(()),
SignedIntegerRepr::U128(u) => Ok(*u),
SignedIntegerRepr::Big(_) => Err(()),
}
}
}
impl<'a> From<&'a SignedInteger> for Cow<'a, BigInt> {
fn from(v: &'a SignedInteger) -> Self {
match v.repr() {
SignedIntegerRepr::I128(i) => Cow::Owned(BigInt::from(*i)),
SignedIntegerRepr::U128(u) => Cow::Owned(BigInt::from(*u)),
SignedIntegerRepr::Big(n) => Cow::Borrowed(n),
}
}
}
impl<'a> From<&'a SignedInteger> for BigInt {
fn from(v: &'a SignedInteger) -> Self {
match v.repr() {
SignedIntegerRepr::I128(i) => BigInt::from(*i),
SignedIntegerRepr::U128(u) => BigInt::from(*u),
SignedIntegerRepr::Big(n) => *n.clone(),
}
}
}

View File

@ -1,7 +1,9 @@
use num::bigint::BigInt;
use num::traits::cast::ToPrimitive;
use std::borrow::Cow;
use std::cmp::Ordering;
use std::convert::TryFrom;
use std::convert::TryInto;
use std::fmt::Debug;
use std::hash::{Hash, Hasher};
use std::ops::Index;
@ -12,6 +14,7 @@ use std::vec::Vec;
pub use std::collections::BTreeSet as Set;
pub use std::collections::BTreeMap as Map;
use super::signed_integer::SignedInteger;
use crate::error::{Error, ExpectedKind, Received};
pub trait Domain: Sized + Debug + Clone + Eq + Hash + Ord {
@ -23,14 +26,9 @@ pub trait Domain: Sized + Debug + Clone + Eq + Hash + Ord {
}
pub trait NestedValue<D: Domain>: Sized + Debug + Clone + Eq + Hash + Ord {
type BoxType: Sized + Debug + Clone + Eq + Hash + Ord;
fn wrap(v: Value<Self, D>) -> Self;
fn wrap_ann(anns: Vec<Self>, v: Value<Self, D>) -> Self;
fn boxwrap(self) -> Self::BoxType;
fn boxunwrap(b: &Self::BoxType) -> &Self;
fn annotations(&self) -> &[Self];
fn value(&self) -> &Value<Self, D>;
fn pieces(self) -> (Vec<Self>, Value<Self, D>);
@ -66,11 +64,11 @@ pub enum Value<N, D> where N: NestedValue<D>, D: Domain {
Boolean(bool),
Float(Float),
Double(Double),
SignedInteger(BigInt),
SignedInteger(SignedInteger),
String(String),
ByteString(Vec<u8>),
Symbol(String),
Record(Record<N, D>),
Record(Record<N>),
Sequence(Vec<N>),
Set(Set<N>),
Dictionary(Map<N, N>),
@ -85,8 +83,43 @@ pub struct Float(pub f32);
#[derive(Clone, Debug)]
pub struct Double(pub f64);
/// A Record `Value`
pub type Record<N, D> = (<N as NestedValue<D>>::BoxType, Vec<N>);
/// A Record `Value` -- INVARIANT: length always non-zero
#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct Record<N>(pub Vec<N>);
impl<N> Record<N> {
pub fn label(&self) -> &N {
&self.0[0]
}
pub fn label_mut(&mut self) -> &mut N {
&mut self.0[0]
}
pub fn arity(&self) -> usize {
self.0.len() - 1
}
pub fn fields(&self) -> &[N] {
&self.0[1..]
}
pub fn fields_mut(&mut self) -> &mut [N] {
&mut self.0[1..]
}
pub fn fields_vec(&self) -> &Vec<N> {
&self.0
}
pub fn fields_vec_mut(&mut self) -> &mut Vec<N> {
&mut self.0
}
pub fn finish<D: Domain>(self) -> Value<N, D> where N: NestedValue<D> {
Value::Record(self)
}
}
impl From<f32> for Float {
fn from(v: f32) -> Self {
@ -185,9 +218,9 @@ impl<N: NestedValue<D>, D: Domain> From<u32> for Value<N, D> { fn from(v: u32) -
impl<N: NestedValue<D>, D: Domain> From<i32> for Value<N, D> { fn from(v: i32) -> Self { Value::from(i128::from(v)) } }
impl<N: NestedValue<D>, D: Domain> From<u64> for Value<N, D> { fn from(v: u64) -> Self { Value::from(i128::from(v)) } }
impl<N: NestedValue<D>, D: Domain> From<i64> for Value<N, D> { fn from(v: i64) -> Self { Value::from(i128::from(v)) } }
impl<N: NestedValue<D>, D: Domain> From<u128> for Value<N, D> { fn from(v: u128) -> Self { Value::SignedInteger(BigInt::from(v)) } }
impl<N: NestedValue<D>, D: Domain> From<i128> for Value<N, D> { fn from(v: i128) -> Self { Value::SignedInteger(BigInt::from(v)) } }
impl<N: NestedValue<D>, D: Domain> From<BigInt> for Value<N, D> { fn from(v: BigInt) -> Self { Value::SignedInteger(v) } }
impl<N: NestedValue<D>, D: Domain> From<u128> for Value<N, D> { fn from(v: u128) -> Self { Value::SignedInteger(SignedInteger::from(v)) } }
impl<N: NestedValue<D>, D: Domain> From<i128> for Value<N, D> { fn from(v: i128) -> Self { Value::SignedInteger(SignedInteger::from(v)) } }
impl<N: NestedValue<D>, D: Domain> From<&BigInt> for Value<N, D> { fn from(v: &BigInt) -> Self { Value::SignedInteger(SignedInteger::from(Cow::Borrowed(v))) } }
impl<N: NestedValue<D>, D: Domain> From<&str> for Value<N, D> { fn from(v: &str) -> Self { Value::String(String::from(v)) } }
impl<N: NestedValue<D>, D: Domain> From<String> for Value<N, D> { fn from(v: String) -> Self { Value::String(v) } }
@ -223,10 +256,10 @@ impl<N: NestedValue<D>, D: Domain> Debug for Value<N, D> {
write!(f, "{}", v)
}
}
Value::Record((ref l, ref fs)) => {
Value::Record(ref r) => {
f.write_str("<")?;
l.fmt(f)?;
for v in fs {
r.label().fmt(f)?;
for v in r.fields() {
f.write_str(" ")?;
v.fmt(f)?;
}
@ -330,73 +363,129 @@ impl<N: NestedValue<D>, D: Domain> Value<N, D> {
self.as_signedinteger().is_some()
}
pub fn as_signedinteger(&self) -> Option<&BigInt> {
if let Value::SignedInteger(ref i) = *self {
Some(i)
pub fn as_signedinteger(&self) -> Option<&SignedInteger> {
if let Value::SignedInteger(ref n) = *self {
Some(n)
} else {
None
}
}
pub fn as_signedinteger_mut(&mut self) -> Option<&mut BigInt> {
if let Value::SignedInteger(ref mut i) = *self {
Some(i)
pub fn as_signedinteger_mut(&mut self) -> Option<&mut SignedInteger> {
if let Value::SignedInteger(ref mut n) = *self {
Some(n)
} else {
None
}
}
pub fn to_signedinteger(&self) -> Result<&BigInt, Error> {
pub fn to_signedinteger(&self) -> Result<&SignedInteger, Error> {
self.as_signedinteger().ok_or_else(|| self.expected(ExpectedKind::SignedInteger))
}
pub fn as_u8(&self) -> Option<u8> { self.as_signedinteger().and_then(|i| i.to_u8()) }
pub fn as_i8(&self) -> Option<i8> { self.as_signedinteger().and_then(|i| i.to_i8()) }
pub fn as_u16(&self) -> Option<u16> { self.as_signedinteger().and_then(|i| i.to_u16()) }
pub fn as_i16(&self) -> Option<i16> { self.as_signedinteger().and_then(|i| i.to_i16()) }
pub fn as_u32(&self) -> Option<u32> { self.as_signedinteger().and_then(|i| i.to_u32()) }
pub fn as_i32(&self) -> Option<i32> { self.as_signedinteger().and_then(|i| i.to_i32()) }
pub fn as_u64(&self) -> Option<u64> { self.as_signedinteger().and_then(|i| i.to_u64()) }
pub fn as_i64(&self) -> Option<i64> { self.as_signedinteger().and_then(|i| i.to_i64()) }
pub fn is_i(&self) -> bool {
self.as_i().is_some()
}
pub fn as_i(&self) -> Option<i128> {
self.as_signedinteger().and_then(|n| n.try_into().ok())
}
pub fn to_i(&self) -> Result<i128, Error> {
self.as_i().ok_or_else(|| self.expected(ExpectedKind::SignedIntegerI128))
}
pub fn is_u(&self) -> bool {
self.as_u().is_some()
}
pub fn as_u(&self) -> Option<u128> {
self.as_signedinteger().and_then(|n| n.try_into().ok())
}
pub fn to_u(&self) -> Result<u128, Error> {
self.as_u().ok_or_else(|| self.expected(ExpectedKind::SignedIntegerU128))
}
pub fn as_u8(&self) -> Option<u8> { self.as_u().and_then(|i| i.to_u8()) }
pub fn as_i8(&self) -> Option<i8> { self.as_i().and_then(|i| i.to_i8()) }
pub fn as_u16(&self) -> Option<u16> { self.as_u().and_then(|i| i.to_u16()) }
pub fn as_i16(&self) -> Option<i16> { self.as_i().and_then(|i| i.to_i16()) }
pub fn as_u32(&self) -> Option<u32> { self.as_u().and_then(|i| i.to_u32()) }
pub fn as_i32(&self) -> Option<i32> { self.as_i().and_then(|i| i.to_i32()) }
pub fn as_u64(&self) -> Option<u64> { self.as_u().and_then(|i| i.to_u64()) }
pub fn as_i64(&self) -> Option<i64> { self.as_i().and_then(|i| i.to_i64()) }
pub fn as_u128(&self) -> Option<u128> { self.as_u().and_then(|i| i.to_u128()) }
pub fn as_i128(&self) -> Option<i128> { self.as_i().and_then(|i| i.to_i128()) }
pub fn to_i8(&self) -> Result<i8, Error> {
let i = self.to_signedinteger()?;
i.to_i8().ok_or_else(|| Error::NumberOutOfRange(i.clone()))
match self.as_i() {
Some(i) => i.to_i8().ok_or_else(|| Error::NumberOutOfRange(BigInt::from(i))),
None => Err(self.expected(ExpectedKind::SignedInteger)),
}
}
pub fn to_u8(&self) -> Result<u8, Error> {
let i = self.to_signedinteger()?;
i.to_u8().ok_or_else(|| Error::NumberOutOfRange(i.clone()))
}
pub fn to_u16(&self) -> Result<u16, Error> {
let i = self.to_signedinteger()?;
i.to_u16().ok_or_else(|| Error::NumberOutOfRange(i.clone()))
match self.as_u() {
Some(i) => i.to_u8().ok_or_else(|| Error::NumberOutOfRange(BigInt::from(i))),
None => Err(self.expected(ExpectedKind::SignedInteger)),
}
}
pub fn to_i16(&self) -> Result<i16, Error> {
let i = self.to_signedinteger()?;
i.to_i16().ok_or_else(|| Error::NumberOutOfRange(i.clone()))
match self.as_i() {
Some(i) => i.to_i16().ok_or_else(|| Error::NumberOutOfRange(BigInt::from(i))),
None => Err(self.expected(ExpectedKind::SignedInteger)),
}
}
pub fn to_u32(&self) -> Result<u32, Error> {
let i = self.to_signedinteger()?;
i.to_u32().ok_or_else(|| Error::NumberOutOfRange(i.clone()))
pub fn to_u16(&self) -> Result<u16, Error> {
match self.as_u() {
Some(i) => i.to_u16().ok_or_else(|| Error::NumberOutOfRange(BigInt::from(i))),
None => Err(self.expected(ExpectedKind::SignedInteger)),
}
}
pub fn to_i32(&self) -> Result<i32, Error> {
let i = self.to_signedinteger()?;
i.to_i32().ok_or_else(|| Error::NumberOutOfRange(i.clone()))
match self.as_i() {
Some(i) => i.to_i32().ok_or_else(|| Error::NumberOutOfRange(BigInt::from(i))),
None => Err(self.expected(ExpectedKind::SignedInteger)),
}
}
pub fn to_u64(&self) -> Result<u64, Error> {
let i = self.to_signedinteger()?;
i.to_u64().ok_or_else(|| Error::NumberOutOfRange(i.clone()))
pub fn to_u32(&self) -> Result<u32, Error> {
match self.as_u() {
Some(i) => i.to_u32().ok_or_else(|| Error::NumberOutOfRange(BigInt::from(i))),
None => Err(self.expected(ExpectedKind::SignedInteger)),
}
}
pub fn to_i64(&self) -> Result<i64, Error> {
let i = self.to_signedinteger()?;
i.to_i64().ok_or_else(|| Error::NumberOutOfRange(i.clone()))
match self.as_i() {
Some(i) => i.to_i64().ok_or_else(|| Error::NumberOutOfRange(BigInt::from(i))),
None => Err(self.expected(ExpectedKind::SignedInteger)),
}
}
pub fn to_u64(&self) -> Result<u64, Error> {
match self.as_u() {
Some(i) => i.to_u64().ok_or_else(|| Error::NumberOutOfRange(BigInt::from(i))),
None => Err(self.expected(ExpectedKind::SignedInteger)),
}
}
pub fn to_i128(&self) -> Result<i128, Error> {
match self.as_i() {
Some(i) => i.to_i128().ok_or_else(|| Error::NumberOutOfRange(BigInt::from(i))),
None => Err(self.expected(ExpectedKind::SignedInteger)),
}
}
pub fn to_u128(&self) -> Result<u128, Error> {
match self.as_u() {
Some(i) => i.to_u128().ok_or_else(|| Error::NumberOutOfRange(BigInt::from(i))),
None => Err(self.expected(ExpectedKind::SignedInteger)),
}
}
pub fn to_char(&self) -> Result<char, Error> {
@ -481,18 +570,24 @@ impl<N: NestedValue<D>, D: Domain> Value<N, D> {
self.as_symbol().ok_or_else(|| self.expected(ExpectedKind::Symbol))
}
pub fn record(label: N, fields: Vec<N>) -> Value<N, D> {
Value::Record((label.boxwrap(), fields))
pub fn record(label: N, expected_arity: usize) -> Record<N> {
let mut v = Vec::with_capacity(expected_arity + 1);
v.push(label);
Record(v)
}
pub fn is_record(&self) -> bool {
self.as_record(None).is_some()
if let Value::Record(_) = *self {
true
} else {
false
}
}
pub fn as_record(&self, arity: Option<usize>) -> Option<&Record<N, D>> {
pub fn as_record(&self, arity: Option<usize>) -> Option<&Record<N>> {
if let Value::Record(ref r) = *self {
match arity {
Some(expected) if r.1.len() == expected => Some(r),
Some(expected) if r.arity() == expected => Some(r),
Some(_other) => None,
None => Some(r)
}
@ -501,10 +596,10 @@ impl<N: NestedValue<D>, D: Domain> Value<N, D> {
}
}
pub fn as_record_mut(&mut self, arity: Option<usize>) -> Option<&mut Record<N, D>> {
pub fn as_record_mut(&mut self, arity: Option<usize>) -> Option<&mut Record<N>> {
if let Value::Record(ref mut r) = *self {
match arity {
Some(expected) if r.1.len() == expected => Some(r),
Some(expected) if r.arity() == expected => Some(r),
Some(_other) => None,
None => Some(r)
}
@ -513,32 +608,42 @@ impl<N: NestedValue<D>, D: Domain> Value<N, D> {
}
}
pub fn to_record(&self, arity: Option<usize>) -> Result<&Record<N, D>, Error> {
pub fn to_record(&self, arity: Option<usize>) -> Result<&Record<N>, Error> {
self.as_record(arity).ok_or_else(|| self.expected(ExpectedKind::Record(arity)))
}
pub fn simple_record(label: &str, fields: Vec<N>) -> Value<N, D> {
Value::record(Value::symbol(label).wrap(), fields)
pub fn simple_record(label: &str, expected_arity: usize) -> Record<N> {
Self::record(Value::symbol(label).wrap(), expected_arity)
}
pub fn simple_record0(label: &str) -> Value<N, D> {
Self::simple_record(label, 0).finish()
}
pub fn simple_record1(label: &str, field: N) -> Value<N, D> {
let mut r = Self::simple_record(label, 1);
r.fields_vec_mut().push(field);
r.finish()
}
pub fn is_simple_record(&self, label: &str, arity: Option<usize>) -> bool {
self.as_simple_record(label, arity).is_some()
}
pub fn as_simple_record(&self, label: &str, arity: Option<usize>) -> Option<&Vec<N>> {
self.as_record(arity).and_then(|(lp,fs)| {
match N::boxunwrap(lp).value() {
Value::Symbol(ref s) if s == label => Some(fs),
pub fn as_simple_record(&self, label: &str, arity: Option<usize>) -> Option<&[N]> {
self.as_record(arity).and_then(|r| {
match r.label().value() {
Value::Symbol(ref s) if s == label => Some(r.fields()),
_ => None
}
})
}
pub fn to_simple_record(&self, label: &'static str, arity: Option<usize>) ->
Result<&Vec<N>, Error>
pub fn to_simple_record(&self, label: &str, arity: Option<usize>) ->
Result<&[N], Error>
{
self.as_simple_record(label, arity)
.ok_or_else(|| self.expected(ExpectedKind::SimpleRecord(label, arity)))
.ok_or_else(|| self.expected(ExpectedKind::SimpleRecord(label.to_owned(), arity)))
}
pub fn to_option(&self) -> Result<Option<&N>, Error> {
@ -631,13 +736,12 @@ impl<N: NestedValue<D>, D: Domain> Value<N, D> {
Value::Boolean(b) => Value::Boolean(*b),
Value::Float(f) => Value::Float(f.clone()),
Value::Double(d) => Value::Double(d.clone()),
Value::SignedInteger(i) => Value::SignedInteger(i.clone()),
Value::SignedInteger(ref n) => Value::SignedInteger(n.clone()),
Value::String(ref s) => Value::String(s.clone()),
Value::ByteString(ref v) => Value::ByteString(v.clone()),
Value::Symbol(ref v) => Value::Symbol(v.clone()),
Value::Record((ref l, ref fs)) =>
Value::Record((N::boxunwrap(l).copy_via::<M,E,F>(f).boxwrap(),
fs.iter().map(|a| a.copy_via(f)).collect())),
Value::Record(ref r) =>
Value::Record(Record(r.fields_vec().iter().map(|a| a.copy_via(f)).collect())),
Value::Sequence(ref v) => Value::Sequence(v.iter().map(|a| a.copy_via(f)).collect()),
Value::Set(ref v) => Value::Set(v.iter().map(|a| a.copy_via(f)).collect()),
Value::Dictionary(ref v) =>
@ -745,8 +849,6 @@ impl<D: Domain> PlainValue<D> {
}
impl<D: Domain> NestedValue<D> for PlainValue<D> {
type BoxType = Box<Self>;
fn wrap(v: Value<Self, D>) -> Self {
Self::wrap_ann(Vec::new(), v)
}
@ -755,14 +857,6 @@ impl<D: Domain> NestedValue<D> for PlainValue<D> {
PlainValue(AnnotatedValue(anns, v))
}
fn boxwrap(self) -> Self::BoxType {
Box::new(self)
}
fn boxunwrap(b: &Self::BoxType) -> &Self {
&**b
}
fn annotations(&self) -> &[Self] {
&(self.0).0
}
@ -807,8 +901,6 @@ use std::rc::Rc;
pub struct RcValue<D: Domain>(Rc<AnnotatedValue<RcValue<D>, D>>);
impl<D: Domain> NestedValue<D> for RcValue<D> {
type BoxType = Self;
fn wrap(v: Value<Self, D>) -> Self {
Self::wrap_ann(Vec::new(), v)
}
@ -817,14 +909,6 @@ impl<D: Domain> NestedValue<D> for RcValue<D> {
RcValue(Rc::new(AnnotatedValue(anns, v)))
}
fn boxwrap(self) -> Self::BoxType {
self
}
fn boxunwrap(b: &Self::BoxType) -> &Self {
b
}
fn annotations(&self) -> &[Self] {
&(self.0).0
}
@ -871,8 +955,6 @@ use std::sync::Arc;
pub struct ArcValue<D: Domain>(Arc<AnnotatedValue<ArcValue<D>, D>>);
impl<D: Domain> NestedValue<D> for ArcValue<D> {
type BoxType = Self;
fn wrap(v: Value<Self, D>) -> Self {
Self::wrap_ann(Vec::new(), v)
}
@ -881,14 +963,6 @@ impl<D: Domain> NestedValue<D> for ArcValue<D> {
ArcValue(Arc::new(AnnotatedValue(anns, v)))
}
fn boxwrap(self) -> Self::BoxType {
self
}
fn boxunwrap(b: &Self::BoxType) -> &Self {
b
}
fn annotations(&self) -> &[Self] {
&(self.0).0
}
@ -944,8 +1018,6 @@ lazy_static! {
}
impl NestedValue<NullDomain> for IOValue {
type BoxType = Self;
fn wrap(v: Value<Self, NullDomain>) -> Self {
Self::wrap_ann(Vec::new(), v)
}
@ -954,14 +1026,6 @@ impl NestedValue<NullDomain> for IOValue {
IOValue(Arc::new(AnnotatedValue(anns, v)))
}
fn boxwrap(self) -> Self::BoxType {
self
}
fn boxunwrap(b: &Self::BoxType) -> &Self {
b
}
fn annotations(&self) -> &[Self] {
&(self.0).0
}

View File

@ -1,3 +1,4 @@
use num;
use num::bigint::BigInt;
use num::cast::ToPrimitive;
use std::convert::TryInto;
@ -23,6 +24,8 @@ pub trait Writer {
fn write_u32(&mut self, v: u32) -> Result;
fn write_i64(&mut self, v: i64) -> Result;
fn write_u64(&mut self, v: u64) -> Result;
fn write_i128(&mut self, v: i128) -> Result;
fn write_u128(&mut self, v: u128) -> Result;
fn write_int(&mut self, v: &BigInt) -> Result;
fn write_string(&mut self, v: &str) -> Result;
@ -80,6 +83,13 @@ pub fn write_atom<W: std::io::Write>(w: &mut W, minor: AtomMinor, bs: &[u8]) ->
w.write_all(bs)
}
macro_rules! fits_in_bytes {
($v:ident, $limit:literal) => ({
let bits = $limit * 8 - 1;
$v >= -(2 << bits) && $v < (2 << bits)
})
}
impl<W: std::io::Write> Writer for W {
fn write_annotation_prefix(&mut self) -> Result {
write_header(self, Op::Misc(0), 5)
@ -126,7 +136,7 @@ impl<W: std::io::Write> Writer for W {
fn write_i32(&mut self, v: i32) -> Result {
if let Ok(w) = v.try_into() { return self.write_i16(w) }
if v >= -(2 << 23) && v < (2 << 23) {
if fits_in_bytes!(v, 3) {
return write_atom(self, AtomMinor::SignedInteger, &[(v >> 16) as u8,
(v >> 8) as u8,
(v & 255) as u8]);
@ -148,14 +158,14 @@ impl<W: std::io::Write> Writer for W {
fn write_i64(&mut self, v: i64) -> Result {
if let Ok(w) = v.try_into() { return self.write_i32(w) }
if v >= -(2 << 39) && v < (2 << 39) {
if fits_in_bytes!(v, 5) {
return write_atom(self, AtomMinor::SignedInteger, &[(v >> 32) as u8,
(v >> 24) as u8,
(v >> 16) as u8,
(v >> 8) as u8,
(v & 255) as u8]);
}
if v >= -(2 << 47) && v < (2 << 47) {
if fits_in_bytes!(v, 6) {
return write_atom(self, AtomMinor::SignedInteger, &[(v >> 40) as u8,
(v >> 32) as u8,
(v >> 24) as u8,
@ -163,7 +173,7 @@ impl<W: std::io::Write> Writer for W {
(v >> 8) as u8,
(v & 255) as u8]);
}
if v >= -(2 << 55) && v < (2 << 55) {
if fits_in_bytes!(v, 7) {
return write_atom(self, AtomMinor::SignedInteger, &[(v >> 48) as u8,
(v >> 40) as u8,
(v >> 32) as u8,
@ -195,6 +205,27 @@ impl<W: std::io::Write> Writer for W {
(v & 255) as u8]);
}
fn write_i128(&mut self, v: i128) -> Result {
if let Ok(w) = v.try_into() { return self.write_i64(w) }
let bs: [u8; 16] = v.to_be_bytes();
if fits_in_bytes!(v, 9) { return write_atom(self, AtomMinor::SignedInteger, &bs[7..]); }
if fits_in_bytes!(v, 10) { return write_atom(self, AtomMinor::SignedInteger, &bs[6..]); }
if fits_in_bytes!(v, 11) { return write_atom(self, AtomMinor::SignedInteger, &bs[5..]); }
if fits_in_bytes!(v, 12) { return write_atom(self, AtomMinor::SignedInteger, &bs[4..]); }
if fits_in_bytes!(v, 13) { return write_atom(self, AtomMinor::SignedInteger, &bs[3..]); }
if fits_in_bytes!(v, 14) { return write_atom(self, AtomMinor::SignedInteger, &bs[2..]); }
if fits_in_bytes!(v, 15) { return write_atom(self, AtomMinor::SignedInteger, &bs[1..]); }
return write_atom(self, AtomMinor::SignedInteger, &bs);
}
fn write_u128(&mut self, v: u128) -> Result {
if let Ok(w) = v.try_into() { return self.write_i128(w) }
let bs: [u8; 16] = v.to_be_bytes();
write_header(self, Op::Atom(AtomMinor::SignedInteger), bs.len() + 1)?;
self.write_all(&[0])?;
self.write_all(&bs)
}
fn write_int(&mut self, v: &BigInt) -> Result {
match v.to_i8() {
Some(n) => self.write_i8(n),