Further steps toward learning enough Rust to produce an implementation
This commit is contained in:
parent
2dd2c329ed
commit
d5cbe90235
|
@ -1 +1,2 @@
|
|||
Cargo.lock
|
||||
target/
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<u8>),
|
||||
Symbol(std::string::String),
|
||||
Record(std::rc::Rc<Value>, std::vec::Vec<Value>),
|
||||
Sequence(std::vec::Vec<Value>),
|
||||
Set(std::collections::BTreeSet<Value>),
|
||||
Dictionary(std::collections::BTreeMap<Value, Value>),
|
||||
String(String),
|
||||
ByteString(Vec<u8>),
|
||||
Symbol(String),
|
||||
Record(Record),
|
||||
Sequence(Vec<AValue>),
|
||||
Set(BTreeSet<AValue>),
|
||||
Dictionary(BTreeMap<AValue, AValue>),
|
||||
}
|
||||
|
||||
/// An possibly-annotated Value, with annotations (themselves
|
||||
/// possibly-annotated) in order of appearance.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct AValue(Vec<AValue>, 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<AValue>, Vec<AValue>);
|
||||
|
||||
impl From<f32> 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<H: Hasher>(&self, state: &mut H) {
|
||||
self.1.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for AValue {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for AValue {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
self.1.cmp(&other.1)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<bool> for Value { fn from(v: bool) -> Self { Value::Boolean(v) } }
|
||||
|
||||
impl From<f32> for Value { fn from(v: f32) -> Self { Value::Float(Float::from(v)) } }
|
||||
|
@ -126,3 +170,286 @@ impl From<BigInt> 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<String> 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<Vec<u8>> for Value { fn from(v: Vec<u8>) -> Self { Value::ByteString(v) } }
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
impl AValue {
|
||||
pub fn rc(self) -> Rc<Self> {
|
||||
Rc::new(self)
|
||||
}
|
||||
|
||||
pub fn annotations(&self) -> &Vec<AValue> {
|
||||
&self.0
|
||||
}
|
||||
|
||||
pub fn annotations_mut(&mut self) -> &mut Vec<AValue> {
|
||||
&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<bool> {
|
||||
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<f32> {
|
||||
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<f64> {
|
||||
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<u8>> {
|
||||
if let Value::ByteString(ref s) = *self {
|
||||
Some(s)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_bytestring_mut(&mut self) -> Option<&mut Vec<u8>> {
|
||||
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<AValue>, fields: Vec<AValue>) -> 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<AValue>> {
|
||||
if let Value::Sequence(ref s) = *self {
|
||||
Some(s)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_sequence_mut(&mut self) -> Option<&mut Vec<AValue>> {
|
||||
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<AValue>> {
|
||||
if let Value::Set(ref s) = *self {
|
||||
Some(s)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_set_mut(&mut self) -> Option<&mut BTreeSet<AValue>> {
|
||||
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<AValue, AValue>> {
|
||||
if let Value::Dictionary(ref s) = *self {
|
||||
Some(s)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_dictionary_mut(&mut self) -> Option<&mut BTreeMap<AValue, AValue>> {
|
||||
if let Value::Dictionary(ref mut s) = *self {
|
||||
Some(s)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Index<usize> for Value {
|
||||
type Output = AValue;
|
||||
|
||||
fn index(&self, i: usize) -> &Self::Output {
|
||||
&self.as_sequence().unwrap()[i]
|
||||
}
|
||||
}
|
||||
|
||||
impl IndexMut<usize> 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]
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue