More basics
This commit is contained in:
parent
c93fea0545
commit
e7f559c944
|
@ -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<f32> 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<Float> 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<H: Hasher>(&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<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for Float {}
|
||||
|
||||
impl From<f64> for Double {
|
||||
fn from(v: f64) -> Self {
|
||||
Double(v)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Double> for f64 {
|
||||
fn from(v: Double) -> Self {
|
||||
v.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Hash for Double {
|
||||
fn hash<H: Hasher>(&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<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for Double {}
|
||||
|
|
|
@ -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<D> + '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<D> + '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<D: Domain> Value<D> for u64 {
|
|||
}
|
||||
}
|
||||
|
||||
impl<D: Domain> Value<D> for Float {
|
||||
impl<D: Domain> Value<D> for f32 {
|
||||
fn value_class(&self) -> ValueClass { ValueClass::Atomic(AtomClass::Float) }
|
||||
fn as_float(&self) -> Option<f32> { Some(self.0) }
|
||||
fn as_double(&self) -> Option<f64> { Some(self.0 as f64) }
|
||||
fn as_float(&self) -> Option<f32> { Some(*self) }
|
||||
fn as_double(&self) -> Option<f64> { Some(*self as f64) }
|
||||
}
|
||||
|
||||
impl<D: Domain> Value<D> for f64 {
|
||||
fn value_class(&self) -> ValueClass { ValueClass::Atomic(AtomClass::Float) }
|
||||
fn as_float(&self) -> Option<f32> { Some(*self as f32) }
|
||||
fn as_double(&self) -> Option<f64> { Some(*self) }
|
||||
}
|
||||
|
||||
impl<D: Domain> Value<D> for str {
|
||||
|
@ -348,6 +353,46 @@ impl<D: Domain> Value<D> for String {
|
|||
fn as_string(&self) -> Option<Cow<'_, str>> { Some(Cow::Borrowed(self)) }
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
#[repr(transparent)]
|
||||
pub struct Bytes<T: AsRef<[u8]>>(T);
|
||||
|
||||
impl<T: AsRef<[u8]> + Debug, D: Domain> Value<D> for Bytes<T> {
|
||||
fn value_class(&self) -> ValueClass { ValueClass::Atomic(AtomClass::ByteString) }
|
||||
fn as_bytestring(&self) -> Option<Cow<'_, [u8]>> { Some(Cow::Borrowed(self.0.as_ref())) }
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
#[repr(transparent)]
|
||||
pub struct Symbol<T: AsRef<str> + Debug>(T);
|
||||
|
||||
impl<T: AsRef<str> + Debug, D: Domain> Value<D> for Symbol<T> {
|
||||
fn value_class(&self) -> ValueClass { ValueClass::Atomic(AtomClass::Symbol) }
|
||||
fn as_symbol(&self) -> Option<Cow<'_, str>> { Some(Cow::Borrowed(self.0.as_ref())) }
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
#[repr(transparent)]
|
||||
pub struct Record<V>(Vec<V> /* at least one element, for the label */);
|
||||
|
||||
impl<V> Record<V> {
|
||||
pub fn new(label: V, mut fields: Vec<V>) -> Self {
|
||||
fields.insert(0, label);
|
||||
Record(fields)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Domain, V: Value<D>> Value<D> for Record<V> {
|
||||
fn value_class(&self) -> ValueClass { ValueClass::Compound(CompoundClass::Record) }
|
||||
fn is_record(&self) -> bool { true }
|
||||
fn label(&self) -> &dyn Value<D> { &self.0[0] }
|
||||
fn len(&self) -> usize { self.0.len() - 1 }
|
||||
fn index(&self, i: usize) -> &dyn Value<D> { &self.0[i + 1] }
|
||||
fn iter(&self) -> Box<dyn Iterator<Item = &dyn Value<D>> + '_> {
|
||||
Box::new(self.0[1..].iter().map(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Domain, V: Value<D>> Value<D> for Vec<V> {
|
||||
fn value_class(&self) -> ValueClass { ValueClass::Compound(CompoundClass::Sequence) }
|
||||
fn is_sequence(&self) -> bool { true }
|
||||
|
@ -410,32 +455,13 @@ impl<D: Domain, V: Value<D>> Value<D> for Map<Box<dyn Value<D>>, V> {
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
pub struct Record<V>(Vec<V> /* at least one element, for the label */);
|
||||
#[repr(transparent)]
|
||||
pub struct Embedded<D: Domain>(D);
|
||||
|
||||
impl<V> Record<V> {
|
||||
pub fn new(label: V, mut fields: Vec<V>) -> Self {
|
||||
fields.insert(0, label);
|
||||
Record(fields)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Domain, V: Value<D>> Value<D> for Record<V> {
|
||||
fn value_class(&self) -> ValueClass { ValueClass::Compound(CompoundClass::Record) }
|
||||
fn is_record(&self) -> bool { true }
|
||||
fn label(&self) -> &dyn Value<D> { &self.0[0] }
|
||||
fn len(&self) -> usize { self.0.len() - 1 }
|
||||
fn index(&self, i: usize) -> &dyn Value<D> { &self.0[i + 1] }
|
||||
fn iter(&self) -> Box<dyn Iterator<Item = &dyn Value<D>> + '_> {
|
||||
Box::new(self.0[1..].iter().map(value))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
pub struct Symbol<T: AsRef<str> + Debug>(T);
|
||||
|
||||
impl<T: AsRef<str> + Debug, D: Domain> Value<D> for Symbol<T> {
|
||||
fn value_class(&self) -> ValueClass { ValueClass::Atomic(AtomClass::Symbol) }
|
||||
fn as_symbol(&self) -> Option<Cow<'_, str>> { Some(Cow::Borrowed(self.0.as_ref())) }
|
||||
impl<D: Domain> Value<D> for Embedded<D> {
|
||||
fn value_class(&self) -> ValueClass { ValueClass::Embedded }
|
||||
fn is_embedded(&self) -> bool { true }
|
||||
fn embedded(&self) -> Cow<'_, D> { Cow::Borrowed(&self.0) }
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
Loading…
Reference in New Issue