diff --git a/implementations/rust/.gitignore b/implementations/rust/.gitignore index 03314f7..1e7caa9 100644 --- a/implementations/rust/.gitignore +++ b/implementations/rust/.gitignore @@ -1 +1,2 @@ Cargo.lock +target/ diff --git a/implementations/rust/Makefile b/implementations/rust/Makefile index 0b65061..b7d0767 100644 --- a/implementations/rust/Makefile +++ b/implementations/rust/Makefile @@ -1,2 +1,6 @@ +# cargo install cargo-watch +watch: + cargo watch -x check -x 'test -- --nocapture' + inotifytest: inotifytest sh -c 'reset; cargo build && RUST_BACKTRACE=1 cargo test -- --nocapture' diff --git a/implementations/rust/src/lib.rs b/implementations/rust/src/lib.rs index b74fc75..c336852 100644 --- a/implementations/rust/src/lib.rs +++ b/implementations/rust/src/lib.rs @@ -94,3 +94,81 @@ mod ieee754_section_5_10_total_order_tests { #[test] fn case64_c3_5() { assert_eq!(d(-1e32).cmp(&d(-1e32)), Equal) } #[test] fn case64_c3_6() { assert_eq!(d(1e33).cmp(&d(1e33)), Equal) } } + +#[cfg(test)] +mod value_tests { + use crate::value::value::Value; + use num::bigint::BigInt; + + #[test] fn boolean_mut() { + let mut b = Value::Boolean(true); + assert!(b.is_boolean()); + *(b.as_boolean_mut().unwrap()) = false; + assert_eq!(b, Value::Boolean(false)); + } + + #[test] fn float_mut() { + let mut f = Value::from(1.0f32); + assert!(f.is_float()); + *(f.as_float_mut().unwrap()) = 123.45; + assert_eq!(f, Value::from(123.45f32)); + assert_eq!(f.as_float().unwrap(), 123.45f32); + } + + #[test] fn double_mut() { + let mut f = Value::from(1.0); + assert!(f.is_double()); + *(f.as_double_mut().unwrap()) = 123.45; + assert_eq!(f, Value::from(123.45)); + assert_eq!(f.as_double().unwrap(), 123.45); + } + + #[test] fn signedinteger_mut() { + let mut i = Value::from(123); + assert!(i.is_signedinteger()); + *(i.as_signedinteger_mut().unwrap()) = BigInt::from(234); + assert_eq!(i, Value::from(234)); + + use num::traits::cast::ToPrimitive; + assert_eq!(i.as_signedinteger().unwrap().to_i64().unwrap(), 234); + } + + #[test] fn string_mut() { + let mut s = Value::from("hello, world!"); + assert!(s.is_string()); + s.as_string_mut().unwrap().replace_range(7..12, "there"); + assert_eq!(s, Value::from("hello, there!")); + } + + #[test] fn bytes_mut() { + let mut b = Value::from(&b"hello, world!"[..]); + assert!(b.is_bytestring()); + b.as_bytestring_mut().unwrap().splice(7..12, Vec::from(&b"there"[..])); + assert_eq!(b, Value::from(&b"hello, there!"[..])); + } + + #[test] fn symbol_mut() { + let mut s = Value::symbol("abcd"); + assert!(s.is_symbol()); + s.as_symbol_mut().unwrap().replace_range(..2, "AB"); + assert_eq!(s, Value::symbol("ABcd")); + } + + #[test] fn record_mut() { + let says = Value::symbol("says").wrap().rc(); + let mut r = Value::record(&says, vec![Value::from("Tony").wrap(), Value::from("Hello!").wrap()]); + r.as_record_mut().unwrap().1[0] = Value::from("Alice").wrap(); + assert_eq!(r, Value::record(&says, vec![Value::from("Alice").wrap(), Value::from("Hello!").wrap()])); + } + + #[test] fn sequence_mut() { + let mut s = Value::Sequence(vec![Value::from(1).wrap(), + Value::from(2).wrap(), + Value::from(3).wrap()]); + let r = Value::Sequence(vec![Value::from(1).wrap(), + Value::from(99).wrap(), + Value::from(3).wrap()]); + s.as_sequence_mut().unwrap()[1] = Value::from(99).wrap(); + assert_eq!(r, s); + } +} diff --git a/implementations/rust/src/value/value.rs b/implementations/rust/src/value/value.rs index 4b6e94b..54bdc07 100644 --- a/implementations/rust/src/value/value.rs +++ b/implementations/rust/src/value/value.rs @@ -1,28 +1,46 @@ use std::hash::{Hash,Hasher}; use std::cmp::{Ordering}; use num::bigint::BigInt; +use std::rc::Rc; +use std::vec::Vec; +use std::string::String; +use std::collections::BTreeSet; +use std::collections::BTreeMap; +use std::ops::Index; +use std::ops::IndexMut; +/// The `Value`s from the specification. #[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] pub enum Value { Boolean(bool), Float(Float), Double(Double), SignedInteger(BigInt), - String(std::string::String), - ByteString(std::vec::Vec), - Symbol(std::string::String), - Record(std::rc::Rc, std::vec::Vec), - Sequence(std::vec::Vec), - Set(std::collections::BTreeSet), - Dictionary(std::collections::BTreeMap), + String(String), + ByteString(Vec), + Symbol(String), + Record(Record), + Sequence(Vec), + Set(BTreeSet), + Dictionary(BTreeMap), } +/// An possibly-annotated Value, with annotations (themselves +/// possibly-annotated) in order of appearance. +#[derive(Clone, Debug)] +pub struct AValue(Vec, Value); + +/// Single-precision IEEE 754 Value #[derive(Clone, Debug)] pub struct Float(f32); +/// Double-precision IEEE 754 Value #[derive(Clone, Debug)] pub struct Double(f64); +/// A Record `Value` +pub type Record = (Rc, Vec); + impl From for Float { fn from(v: f32) -> Self { Float(v) @@ -107,6 +125,32 @@ impl PartialOrd for Double { impl Eq for Double {} +impl PartialEq for AValue { + fn eq(&self, other: &Self) -> bool { + self.1.eq(&other.1) + } +} + +impl Eq for AValue {} + +impl Hash for AValue { + fn hash(&self, state: &mut H) { + self.1.hash(state); + } +} + +impl PartialOrd for AValue { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for AValue { + fn cmp(&self, other: &Self) -> Ordering { + self.1.cmp(&other.1) + } +} + impl From for Value { fn from(v: bool) -> Self { Value::Boolean(v) } } impl From for Value { fn from(v: f32) -> Self { Value::Float(Float::from(v)) } } @@ -126,3 +170,286 @@ impl From for Value { fn from(v: BigInt) -> Self { Value::SignedInteger( impl From<&str> for Value { fn from(v: &str) -> Self { Value::String(String::from(v)) } } impl From for Value { fn from(v: String) -> Self { Value::String(v) } } + +impl From<&[u8]> for Value { fn from(v: &[u8]) -> Self { Value::ByteString(Vec::from(v)) } } +impl From> for Value { fn from(v: Vec) -> Self { Value::ByteString(v) } } + +//--------------------------------------------------------------------------- + +impl AValue { + pub fn rc(self) -> Rc { + Rc::new(self) + } + + pub fn annotations(&self) -> &Vec { + &self.0 + } + + pub fn annotations_mut(&mut self) -> &mut Vec { + &mut self.0 + } + + pub fn value(&self) -> &Value { + &self.1 + } + + pub fn value_mut(&mut self) -> &mut Value { + &mut self.1 + } +} + +impl Value { + pub fn wrap(self) -> AValue { + AValue(Vec::new(), self) + } + + pub fn is_boolean(&self) -> bool { + self.as_boolean().is_some() + } + + pub fn as_boolean(&self) -> Option { + if let Value::Boolean(b) = *self { + Some(b) + } else { + None + } + } + + pub fn as_boolean_mut(&mut self) -> Option<&mut bool> { + if let Value::Boolean(ref mut b) = *self { + Some(b) + } else { + None + } + } + + pub fn is_float(&self) -> bool { + self.as_float().is_some() + } + + pub fn as_float(&self) -> Option { + if let Value::Float(Float(f)) = *self { + Some(f) + } else { + None + } + } + + pub fn as_float_mut(&mut self) -> Option<&mut f32> { + if let Value::Float(Float(ref mut f)) = *self { + Some(f) + } else { + None + } + } + + pub fn is_double(&self) -> bool { + self.as_double().is_some() + } + + pub fn as_double(&self) -> Option { + if let Value::Double(Double(f)) = *self { + Some(f) + } else { + None + } + } + + pub fn as_double_mut(&mut self) -> Option<&mut f64> { + if let Value::Double(Double(ref mut f)) = *self { + Some(f) + } else { + None + } + } + + pub fn is_signedinteger(&self) -> bool { + self.as_signedinteger().is_some() + } + + pub fn as_signedinteger(&self) -> Option<&BigInt> { + if let Value::SignedInteger(ref i) = *self { + Some(i) + } else { + None + } + } + + pub fn as_signedinteger_mut(&mut self) -> Option<&mut BigInt> { + if let Value::SignedInteger(ref mut i) = *self { + Some(i) + } else { + None + } + } + + pub fn is_string(&self) -> bool { + self.as_string().is_some() + } + + pub fn as_string(&self) -> Option<&String> { + if let Value::String(ref s) = *self { + Some(s) + } else { + None + } + } + + pub fn as_string_mut(&mut self) -> Option<&mut String> { + if let Value::String(ref mut s) = *self { + Some(s) + } else { + None + } + } + + pub fn is_bytestring(&self) -> bool { + self.as_bytestring().is_some() + } + + pub fn as_bytestring(&self) -> Option<&Vec> { + if let Value::ByteString(ref s) = *self { + Some(s) + } else { + None + } + } + + pub fn as_bytestring_mut(&mut self) -> Option<&mut Vec> { + if let Value::ByteString(ref mut s) = *self { + Some(s) + } else { + None + } + } + + pub fn symbol(s: &str) -> Value { + Value::Symbol(s.to_string()) + } + + pub fn is_symbol(&self) -> bool { + self.as_symbol().is_some() + } + + pub fn as_symbol(&self) -> Option<&String> { + if let Value::Symbol(ref s) = *self { + Some(s) + } else { + None + } + } + + pub fn as_symbol_mut(&mut self) -> Option<&mut String> { + if let Value::Symbol(ref mut s) = *self { + Some(s) + } else { + None + } + } + + pub fn record(label: &Rc, fields: Vec) -> Value { + Value::Record((Rc::clone(label), fields)) + } + + pub fn is_record(&self) -> bool { + self.as_record().is_some() + } + + pub fn as_record(&self) -> Option<&Record> { + if let Value::Record(ref r) = *self { + Some(r) + } else { + None + } + } + + pub fn as_record_mut(&mut self) -> Option<&mut Record> { + if let Value::Record(ref mut r) = *self { + Some(r) + } else { + None + } + } + + pub fn is_sequence(&self) -> bool { + self.as_sequence().is_some() + } + + pub fn as_sequence(&self) -> Option<&Vec> { + if let Value::Sequence(ref s) = *self { + Some(s) + } else { + None + } + } + + pub fn as_sequence_mut(&mut self) -> Option<&mut Vec> { + if let Value::Sequence(ref mut s) = *self { + Some(s) + } else { + None + } + } + + pub fn is_set(&self) -> bool { + self.as_set().is_some() + } + + pub fn as_set(&self) -> Option<&BTreeSet> { + if let Value::Set(ref s) = *self { + Some(s) + } else { + None + } + } + + pub fn as_set_mut(&mut self) -> Option<&mut BTreeSet> { + if let Value::Set(ref mut s) = *self { + Some(s) + } else { + None + } + } + + pub fn is_dictionary(&self) -> bool { + self.as_dictionary().is_some() + } + + pub fn as_dictionary(&self) -> Option<&BTreeMap> { + if let Value::Dictionary(ref s) = *self { + Some(s) + } else { + None + } + } + + pub fn as_dictionary_mut(&mut self) -> Option<&mut BTreeMap> { + if let Value::Dictionary(ref mut s) = *self { + Some(s) + } else { + None + } + } +} + +impl Index for Value { + type Output = AValue; + + fn index(&self, i: usize) -> &Self::Output { + &self.as_sequence().unwrap()[i] + } +} + +impl IndexMut for Value { + fn index_mut(&mut self, i: usize) -> &mut Self::Output { + &mut self.as_sequence_mut().unwrap()[i] + } +} + +impl Index<&AValue> for Value { + type Output = AValue; + + fn index(&self, i: &AValue) -> &Self::Output { + &self.as_dictionary().unwrap()[i] + } +}