diff --git a/implementations/rust/oo/Cargo.toml b/implementations/rust/oo/Cargo.toml index 0b4dad1..b796a95 100644 --- a/implementations/rust/oo/Cargo.toml +++ b/implementations/rust/oo/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" [dependencies] base64 = "0.13" +bytemuck = "1.12" dtoa = "0.4" num = "0.4" regex = "1.5" diff --git a/implementations/rust/oo/src/lib.rs b/implementations/rust/oo/src/lib.rs index a57da7a..018d9d5 100644 --- a/implementations/rust/oo/src/lib.rs +++ b/implementations/rust/oo/src/lib.rs @@ -1,4 +1,6 @@ -use std::borrow::Cow; +use bytemuck::TransparentWrapper; + +use std::borrow::{Cow, Borrow}; use std::cmp::Ordering; use std::fmt::Debug; use std::hash::{Hash, Hasher}; @@ -74,7 +76,7 @@ pub trait Value: Debug { fn has(&self, _v: &dyn Value) -> bool { false } fn is_dictionary(&self) -> bool { false } - fn get(&self, _k: &(dyn Value + 'static)) -> Option<&dyn Value> { None } + fn get(&self, _k: &dyn Value) -> Option<&dyn Value> { None } fn entries(&self) -> Option, &dyn Value)> + '_>> { None } fn is_embedded(&self) -> bool { false } @@ -105,7 +107,7 @@ impl<'a, D: Domain, V: Value + ?Sized> Value for &'a V { fn is_set(&self) -> bool { (*self).is_set() } fn has(&self, v: &dyn Value) -> bool { (*self).has(v) } fn is_dictionary(&self) -> bool { (*self).is_dictionary() } - fn get(&self, k: &(dyn Value + 'static)) -> Option<&dyn Value> { (*self).get(k) } + fn get(&self, k: &dyn Value) -> Option<&dyn Value> { (*self).get(k) } fn entries(&self) -> Option, &dyn Value)> + '_>> { (*self).entries() } fn is_embedded(&self) -> bool { (*self).is_embedded() } fn embedded(&self) -> Option> { (*self).embedded() } @@ -130,7 +132,7 @@ impl Value for Box> { fn is_set(&self) -> bool { self.as_ref().is_set() } fn has(&self, v: &dyn Value) -> bool { self.as_ref().has(v) } fn is_dictionary(&self) -> bool { self.as_ref().is_dictionary() } - fn get(&self, k: &(dyn Value + 'static)) -> Option<&dyn Value> { self.as_ref().get(k) } + fn get(&self, k: &dyn Value) -> Option<&dyn Value> { self.as_ref().get(k) } fn entries(&self) -> Option, &dyn Value)> + '_>> { self.as_ref().entries() } fn is_embedded(&self) -> bool { self.as_ref().is_embedded() } fn embedded(&self) -> Option> { self.as_ref().embedded() } @@ -341,13 +343,28 @@ impl Value for Set>> { } } +#[derive(PartialEq, Eq, PartialOrd, Ord)] +#[repr(transparent)] +struct Key<'a, D: Domain>(dyn Value + 'a); + +// Many thanks to SkiFire13 and the other participants in +// https://users.rust-lang.org/t/is-the-lifetime-of-a-btreemap-get-result-attached-to-the-key-as-well-as-the-map/83568/7 +// for the idea of using TransparentWrapper here. +// +unsafe impl<'a, D: Domain> TransparentWrapper + 'a> for Key<'a, D> {} +impl<'a, 'b: 'a, D: Domain> Borrow> for Box + 'b> { + fn borrow(&self) -> &Key<'a, D> { + Key::wrap_ref(&**self) + } +} + impl> Value for Map>, V> { fn value_class(&self) -> ValueClass { ValueClass::Compound(CompoundClass::Dictionary) } fn is_dictionary(&self) -> bool { true } fn len(&self) -> Option { Some(self.len()) } fn has(&self, v: &dyn Value) -> bool { self.contains_key(v) } - fn get(&self, k: &(dyn Value + 'static)) -> Option<&dyn Value> { - match Map::get(self, k) { + fn get(&self, k: &dyn Value) -> Option<&dyn Value> { + match Map::get(self, Key::wrap_ref(&k)) { Some(v) => Some(v), None => None, } @@ -395,7 +412,7 @@ impl> Value for Annotations { fn is_set(&self) -> bool { self.value().is_set() } fn has(&self, v: &dyn Value) -> bool { self.value().has(v) } fn is_dictionary(&self) -> bool { self.value().is_dictionary() } - fn get(&self, k: &(dyn Value + 'static)) -> Option<&dyn Value> { self.value().get(k) } + fn get(&self, k: &dyn Value) -> Option<&dyn Value> { self.value().get(k) } fn entries(&self) -> Option, &dyn Value)> + '_>> { self.value().entries() } fn is_embedded(&self) -> bool { self.value().is_embedded() } fn embedded(&self) -> Option> { self.value().embedded() } @@ -433,7 +450,7 @@ mod demo { use crate::*; fn getit<'a>(d: &'a dyn Value, k: &str) -> Option<&'a dyn Value> { - d.get(&k as &(dyn Value + 'static)) + d.get(&k) } #[test] fn a() { @@ -457,7 +474,7 @@ mod demo { // for line in std::io::stdin().lock().lines() { // let line = line.unwrap(); // let val = w.get(&line); - // println!("{:?} = {:?}", line, val); + // println!("{:?} ==> {:?} == {:?}", line, val, getit(&v, &line)); // } // } }