From 6960046263c091451a9368b045762a92aaaec587 Mon Sep 17 00:00:00 2001 From: Tony Garnock-Jones Date: Sat, 29 Jun 2019 23:02:27 +0100 Subject: [PATCH] Beginnings of Rust implementation --- implementations/rust/Cargo.toml | 10 ++ implementations/rust/Makefile | 2 + implementations/rust/src/lib.rs | 9 ++ implementations/rust/src/value/mod.rs | 1 + implementations/rust/src/value/value.rs | 128 ++++++++++++++++++++++++ 5 files changed, 150 insertions(+) create mode 100644 implementations/rust/Cargo.toml create mode 100644 implementations/rust/Makefile create mode 100644 implementations/rust/src/lib.rs create mode 100644 implementations/rust/src/value/mod.rs create mode 100644 implementations/rust/src/value/value.rs diff --git a/implementations/rust/Cargo.toml b/implementations/rust/Cargo.toml new file mode 100644 index 0000000..8ca7edf --- /dev/null +++ b/implementations/rust/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "preserves" +version = "0.1.0" +authors = ["Tony Garnock-Jones "] +edition = "2018" + +[dependencies] +num = "0.2" +serde = "1.0" +serde_bytes = "0.11" diff --git a/implementations/rust/Makefile b/implementations/rust/Makefile new file mode 100644 index 0000000..0b65061 --- /dev/null +++ b/implementations/rust/Makefile @@ -0,0 +1,2 @@ +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 new file mode 100644 index 0000000..9528724 --- /dev/null +++ b/implementations/rust/src/lib.rs @@ -0,0 +1,9 @@ +pub mod value; + +#[cfg(test)] +mod tests { + #[test] + fn it_works() { + assert_eq!(2 + 2, 4); + } +} diff --git a/implementations/rust/src/value/mod.rs b/implementations/rust/src/value/mod.rs new file mode 100644 index 0000000..fc45e21 --- /dev/null +++ b/implementations/rust/src/value/mod.rs @@ -0,0 +1 @@ +pub mod value; diff --git a/implementations/rust/src/value/value.rs b/implementations/rust/src/value/value.rs new file mode 100644 index 0000000..da71767 --- /dev/null +++ b/implementations/rust/src/value/value.rs @@ -0,0 +1,128 @@ +use std::hash::{Hash,Hasher}; +use std::cmp::{Ordering}; +use num::bigint::BigInt; + +#[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), +} + +#[derive(Clone, Debug)] +pub struct Float(f32); + +#[derive(Clone, Debug)] +pub struct Double(f64); + +impl From for Float { + fn from(v: f32) -> Self { + Float(v) + } +} + +impl From for f32 { + fn from(v: Float) -> Self { + v.0 + } +} + +impl Hash for Float { + fn hash(&self, state: &mut H) { + self.0.to_bits().hash(state); + } +} + +impl PartialEq for Float { + fn eq(&self, other: &Self) -> bool { + self.0.to_bits() == other.0.to_bits() + } +} + +impl Ord for Float { + fn cmp(&self, other: &Self) -> Ordering { + let mut a = self.0.to_bits(); + let mut b = other.0.to_bits(); + if a & 0x80000000 != 0 { a ^= 0x7fffffff; } + if b & 0x80000000 != 0 { b ^= 0x7fffffff; } + a.cmp(&b) + } +} + +impl PartialOrd for Float { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Eq for Float {} + +impl From for Double { + fn from(v: f64) -> Self { + Double(v) + } +} + +impl From for f64 { + fn from(v: Double) -> Self { + v.0 + } +} + +impl Hash for Double { + fn hash(&self, state: &mut H) { + self.0.to_bits().hash(state); + } +} + +impl PartialEq for Double { + fn eq(&self, other: &Self) -> bool { + return self.0.to_bits() == other.0.to_bits(); + } +} + +impl Ord for Double { + fn cmp(&self, other: &Self) -> Ordering { + let mut a = self.0.to_bits(); + let mut b = other.0.to_bits(); + if a & 0x8000000000000000 != 0 { a ^= 0x7fffffffffffffff; } + if b & 0x8000000000000000 != 0 { b ^= 0x7fffffffffffffff; } + a.cmp(&b) + } +} + +impl PartialOrd for Double { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Eq for Double {} + +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)) } } +impl From for Value { fn from(v: f64) -> Self { Value::Double(Double::from(v)) } } + +impl From for Value { fn from(v: u8) -> Self { Value::SignedInteger(BigInt::from(v)) } } +impl From for Value { fn from(v: i8) -> Self { Value::SignedInteger(BigInt::from(v)) } } +impl From for Value { fn from(v: u16) -> Self { Value::SignedInteger(BigInt::from(v)) } } +impl From for Value { fn from(v: i16) -> Self { Value::SignedInteger(BigInt::from(v)) } } +impl From for Value { fn from(v: u32) -> Self { Value::SignedInteger(BigInt::from(v)) } } +impl From for Value { fn from(v: i32) -> Self { Value::SignedInteger(BigInt::from(v)) } } +impl From for Value { fn from(v: u64) -> Self { Value::SignedInteger(BigInt::from(v)) } } +impl From for Value { fn from(v: i64) -> Self { Value::SignedInteger(BigInt::from(v)) } } +impl From for Value { fn from(v: u128) -> Self { Value::SignedInteger(BigInt::from(v)) } } +impl From for Value { fn from(v: i128) -> Self { Value::SignedInteger(BigInt::from(v)) } } +impl From for Value { fn from(v: BigInt) -> Self { Value::SignedInteger(v) } } + +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) } }