From bffbeb2f6ee27cb937a36a3060bb90e3317cecb3 Mon Sep 17 00:00:00 2001 From: Tony Garnock-Jones Date: Mon, 15 Jun 2020 12:48:53 +0200 Subject: [PATCH] Smaller Record; also, use u128/i128 when possible --- implementations/rust/src/error.rs | 4 +- implementations/rust/src/lib.rs | 19 +- implementations/rust/src/value/de.rs | 32 +- implementations/rust/src/value/encoder.rs | 15 +- implementations/rust/src/value/mod.rs | 1 + implementations/rust/src/value/reader.rs | 176 +++++------ implementations/rust/src/value/ser.rs | 35 ++- .../rust/src/value/signed_integer.rs | 155 ++++++++++ implementations/rust/src/value/value.rs | 288 +++++++++++------- implementations/rust/src/value/writer.rs | 39 ++- 10 files changed, 512 insertions(+), 252 deletions(-) create mode 100644 implementations/rust/src/value/signed_integer.rs diff --git a/implementations/rust/src/error.rs b/implementations/rust/src/error.rs index 2a5adf3..bf74a06 100644 --- a/implementations/rust/src/error.rs +++ b/implementations/rust/src/error.rs @@ -27,13 +27,15 @@ pub enum ExpectedKind { Float, Double, + SignedIntegerI128, + SignedIntegerU128, SignedInteger, String, ByteString, Symbol, Record(Option), - SimpleRecord(&'static str, Option), + SimpleRecord(String, Option), Sequence, Set, Dictionary, diff --git a/implementations/rust/src/lib.rs b/implementations/rust/src/lib.rs index 83fdc52..5aeb109 100644 --- a/implementations/rust/src/lib.rs +++ b/implementations/rust/src/lib.rs @@ -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, 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 }); diff --git a/implementations/rust/src/value/de.rs b/implementations/rust/src/value/de.rs index 239f463..d398e78 100644 --- a/implementations/rust/src/value/de.rs +++ b/implementations/rust/src/value/de.rs @@ -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(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(self, seed: T) -> Result 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(self, _len: usize, visitor: V) -> Result 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(self, fields: &'static [&'static str], visitor: V) -> Result 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())) } } diff --git a/implementations/rust/src/value/encoder.rs b/implementations/rust/src/value/encoder.rs index 03eab97..44916fc 100644 --- a/implementations/rust/src/value/encoder.rs +++ b/implementations/rust/src/value/encoder.rs @@ -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) => { diff --git a/implementations/rust/src/value/mod.rs b/implementations/rust/src/value/mod.rs index 69cd27b..4bc3a02 100644 --- a/implementations/rust/src/value/mod.rs +++ b/implementations/rust/src/value/mod.rs @@ -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; diff --git a/implementations/rust/src/value/reader.rs b/implementations/rust/src/value/reader.rs index ec26341..67acfc9 100644 --- a/implementations/rust/src/value/reader.rs +++ b/implementations/rust/src/value/reader.rs @@ -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 = std::result::Result; @@ -138,6 +139,8 @@ pub trait Reader<'de> { fn next_u32(&mut self) -> ReaderResult { self.demand_next(false)?.value().to_u32() } fn next_i64(&mut self) -> ReaderResult { self.demand_next(false)?.value().to_i64() } fn next_u64(&mut self) -> ReaderResult { self.demand_next(false)?.value().to_u64() } + fn next_i128(&mut self) -> ReaderResult { self.demand_next(false)?.value().to_i128() } + fn next_u128(&mut self) -> ReaderResult { self.demand_next(false)?.value().to_u128() } fn next_float(&mut self) -> ReaderResult { self.demand_next(false)?.value().to_float() } fn next_double(&mut self) -> ReaderResult { self.demand_next(false)?.value().to_double() } fn next_char(&mut self) -> ReaderResult { 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) -> + fn open_simple_record(&mut self, name: &str, arity: Option) -> ReaderResult 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: 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 { + 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(&mut self, f: F) -> ReaderResult where - F: FnOnce(u64) -> Option + F: FnOnce(u128) -> Option { 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(&mut self, f: F) -> ReaderResult where - F: FnOnce(i64) -> Option + F: FnOnce(i128) -> Option { 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 { self.next_signed(|n| n.to_i8()) } - fn next_i16(&mut self) -> ReaderResult { self.next_signed(|n| n.to_i16()) } - fn next_i32(&mut self) -> ReaderResult { self.next_signed(|n| n.to_i32()) } - fn next_i64(&mut self) -> ReaderResult { self.next_signed(|n| Some(n)) } + fn next_i8(&mut self) -> ReaderResult { self.next_signed(|n| n.to_i8()) } + fn next_i16(&mut self) -> ReaderResult { self.next_signed(|n| n.to_i16()) } + fn next_i32(&mut self) -> ReaderResult { self.next_signed(|n| n.to_i32()) } + fn next_i64(&mut self) -> ReaderResult { self.next_signed(|n| n.to_i64()) } + fn next_i128(&mut self) -> ReaderResult { self.next_signed(|n| n.to_i128()) } - fn next_u8(&mut self) -> ReaderResult { self.next_unsigned(|n| n.to_u8()) } - fn next_u16(&mut self) -> ReaderResult { self.next_unsigned(|n| n.to_u16()) } - fn next_u32(&mut self) -> ReaderResult { self.next_unsigned(|n| n.to_u32()) } - fn next_u64(&mut self) -> ReaderResult { self.next_unsigned(|n| Some(n)) } + fn next_u8(&mut self) -> ReaderResult { self.next_unsigned(|n| n.to_u8()) } + fn next_u16(&mut self) -> ReaderResult { self.next_unsigned(|n| n.to_u16()) } + fn next_u32(&mut self) -> ReaderResult { self.next_unsigned(|n| n.to_u32()) } + fn next_u64(&mut self) -> ReaderResult { self.next_unsigned(|n| n.to_u64()) } + fn next_u128(&mut self) -> ReaderResult { self.next_unsigned(|n| n.to_u128()) } fn next_float(&mut self) -> ReaderResult { 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> { match cow { Cow::Borrowed(bs) => @@ -808,7 +815,7 @@ pub fn decodestr<'de>(cow: Cow<'de, [u8]>) -> IOResult> { pub fn decodebinary<'de>(minor: AtomMinor, bs: Cow<'de, [u8]>) -> IOResult { 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>>>( IOResult { 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::>>()?; - Ok(Value::record(label, fields).wrap()) - } + CompoundMinor::Record => { + let vs = iter.map(|r| r.map(|c| c.into_owned())).collect::>>()?; + 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::>>()?; Ok(Value::Sequence(vs).wrap()) diff --git a/implementations/rust/src/value/ser.rs b/implementations/rust/src/value/ser.rs index de4f8ee..215b56e 100644 --- a/implementations/rust/src/value/ser.rs +++ b/implementations/rust/src/value/ser.rs @@ -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, + r: Record, } pub struct SerializeSequence { @@ -89,7 +88,7 @@ impl serde::Serializer for Serializer { } fn serialize_char(self, v: char) -> Result { - 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 { @@ -101,19 +100,19 @@ impl serde::Serializer for Serializer { } fn serialize_none(self) -> Result { - Ok(Value::simple_record("None", vec![]).wrap()) + Ok(Value::simple_record0("None").wrap()) } fn serialize_some(self, v: &T) -> Result 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 { - Ok(Value::simple_record("tuple", vec![]).wrap()) + Ok(Value::simple_record0("tuple").wrap()) } fn serialize_unit_struct(self, name: &'static str) -> Result { - 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 { - Ok(Value::simple_record(variant_name, vec![]).wrap()) + Ok(Value::simple_record0(variant_name).wrap()) } fn serialize_newtype_struct(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 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) -> Result { @@ -153,13 +152,13 @@ impl serde::Serializer for Serializer { } fn serialize_tuple(self, count: usize) -> Result { - 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 { - 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 { - 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) -> Result { @@ -177,7 +176,7 @@ impl serde::Serializer for Serializer { } fn serialize_struct(self, name: &'static str, count: usize) -> Result { - 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 { - 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 { - Ok(Value::simple_record(self.name, self.vec).wrap()) + Ok(self.r.finish().wrap()) } } diff --git a/implementations/rust/src/value/signed_integer.rs b/implementations/rust/src/value/signed_integer.rs new file mode 100644 index 0000000..d4d3026 --- /dev/null +++ b/implementations/rust/src/value/signed_integer.rs @@ -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), +} + +#[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 { + 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 for SignedInteger { + fn from(v: i128) -> Self { + SignedInteger(SignedIntegerRepr::I128(v)) + } +} + +impl From 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> 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 { + 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 { + 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(), + } + } +} diff --git a/implementations/rust/src/value/value.rs b/implementations/rust/src/value/value.rs index a373b78..5df7630 100644 --- a/implementations/rust/src/value/value.rs +++ b/implementations/rust/src/value/value.rs @@ -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: Sized + Debug + Clone + Eq + Hash + Ord { - type BoxType: Sized + Debug + Clone + Eq + Hash + Ord; - fn wrap(v: Value) -> Self; fn wrap_ann(anns: Vec, v: Value) -> Self; - fn boxwrap(self) -> Self::BoxType; - fn boxunwrap(b: &Self::BoxType) -> &Self; - fn annotations(&self) -> &[Self]; fn value(&self) -> &Value; fn pieces(self) -> (Vec, Value); @@ -66,11 +64,11 @@ pub enum Value where N: NestedValue, D: Domain { Boolean(bool), Float(Float), Double(Double), - SignedInteger(BigInt), + SignedInteger(SignedInteger), String(String), ByteString(Vec), Symbol(String), - Record(Record), + Record(Record), Sequence(Vec), Set(Set), Dictionary(Map), @@ -85,8 +83,43 @@ pub struct Float(pub f32); #[derive(Clone, Debug)] pub struct Double(pub f64); -/// A Record `Value` -pub type Record = (>::BoxType, Vec); +/// A Record `Value` -- INVARIANT: length always non-zero +#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub struct Record(pub Vec); + +impl Record { + 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 { + &self.0 + } + + pub fn fields_vec_mut(&mut self) -> &mut Vec { + &mut self.0 + } + + pub fn finish(self) -> Value where N: NestedValue { + Value::Record(self) + } +} impl From for Float { fn from(v: f32) -> Self { @@ -185,9 +218,9 @@ impl, D: Domain> From for Value { fn from(v: u32) - impl, D: Domain> From for Value { fn from(v: i32) -> Self { Value::from(i128::from(v)) } } impl, D: Domain> From for Value { fn from(v: u64) -> Self { Value::from(i128::from(v)) } } impl, D: Domain> From for Value { fn from(v: i64) -> Self { Value::from(i128::from(v)) } } -impl, D: Domain> From for Value { fn from(v: u128) -> Self { Value::SignedInteger(BigInt::from(v)) } } -impl, D: Domain> From for Value { fn from(v: i128) -> Self { Value::SignedInteger(BigInt::from(v)) } } -impl, D: Domain> From for Value { fn from(v: BigInt) -> Self { Value::SignedInteger(v) } } +impl, D: Domain> From for Value { fn from(v: u128) -> Self { Value::SignedInteger(SignedInteger::from(v)) } } +impl, D: Domain> From for Value { fn from(v: i128) -> Self { Value::SignedInteger(SignedInteger::from(v)) } } +impl, D: Domain> From<&BigInt> for Value { fn from(v: &BigInt) -> Self { Value::SignedInteger(SignedInteger::from(Cow::Borrowed(v))) } } impl, D: Domain> From<&str> for Value { fn from(v: &str) -> Self { Value::String(String::from(v)) } } impl, D: Domain> From for Value { fn from(v: String) -> Self { Value::String(v) } } @@ -223,10 +256,10 @@ impl, D: Domain> Debug for Value { 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, D: Domain> Value { 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 { self.as_signedinteger().and_then(|i| i.to_u8()) } - pub fn as_i8(&self) -> Option { self.as_signedinteger().and_then(|i| i.to_i8()) } - pub fn as_u16(&self) -> Option { self.as_signedinteger().and_then(|i| i.to_u16()) } - pub fn as_i16(&self) -> Option { self.as_signedinteger().and_then(|i| i.to_i16()) } - pub fn as_u32(&self) -> Option { self.as_signedinteger().and_then(|i| i.to_u32()) } - pub fn as_i32(&self) -> Option { self.as_signedinteger().and_then(|i| i.to_i32()) } - pub fn as_u64(&self) -> Option { self.as_signedinteger().and_then(|i| i.to_u64()) } - pub fn as_i64(&self) -> Option { 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 { + self.as_signedinteger().and_then(|n| n.try_into().ok()) + } + + pub fn to_i(&self) -> Result { + 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 { + self.as_signedinteger().and_then(|n| n.try_into().ok()) + } + + pub fn to_u(&self) -> Result { + self.as_u().ok_or_else(|| self.expected(ExpectedKind::SignedIntegerU128)) + } + + pub fn as_u8(&self) -> Option { self.as_u().and_then(|i| i.to_u8()) } + pub fn as_i8(&self) -> Option { self.as_i().and_then(|i| i.to_i8()) } + pub fn as_u16(&self) -> Option { self.as_u().and_then(|i| i.to_u16()) } + pub fn as_i16(&self) -> Option { self.as_i().and_then(|i| i.to_i16()) } + pub fn as_u32(&self) -> Option { self.as_u().and_then(|i| i.to_u32()) } + pub fn as_i32(&self) -> Option { self.as_i().and_then(|i| i.to_i32()) } + pub fn as_u64(&self) -> Option { self.as_u().and_then(|i| i.to_u64()) } + pub fn as_i64(&self) -> Option { self.as_i().and_then(|i| i.to_i64()) } + pub fn as_u128(&self) -> Option { self.as_u().and_then(|i| i.to_u128()) } + pub fn as_i128(&self) -> Option { self.as_i().and_then(|i| i.to_i128()) } pub fn to_i8(&self) -> Result { - 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 { - let i = self.to_signedinteger()?; - i.to_u8().ok_or_else(|| Error::NumberOutOfRange(i.clone())) - } - - pub fn to_u16(&self) -> Result { - 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 { - 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 { - let i = self.to_signedinteger()?; - i.to_u32().ok_or_else(|| Error::NumberOutOfRange(i.clone())) + pub fn to_u16(&self) -> Result { + 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 { - 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 { - let i = self.to_signedinteger()?; - i.to_u64().ok_or_else(|| Error::NumberOutOfRange(i.clone())) + pub fn to_u32(&self) -> Result { + 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 { - 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 { + 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 { + 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 { + 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 { @@ -481,18 +570,24 @@ impl, D: Domain> Value { self.as_symbol().ok_or_else(|| self.expected(ExpectedKind::Symbol)) } - pub fn record(label: N, fields: Vec) -> Value { - Value::Record((label.boxwrap(), fields)) + pub fn record(label: N, expected_arity: usize) -> Record { + 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) -> Option<&Record> { + pub fn as_record(&self, arity: Option) -> Option<&Record> { 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, D: Domain> Value { } } - pub fn as_record_mut(&mut self, arity: Option) -> Option<&mut Record> { + pub fn as_record_mut(&mut self, arity: Option) -> Option<&mut Record> { 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, D: Domain> Value { } } - pub fn to_record(&self, arity: Option) -> Result<&Record, Error> { + pub fn to_record(&self, arity: Option) -> Result<&Record, Error> { self.as_record(arity).ok_or_else(|| self.expected(ExpectedKind::Record(arity))) } - pub fn simple_record(label: &str, fields: Vec) -> Value { - Value::record(Value::symbol(label).wrap(), fields) + pub fn simple_record(label: &str, expected_arity: usize) -> Record { + Self::record(Value::symbol(label).wrap(), expected_arity) + } + + pub fn simple_record0(label: &str) -> Value { + Self::simple_record(label, 0).finish() + } + + pub fn simple_record1(label: &str, field: N) -> Value { + 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) -> bool { self.as_simple_record(label, arity).is_some() } - pub fn as_simple_record(&self, label: &str, arity: Option) -> Option<&Vec> { - 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) -> 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) -> - Result<&Vec, Error> + pub fn to_simple_record(&self, label: &str, arity: Option) -> + 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, Error> { @@ -631,13 +736,12 @@ impl, D: Domain> Value { 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::(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 PlainValue { } impl NestedValue for PlainValue { - type BoxType = Box; - fn wrap(v: Value) -> Self { Self::wrap_ann(Vec::new(), v) } @@ -755,14 +857,6 @@ impl NestedValue for PlainValue { 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(Rc, D>>); impl NestedValue for RcValue { - type BoxType = Self; - fn wrap(v: Value) -> Self { Self::wrap_ann(Vec::new(), v) } @@ -817,14 +909,6 @@ impl NestedValue for RcValue { 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(Arc, D>>); impl NestedValue for ArcValue { - type BoxType = Self; - fn wrap(v: Value) -> Self { Self::wrap_ann(Vec::new(), v) } @@ -881,14 +963,6 @@ impl NestedValue for ArcValue { 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 for IOValue { - type BoxType = Self; - fn wrap(v: Value) -> Self { Self::wrap_ann(Vec::new(), v) } @@ -954,14 +1026,6 @@ impl NestedValue 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 } diff --git a/implementations/rust/src/value/writer.rs b/implementations/rust/src/value/writer.rs index 95515da..22b685b 100644 --- a/implementations/rust/src/value/writer.rs +++ b/implementations/rust/src/value/writer.rs @@ -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: &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 Writer for W { fn write_annotation_prefix(&mut self) -> Result { write_header(self, Op::Misc(0), 5) @@ -126,7 +136,7 @@ impl 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 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 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 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),