diff --git a/implementations/rust/oo/src/float.rs b/implementations/rust/oo/src/float.rs index ff1f9cf..796d3d6 100644 --- a/implementations/rust/oo/src/float.rs +++ b/implementations/rust/oo/src/float.rs @@ -1,94 +1,25 @@ use std::cmp::Ordering; -use std::hash::{Hash, Hasher}; -/// Single-precision IEEE 754 Value -#[derive(Clone, Copy, Debug)] -pub struct Float(pub f32); - -/// Double-precision IEEE 754 Value -#[derive(Clone, Copy, Debug)] -pub struct Double(pub f64); - -impl From for Float { - fn from(v: f32) -> Self { - Float(v) - } +pub fn cmp_f32(a: f32, b: f32) -> Ordering { + let mut a: u32 = a.to_bits(); + let mut b: u32 = b.to_bits(); + if a & 0x8000_0000 != 0 { a ^= 0x7fff_ffff; } + if b & 0x8000_0000 != 0 { b ^= 0x7fff_ffff; } + (a as i32).cmp(&(b as i32)) } -impl From for f32 { - fn from(v: Float) -> Self { - v.0 - } +pub fn eq_f32(a: f32, b: f32) -> bool { + a.to_bits() == b.to_bits() } -impl Hash for Float { - fn hash(&self, state: &mut H) { - self.0.to_bits().hash(state); - } +pub fn cmp_f64(a: f64, b: f64) -> Ordering { + let mut a: u64 = a.to_bits(); + let mut b: u64 = b.to_bits(); + if a & 0x8000_0000_0000_0000 != 0 { a ^= 0x7fff_ffff_ffff_ffff; } + if b & 0x8000_0000_0000_0000 != 0 { b ^= 0x7fff_ffff_ffff_ffff; } + (a as i64).cmp(&(b as i64)) } -impl PartialEq for Float { - fn eq(&self, other: &Self) -> bool { - self.0.to_bits() == other.0.to_bits() - } +pub fn eq_f64(a: f64, b: f64) -> bool { + a.to_bits() == b.to_bits() } - -impl Ord for Float { - fn cmp(&self, other: &Self) -> Ordering { - let mut a: u32 = self.0.to_bits(); - let mut b: u32 = other.0.to_bits(); - if a & 0x8000_0000 != 0 { a ^= 0x7fff_ffff; } - if b & 0x8000_0000 != 0 { b ^= 0x7fff_ffff; } - (a as i32).cmp(&(b as i32)) - } -} - -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 { - self.0.to_bits() == other.0.to_bits() - } -} - -impl Ord for Double { - fn cmp(&self, other: &Self) -> Ordering { - let mut a: u64 = self.0.to_bits(); - let mut b: u64 = other.0.to_bits(); - if a & 0x8000_0000_0000_0000 != 0 { a ^= 0x7fff_ffff_ffff_ffff; } - if b & 0x8000_0000_0000_0000 != 0 { b ^= 0x7fff_ffff_ffff_ffff; } - (a as i64).cmp(&(b as i64)) - } -} - -impl PartialOrd for Double { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } -} - -impl Eq for Double {} diff --git a/implementations/rust/oo/src/lib.rs b/implementations/rust/oo/src/lib.rs index d4fa4e1..62953ee 100644 --- a/implementations/rust/oo/src/lib.rs +++ b/implementations/rust/oo/src/lib.rs @@ -1,4 +1,5 @@ use bytemuck::TransparentWrapper; +use float::{eq_f32, eq_f64, cmp_f32, cmp_f64}; use std::borrow::{Cow, Borrow}; use std::cmp::Ordering; @@ -12,8 +13,6 @@ pub use std::collections::BTreeMap as Map; pub mod float; pub mod signed_integer; -pub use float::Float; -pub use float::Double; pub use signed_integer::SignedInteger; /// The kinds of `Value` from the specification. @@ -205,9 +204,9 @@ impl<'a, D: Domain> PartialEq for dyn Value + 'a { AtomClass::Boolean => self.as_boolean().unwrap() == other.as_boolean().unwrap(), AtomClass::Float => - Float(self.as_float().unwrap()) == Float(other.as_float().unwrap()), + eq_f32(self.as_float().unwrap(), other.as_float().unwrap()), AtomClass::Double => - Double(self.as_double().unwrap()) == Double(other.as_double().unwrap()), + eq_f64(self.as_double().unwrap(), other.as_double().unwrap()), AtomClass::SignedInteger => self.as_signed_integer().unwrap() == other.as_signed_integer().unwrap(), AtomClass::String => @@ -270,9 +269,9 @@ impl<'a, D: Domain> Ord for dyn Value + 'a { AtomClass::Boolean => self.as_boolean().cmp(&other.as_boolean()), AtomClass::Float => - Float(self.as_float().unwrap()).cmp(&Float(other.as_float().unwrap())), + cmp_f32(self.as_float().unwrap(), other.as_float().unwrap()), AtomClass::Double => - Double(self.as_double().unwrap()).cmp(&Double(other.as_double().unwrap())), + cmp_f64(self.as_double().unwrap(), other.as_double().unwrap()), AtomClass::SignedInteger => self.as_signed_integer().cmp(&other.as_signed_integer()), AtomClass::String => @@ -332,10 +331,16 @@ impl Value for u64 { } } -impl Value for Float { +impl Value for f32 { fn value_class(&self) -> ValueClass { ValueClass::Atomic(AtomClass::Float) } - fn as_float(&self) -> Option { Some(self.0) } - fn as_double(&self) -> Option { Some(self.0 as f64) } + fn as_float(&self) -> Option { Some(*self) } + fn as_double(&self) -> Option { Some(*self as f64) } +} + +impl Value for f64 { + fn value_class(&self) -> ValueClass { ValueClass::Atomic(AtomClass::Float) } + fn as_float(&self) -> Option { Some(*self as f32) } + fn as_double(&self) -> Option { Some(*self) } } impl Value for str { @@ -348,6 +353,46 @@ impl Value for String { fn as_string(&self) -> Option> { Some(Cow::Borrowed(self)) } } +#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +#[repr(transparent)] +pub struct Bytes>(T); + +impl + Debug, D: Domain> Value for Bytes { + fn value_class(&self) -> ValueClass { ValueClass::Atomic(AtomClass::ByteString) } + fn as_bytestring(&self) -> Option> { Some(Cow::Borrowed(self.0.as_ref())) } +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +#[repr(transparent)] +pub struct Symbol + Debug>(T); + +impl + Debug, D: Domain> Value for Symbol { + fn value_class(&self) -> ValueClass { ValueClass::Atomic(AtomClass::Symbol) } + fn as_symbol(&self) -> Option> { Some(Cow::Borrowed(self.0.as_ref())) } +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +#[repr(transparent)] +pub struct Record(Vec /* at least one element, for the label */); + +impl Record { + pub fn new(label: V, mut fields: Vec) -> Self { + fields.insert(0, label); + Record(fields) + } +} + +impl> Value for Record { + fn value_class(&self) -> ValueClass { ValueClass::Compound(CompoundClass::Record) } + fn is_record(&self) -> bool { true } + fn label(&self) -> &dyn Value { &self.0[0] } + fn len(&self) -> usize { self.0.len() - 1 } + fn index(&self, i: usize) -> &dyn Value { &self.0[i + 1] } + fn iter(&self) -> Box> + '_> { + Box::new(self.0[1..].iter().map(value)) + } +} + impl> Value for Vec { fn value_class(&self) -> ValueClass { ValueClass::Compound(CompoundClass::Sequence) } fn is_sequence(&self) -> bool { true } @@ -410,32 +455,13 @@ impl> Value for Map>, V> { } #[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub struct Record(Vec /* at least one element, for the label */); +#[repr(transparent)] +pub struct Embedded(D); -impl Record { - pub fn new(label: V, mut fields: Vec) -> Self { - fields.insert(0, label); - Record(fields) - } -} - -impl> Value for Record { - fn value_class(&self) -> ValueClass { ValueClass::Compound(CompoundClass::Record) } - fn is_record(&self) -> bool { true } - fn label(&self) -> &dyn Value { &self.0[0] } - fn len(&self) -> usize { self.0.len() - 1 } - fn index(&self, i: usize) -> &dyn Value { &self.0[i + 1] } - fn iter(&self) -> Box> + '_> { - Box::new(self.0[1..].iter().map(value)) - } -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub struct Symbol + Debug>(T); - -impl + Debug, D: Domain> Value for Symbol { - fn value_class(&self) -> ValueClass { ValueClass::Atomic(AtomClass::Symbol) } - fn as_symbol(&self) -> Option> { Some(Cow::Borrowed(self.0.as_ref())) } +impl Value for Embedded { + fn value_class(&self) -> ValueClass { ValueClass::Embedded } + fn is_embedded(&self) -> bool { true } + fn embedded(&self) -> Cow<'_, D> { Cow::Borrowed(&self.0) } } #[derive(Debug)]