This was the trick for Maps!

This commit is contained in:
Tony Garnock-Jones 2022-11-02 16:26:21 +01:00
parent 9aea564b2c
commit 71a45d7808
2 changed files with 27 additions and 9 deletions

View File

@ -7,6 +7,7 @@ edition = "2021"
[dependencies]
base64 = "0.13"
bytemuck = "1.12"
dtoa = "0.4"
num = "0.4"
regex = "1.5"

View File

@ -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<D: Domain>: Debug {
fn has(&self, _v: &dyn Value<D>) -> bool { false }
fn is_dictionary(&self) -> bool { false }
fn get(&self, _k: &(dyn Value<D> + 'static)) -> Option<&dyn Value<D>> { None }
fn get(&self, _k: &dyn Value<D>) -> Option<&dyn Value<D>> { None }
fn entries(&self) -> Option<Box<dyn Iterator<Item = (&dyn Value<D>, &dyn Value<D>)> + '_>> { None }
fn is_embedded(&self) -> bool { false }
@ -105,7 +107,7 @@ impl<'a, D: Domain, V: Value<D> + ?Sized> Value<D> for &'a V {
fn is_set(&self) -> bool { (*self).is_set() }
fn has(&self, v: &dyn Value<D>) -> bool { (*self).has(v) }
fn is_dictionary(&self) -> bool { (*self).is_dictionary() }
fn get(&self, k: &(dyn Value<D> + 'static)) -> Option<&dyn Value<D>> { (*self).get(k) }
fn get(&self, k: &dyn Value<D>) -> Option<&dyn Value<D>> { (*self).get(k) }
fn entries(&self) -> Option<Box<dyn Iterator<Item = (&dyn Value<D>, &dyn Value<D>)> + '_>> { (*self).entries() }
fn is_embedded(&self) -> bool { (*self).is_embedded() }
fn embedded(&self) -> Option<Cow<'_, D>> { (*self).embedded() }
@ -130,7 +132,7 @@ impl<D: Domain> Value<D> for Box<dyn Value<D>> {
fn is_set(&self) -> bool { self.as_ref().is_set() }
fn has(&self, v: &dyn Value<D>) -> bool { self.as_ref().has(v) }
fn is_dictionary(&self) -> bool { self.as_ref().is_dictionary() }
fn get(&self, k: &(dyn Value<D> + 'static)) -> Option<&dyn Value<D>> { self.as_ref().get(k) }
fn get(&self, k: &dyn Value<D>) -> Option<&dyn Value<D>> { self.as_ref().get(k) }
fn entries(&self) -> Option<Box<dyn Iterator<Item = (&dyn Value<D>, &dyn Value<D>)> + '_>> { self.as_ref().entries() }
fn is_embedded(&self) -> bool { self.as_ref().is_embedded() }
fn embedded(&self) -> Option<Cow<'_, D>> { self.as_ref().embedded() }
@ -341,13 +343,28 @@ impl<D: Domain> Value<D> for Set<Box<dyn Value<D>>> {
}
}
#[derive(PartialEq, Eq, PartialOrd, Ord)]
#[repr(transparent)]
struct Key<'a, D: Domain>(dyn Value<D> + '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<dyn Value<D> + 'a> for Key<'a, D> {}
impl<'a, 'b: 'a, D: Domain> Borrow<Key<'a, D>> for Box<dyn Value<D> + 'b> {
fn borrow(&self) -> &Key<'a, D> {
Key::wrap_ref(&**self)
}
}
impl<D: Domain, V: Value<D>> Value<D> for Map<Box<dyn Value<D>>, V> {
fn value_class(&self) -> ValueClass { ValueClass::Compound(CompoundClass::Dictionary) }
fn is_dictionary(&self) -> bool { true }
fn len(&self) -> Option<usize> { Some(self.len()) }
fn has(&self, v: &dyn Value<D>) -> bool { self.contains_key(v) }
fn get(&self, k: &(dyn Value<D> + 'static)) -> Option<&dyn Value<D>> {
match Map::get(self, k) {
fn get(&self, k: &dyn Value<D>) -> Option<&dyn Value<D>> {
match Map::get(self, Key::wrap_ref(&k)) {
Some(v) => Some(v),
None => None,
}
@ -395,7 +412,7 @@ impl<D: Domain, V: Value<D>> Value<D> for Annotations<D, V> {
fn is_set(&self) -> bool { self.value().is_set() }
fn has(&self, v: &dyn Value<D>) -> bool { self.value().has(v) }
fn is_dictionary(&self) -> bool { self.value().is_dictionary() }
fn get(&self, k: &(dyn Value<D> + 'static)) -> Option<&dyn Value<D>> { self.value().get(k) }
fn get(&self, k: &dyn Value<D>) -> Option<&dyn Value<D>> { self.value().get(k) }
fn entries(&self) -> Option<Box<dyn Iterator<Item = (&dyn Value<D>, &dyn Value<D>)> + '_>> { self.value().entries() }
fn is_embedded(&self) -> bool { self.value().is_embedded() }
fn embedded(&self) -> Option<Cow<'_, D>> { self.value().embedded() }
@ -433,7 +450,7 @@ mod demo {
use crate::*;
fn getit<'a>(d: &'a dyn Value<NoValue>, k: &str) -> Option<&'a dyn Value<NoValue>> {
d.get(&k as &(dyn Value<NoValue> + '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));
// }
// }
}