preserves/implementations/rust/oo/src/lib.rs

568 lines
22 KiB
Rust

use bytemuck::TransparentWrapper;
use float::{eq_f32, eq_f64, cmp_f32, cmp_f64};
use std::borrow::{Cow, Borrow};
use std::cmp::Ordering;
use std::fmt::Debug;
use std::hash::{Hash, Hasher};
use std::vec::Vec;
pub use std::collections::BTreeSet as Set;
pub use std::collections::BTreeMap as Map;
pub mod float;
pub mod signed_integer;
pub use signed_integer::SignedInteger;
/// The kinds of `Value` from the specification.
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum ValueClass {
Atomic(AtomClass),
Compound(CompoundClass),
Embedded,
}
/// The kinds of `Atom` from the specification.
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum AtomClass {
Boolean,
Float,
Double,
SignedInteger,
String,
ByteString,
Symbol,
}
/// The kinds of `Compound` from the specification.
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum CompoundClass {
Record,
Sequence,
Set,
Dictionary,
}
pub trait Domain: Debug + Eq + Hash + Ord + Clone {}
#[derive(Debug)]
pub struct OutOfRange;
pub trait Value<D: Domain>: Debug {
fn value_class(&self) -> ValueClass;
fn as_boolean(&self) -> Option<bool> { None }
fn as_float(&self) -> Option<f32> { None }
fn as_double(&self) -> Option<f64> { None }
fn is_signed_integer(&self) -> bool { false }
fn as_signed_integer(&self) -> Option<SignedInteger> { None }
fn as_string(&self) -> Option<Cow<'_, str>> { None }
fn as_bytestring(&self) -> Option<Cow<'_, [u8]>> { None }
fn as_symbol(&self) -> Option<Cow<'_, str>> { None }
fn is_record(&self) -> bool { false }
fn label(&self) -> &dyn Value<D> { panic!("Not a record") }
fn is_sequence(&self) -> bool { false }
fn len(&self) -> usize { panic!("Has no length") }
fn index(&self, _i: usize) -> &dyn Value<D> { panic!("Not indexable") }
fn iter(&self) -> Box<dyn Iterator<Item = &dyn Value<D>> + '_> { panic!("Not iterable") }
fn is_set(&self) -> bool { false }
fn has(&self, _v: &dyn Value<D>) -> bool { false }
fn is_dictionary(&self) -> bool { false }
fn get(&self, _k: &dyn Value<D>) -> Option<&dyn Value<D>> { None }
fn entries(&self) -> Box<dyn Iterator<Item = (&dyn Value<D>, &dyn Value<D>)> + '_> { panic!("Not a dictionary") }
fn is_embedded(&self) -> bool { false }
fn embedded(&self) -> Cow<'_, D> { panic!("Not an embedded value") }
fn annotations(&self) -> Option<&[Box<dyn Value<D>>]> { None }
}
pub fn value<D: Domain, V: Value<D>>(v: &V) -> &dyn Value<D> {
v
}
pub fn owned<D: Domain, V: Value<D> + 'static>(v: V) -> Box<dyn Value<D>> {
Box::new(v)
}
impl<'a, D: Domain, V: Value<D> + ?Sized> Value<D> for &'a V {
fn value_class(&self) -> ValueClass { (*self).value_class() }
fn as_boolean(&self) -> Option<bool> { (*self).as_boolean() }
fn as_float(&self) -> Option<f32> { (*self).as_float() }
fn as_double(&self) -> Option<f64> { (*self).as_double() }
fn is_signed_integer(&self) -> bool { (*self).is_signed_integer() }
fn as_signed_integer(&self) -> Option<SignedInteger> { (*self).as_signed_integer() }
fn as_string(&self) -> Option<Cow<'_, str>> { (*self).as_string() }
fn as_bytestring(&self) -> Option<Cow<'_, [u8]>> { (*self).as_bytestring() }
fn as_symbol(&self) -> Option<Cow<'_, str>> { (*self).as_symbol() }
fn is_record(&self) -> bool { (*self).is_record() }
fn label(&self) -> &dyn Value<D> { (*self).label() }
fn is_sequence(&self) -> bool { (*self).is_sequence() }
fn len(&self) -> usize { (*self).len() }
fn index(&self, i: usize) -> &dyn Value<D> { (*self).index(i) }
fn iter(&self) -> Box<dyn Iterator<Item = &dyn Value<D>> + '_> { (*self).iter() }
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>) -> Option<&dyn Value<D>> { (*self).get(k) }
fn entries(&self) -> Box<dyn Iterator<Item = (&dyn Value<D>, &dyn Value<D>)> + '_> { (*self).entries() }
fn is_embedded(&self) -> bool { (*self).is_embedded() }
fn embedded(&self) -> Cow<'_, D> { (*self).embedded() }
fn annotations(&self) -> Option<&[Box<dyn Value<D>>]> { (*self).annotations() }
}
impl<D: Domain> Value<D> for Box<dyn Value<D>> {
fn value_class(&self) -> ValueClass { self.as_ref().value_class() }
fn as_boolean(&self) -> Option<bool> { self.as_ref().as_boolean() }
fn as_float(&self) -> Option<f32> { self.as_ref().as_float() }
fn as_double(&self) -> Option<f64> { self.as_ref().as_double() }
fn is_signed_integer(&self) -> bool { self.as_ref().is_signed_integer() }
fn as_signed_integer(&self) -> Option<SignedInteger> { self.as_ref().as_signed_integer() }
fn as_string(&self) -> Option<Cow<'_, str>> { self.as_ref().as_string() }
fn as_bytestring(&self) -> Option<Cow<'_, [u8]>> { self.as_ref().as_bytestring() }
fn as_symbol(&self) -> Option<Cow<'_, str>> { self.as_ref().as_symbol() }
fn is_record(&self) -> bool { self.as_ref().is_record() }
fn label(&self) -> &dyn Value<D> { self.as_ref().label() }
fn is_sequence(&self) -> bool { self.as_ref().is_sequence() }
fn len(&self) -> usize { self.as_ref().len() }
fn index(&self, i: usize) -> &dyn Value<D> { self.as_ref().index(i) }
fn iter(&self) -> Box<dyn Iterator<Item = &dyn Value<D>> + '_> { self.as_ref().iter() }
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>) -> Option<&dyn Value<D>> { self.as_ref().get(k) }
fn entries(&self) -> 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) -> Cow<'_, D> { self.as_ref().embedded() }
fn annotations(&self) -> Option<&[Box<dyn Value<D>>]> { self.as_ref().annotations() }
}
impl<'a, D: Domain> Hash for dyn Value<D> + 'a {
fn hash<H: Hasher>(&self, state: &mut H) {
match self.value_class() {
ValueClass::Atomic(a) => match a {
AtomClass::Boolean => self.as_boolean().unwrap().hash(state),
AtomClass::Float => self.as_float().unwrap().to_bits().hash(state),
AtomClass::Double => self.as_double().unwrap().to_bits().hash(state),
AtomClass::SignedInteger => self.as_signed_integer().unwrap().hash(state),
AtomClass::String => self.as_string().unwrap().hash(state),
AtomClass::ByteString => self.as_bytestring().unwrap().hash(state),
AtomClass::Symbol => self.as_symbol().unwrap().hash(state),
}
ValueClass::Compound(c) => match c {
CompoundClass::Sequence |
CompoundClass::Set => {
state.write_usize(self.len());
for v in self.iter() { v.hash(state) }
}
CompoundClass::Record => {
self.label().hash(state);
state.write_usize(self.len());
for v in self.iter() { v.hash(state) }
}
CompoundClass::Dictionary => {
state.write_usize(self.len());
for (k, v) in self.entries() {
k.hash(state);
v.hash(state);
}
}
}
ValueClass::Embedded => self.embedded().hash(state),
}
}
}
fn iters_eq<'a, D: Domain>(
mut i1: Box<dyn Iterator<Item = &dyn Value<D>> + 'a>,
mut i2: Box<dyn Iterator<Item = &dyn Value<D>> + 'a>,
) -> bool {
loop {
match i1.next() {
None => return i2.next().is_none(),
Some(v1) => match i2.next() {
None => return false,
Some(v2) => if v1 != v2 { return false; },
}
}
}
}
impl<'a, D: Domain> PartialEq for dyn Value<D> + 'a {
fn eq(&self, other: &Self) -> bool {
let cls = self.value_class();
if cls != other.value_class() { return false; }
match cls {
ValueClass::Atomic(a) => match a {
AtomClass::Boolean =>
self.as_boolean().unwrap() == other.as_boolean().unwrap(),
AtomClass::Float =>
eq_f32(self.as_float().unwrap(), other.as_float().unwrap()),
AtomClass::Double =>
eq_f64(self.as_double().unwrap(), other.as_double().unwrap()),
AtomClass::SignedInteger =>
self.as_signed_integer().unwrap() == other.as_signed_integer().unwrap(),
AtomClass::String =>
self.as_string().unwrap() == other.as_string().unwrap(),
AtomClass::ByteString =>
self.as_bytestring().unwrap() == other.as_bytestring().unwrap(),
AtomClass::Symbol =>
self.as_symbol().unwrap() == other.as_symbol().unwrap(),
}
ValueClass::Compound(c) => match c {
CompoundClass::Record => {
if self.label() != other.label() { return false; }
iters_eq(self.iter(), other.iter())
}
CompoundClass::Sequence => {
iters_eq(self.iter(), other.iter())
}
CompoundClass::Set => {
let s1 = self.iter().collect::<Set<_>>();
let s2 = other.iter().collect::<Set<_>>();
s1 == s2
}
CompoundClass::Dictionary => {
let d1 = self.entries().collect::<Map<_, _>>();
let d2 = other.entries().collect::<Map<_, _>>();
d1 == d2
}
}
ValueClass::Embedded => self.embedded() == other.embedded(),
}
}
}
fn iters_cmp<'a, D: Domain>(
mut i1: Box<dyn Iterator<Item = &dyn Value<D>> + 'a>,
mut i2: Box<dyn Iterator<Item = &dyn Value<D>> + 'a>,
) -> Ordering {
loop {
match i1.next() {
None => match i2.next() {
None => return Ordering::Equal,
Some(_) => return Ordering::Less,
}
Some(v1) => match i2.next() {
None => return Ordering::Greater,
Some(v2) => match v1.cmp(v2) {
Ordering::Equal => (),
other => return other,
}
}
}
}
}
impl<'a, D: Domain> Ord for dyn Value<D> + 'a {
fn cmp(&self, other: &Self) -> Ordering {
let cls = self.value_class();
cls.cmp(&other.value_class()).then_with(|| match cls {
ValueClass::Atomic(a) => match a {
AtomClass::Boolean =>
self.as_boolean().cmp(&other.as_boolean()),
AtomClass::Float =>
cmp_f32(self.as_float().unwrap(), other.as_float().unwrap()),
AtomClass::Double =>
cmp_f64(self.as_double().unwrap(), other.as_double().unwrap()),
AtomClass::SignedInteger =>
self.as_signed_integer().cmp(&other.as_signed_integer()),
AtomClass::String =>
self.as_string().cmp(&other.as_string()),
AtomClass::ByteString =>
self.as_bytestring().cmp(&other.as_bytestring()),
AtomClass::Symbol =>
self.as_symbol().cmp(&other.as_symbol()),
},
ValueClass::Compound(c) => match c {
CompoundClass::Record =>
self.label().cmp(other.label()).then_with(
|| iters_cmp(self.iter(), other.iter())),
CompoundClass::Sequence => iters_cmp(self.iter(), other.iter()),
CompoundClass::Set => {
let s1 = self.iter().collect::<Set<_>>();
let s2 = other.iter().collect::<Set<_>>();
s1.cmp(&s2)
}
CompoundClass::Dictionary => {
let d1 = self.entries().collect::<Map<_, _>>();
let d2 = other.entries().collect::<Map<_, _>>();
d1.cmp(&d2)
}
},
ValueClass::Embedded => self.embedded().cmp(&other.embedded()),
})
}
}
impl<'a, D: Domain> Eq for dyn Value<D> + 'a {}
impl<'a, D: Domain> PartialOrd for dyn Value<D> + 'a {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum NoValue {}
impl Domain for NoValue {}
impl<D: Domain> Value<D> for NoValue {
fn value_class(&self) -> ValueClass { unreachable!() }
}
impl<D: Domain> Value<D> for bool {
fn value_class(&self) -> ValueClass { ValueClass::Atomic(AtomClass::Boolean) }
fn as_boolean(&self) -> Option<bool> { Some(*self) }
}
impl<D: Domain> Value<D> for u64 {
fn value_class(&self) -> ValueClass { ValueClass::Atomic(AtomClass::SignedInteger) }
fn as_signed_integer(&self) -> Option<SignedInteger> {
Some((*self).into())
}
}
impl<D: Domain> Value<D> for f32 {
fn value_class(&self) -> ValueClass { ValueClass::Atomic(AtomClass::Float) }
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 {
fn value_class(&self) -> ValueClass { ValueClass::Atomic(AtomClass::String) }
fn as_string(&self) -> Option<Cow<'_, str>> { Some(Cow::Borrowed(self)) }
}
impl<D: Domain> Value<D> for String {
fn value_class(&self) -> ValueClass { ValueClass::Atomic(AtomClass::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 }
fn len(&self) -> usize { self.len() }
fn index(&self, i: usize) -> &dyn Value<D> { &self[i] }
fn iter(&self) -> Box<dyn Iterator<Item = &dyn Value<D>> + '_> {
Box::new(self[..].iter().map(value))
}
}
impl<D: Domain, V: Value<D>> Value<D> for [V] {
fn value_class(&self) -> ValueClass { ValueClass::Compound(CompoundClass::Sequence) }
fn is_sequence(&self) -> bool { true }
fn len(&self) -> usize { self.len() }
fn index(&self, i: usize) -> &dyn Value<D> { &self[i] }
fn iter(&self) -> Box<dyn Iterator<Item = &dyn Value<D>> + '_> {
Box::new(self[..].iter().map(value))
}
}
impl<D: Domain> Value<D> for Set<Box<dyn Value<D>>> {
fn value_class(&self) -> ValueClass { ValueClass::Compound(CompoundClass::Set) }
fn is_set(&self) -> bool { true }
fn len(&self) -> usize { self.len() }
fn has(&self, v: &dyn Value<D>) -> bool { self.contains(v) }
fn iter(&self) -> Box<dyn Iterator<Item = &dyn Value<D>> + '_> {
Box::new(self.iter().map(value))
}
}
#[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) -> usize { self.len() }
fn has(&self, v: &dyn Value<D>) -> bool { self.contains_key(v) }
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,
}
}
fn entries(&self) -> Box<dyn Iterator<Item = (&dyn Value<D>, &dyn Value<D>)> + '_> {
Box::new(self.iter().map(|(k,v)| (value(k), value(v))))
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[repr(transparent)]
pub struct Embedded<D: Domain>(D);
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)]
pub struct Annotations<D: Domain, V: Value<D>>(V, Vec<Box<dyn Value<D>>>);
impl<D: Domain, V: Value<D>> Annotations<D, V> {
pub fn value(&self) -> &dyn Value<D> {
&self.0
}
}
impl<D: Domain, V: Value<D>> Value<D> for Annotations<D, V> {
fn value_class(&self) -> ValueClass { self.value().value_class() }
fn as_boolean(&self) -> Option<bool> { self.value().as_boolean() }
fn as_float(&self) -> Option<f32> { self.value().as_float() }
fn as_double(&self) -> Option<f64> { self.value().as_double() }
fn is_signed_integer(&self) -> bool { self.value().is_signed_integer() }
fn as_signed_integer(&self) -> Option<SignedInteger> { self.value().as_signed_integer() }
fn as_string(&self) -> Option<Cow<'_, str>> { self.value().as_string() }
fn as_bytestring(&self) -> Option<Cow<'_, [u8]>> { self.value().as_bytestring() }
fn as_symbol(&self) -> Option<Cow<'_, str>> { self.value().as_symbol() }
fn is_record(&self) -> bool { self.value().is_record() }
fn label(&self) -> &dyn Value<D> { self.value().label() }
fn is_sequence(&self) -> bool { self.value().is_sequence() }
fn len(&self) -> usize { self.value().len() }
fn index(&self, i: usize) -> &dyn Value<D> { self.value().index(i) }
fn iter(&self) -> Box<dyn Iterator<Item = &dyn Value<D>> + '_> { self.value().iter() }
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>) -> Option<&dyn Value<D>> { self.value().get(k) }
fn entries(&self) -> 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) -> Cow<'_, D> { self.value().embedded() }
fn annotations(&self) -> Option<&[Box<dyn Value<D>>]> { Some(&self.1) }
}
impl<D: Domain, V: Value<D>> PartialEq for Annotations<D, V> {
fn eq(&self, other: &Self) -> bool {
self.value().eq(&other.value())
}
}
impl<D: Domain, V: Value<D>> Eq for Annotations<D, V> {}
impl<D: Domain, V: Value<D>> Hash for Annotations<D, V> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.value().hash(state);
}
}
impl<D: Domain, V: Value<D>> PartialOrd for Annotations<D, V> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl<D: Domain, V: Value<D>> Ord for Annotations<D, V> {
fn cmp(&self, other: &Self) -> Ordering {
self.value().cmp(&other.value())
}
}
#[cfg(test)]
mod demo {
use crate::*;
fn getit<'a>(d: &'a dyn Value<NoValue>, k: &str) -> Option<&'a dyn Value<NoValue>> {
d.get(&k)
}
#[test] fn a() {
let l = Symbol("label");
let r = Record::new(owned::<NoValue, _>(l.clone()), vec![owned(1), owned(2), owned(3)]);
let r2 = Record::new(owned::<NoValue, _>(l), vec![owned(1), owned(2), owned(4)]);
let mut v: Map<Box<dyn Value<NoValue>>, String> = Map::new();
v.insert(Box::new("abc"), "def".to_owned());
v.insert(Box::new(123), "xyz".to_owned());
v.insert(Box::new(vec![1, 2, 3]), "www".to_owned());
v.insert(Box::new(r2), "bbb".to_owned());
v.insert(Box::new(r), "aaa".to_owned());
let w: &dyn Value<NoValue> = &v;
println!("GETw abc {:?}", w.get(&"abc"));
println!("GETw 123 {:?}", w.get(&123));
println!("GETw qqq {:?}", w.get(&"qqq"));
println!("GETv abc {:?}", v.get(value(&"abc")));
println!("GETv 123 {:?}", v.get(value(&123)));
println!("GETv qqq {:?}", v.get(value(&"qqq")));
for (kk, vv) in w.entries() {
println!("{:?} {:?} ==> {:?} {:?}", kk.value_class(), kk, vv.value_class(), vv);
}
// {
// use std::io::BufRead;
// for line in std::io::stdin().lock().lines() {
// let line = line.unwrap();
// let val = w.get(&line);
// println!("{:?} ==> {:?} == {:?}", line, val, getit(&v, &line));
// }
// }
}
}