Experimental WIP

This commit is contained in:
Tony Garnock-Jones 2022-11-16 15:43:49 +01:00
parent ce9d4f2f0c
commit c053e2b9dd
10 changed files with 671 additions and 859 deletions

View File

@ -13,7 +13,7 @@ gitlab = { repository = "preserves/preserves" }
[dependencies]
base64 = "0.13"
bytemuck = "1.12"
bytemuck = { version = "1.12", features = ["extern_crate_alloc"] }
dtoa = "0.4"
lazy_static = "1.4.0"
num-bigint = "0.4"

View File

@ -6,7 +6,6 @@ use std::io;
pub enum Error {
Io(io::Error),
Message(String),
InvalidUnicodeScalar(u32),
NumberOutOfRange(BigInt),
MissingCloseDelimiter,
MissingItem,
@ -34,8 +33,6 @@ pub enum ExpectedKind {
Embedded,
Option,
UnicodeScalar,
Annotation,
}

View File

@ -3,53 +3,49 @@ pub mod domain;
pub mod error;
pub mod float;
pub mod hex;
pub mod packed;
pub mod merge;
// pub mod packed;
pub mod reader;
pub mod repr;
pub mod signed_integer;
pub mod source;
pub mod text;
// pub mod text;
pub mod types;
pub mod writer;
pub use domain::*;
pub use packed::PackedReader;
pub use packed::PackedWriter;
pub use packed::annotated_from_bytes;
pub use packed::annotated_iovalue_from_bytes;
pub use packed::from_bytes;
pub use packed::iovalue_from_bytes;
pub use error::Error;
pub use error::ExpectedKind;
pub use merge::merge;
pub use merge::merge2;
// pub use packed::PackedReader;
// pub use packed::PackedWriter;
// pub use packed::annotated_from_bytes;
// pub use packed::annotated_iovalue_from_bytes;
// pub use packed::from_bytes;
// pub use packed::iovalue_from_bytes;
pub use reader::IOValues;
pub use reader::Reader;
pub use repr::Annotations;
pub use repr::ArcValue;
pub use repr::Atom;
pub use repr::Bytes;
pub use repr::Embedded;
pub use repr::IOValue;
pub use repr::Map;
pub use repr::PlainValue;
pub use repr::NoValue;
pub use repr::Record;
pub use repr::Set;
pub use repr::Symbol;
pub use repr::Value;
pub use repr::ValueImpl;
pub use repr::copy_via;
pub use repr::iovalue;
pub use repr::owned;
pub use repr::shell;
pub use repr::value;
pub use signed_integer::SignedInteger;
pub use source::BinarySource;
pub use source::BytesBinarySource;
pub use source::IOBinarySource;
pub use text::TextReader;
pub use text::TextWriter;
pub use text::annotated_from_str;
pub use text::annotated_iovalue_from_str;
pub use text::from_str;
pub use text::iovalue_from_str;
// pub use text::TextReader;
// pub use text::TextWriter;
// pub use text::annotated_from_str;
// pub use text::annotated_iovalue_from_str;
// pub use text::from_str;
// pub use text::iovalue_from_str;
pub use types::AtomClass;
pub use types::CompoundClass;
pub use types::ValueClass;
@ -64,45 +60,45 @@ mod demo {
// d.get(&k)
// }
#[test] fn a() {
let l: PlainValue<NoValue> = "label".parse().unwrap();
let r = Record::new(l.value_clone(), vec![owned(1), owned(2), owned(3)]);
let r2 = Record::new(l, vec![owned(1), owned(2), owned(4)]);
// #[test] fn a() {
// let l: PlainValue<NoValue> = "label".parse().unwrap();
// let r = Record::new(l.value_clone(), vec![owned(1), owned(2), owned(3)]);
// let r2 = Record::new(l, vec![owned(1), owned(2), owned(4)]);
let mut v: Map<PlainValue<NoValue>, PlainValue<NoValue>> = Map::new();
v.insert("\"abc\"".parse().unwrap(), "def".parse().unwrap());
v.insert("abc".parse().unwrap(), "DEF".parse().unwrap());
v.insert(owned(123), "xyz".parse().unwrap());
v.insert(owned(vec![1, 2, 3]), "{a: 1, b: 2}".parse().unwrap());
v.insert(owned(r2), "bbb".parse().unwrap());
v.insert(owned(r), "<foo bar zot>".parse().unwrap());
let w: &dyn ValueImpl<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, vv);
}
// let mut v: Map<PlainValue<NoValue>, PlainValue<NoValue>> = Map::new();
// v.insert("\"abc\"".parse().unwrap(), "def".parse().unwrap());
// v.insert("abc".parse().unwrap(), "DEF".parse().unwrap());
// v.insert(owned(123), "xyz".parse().unwrap());
// v.insert(owned(vec![1, 2, 3]), "{a: 1, b: 2}".parse().unwrap());
// v.insert(owned(r2), "bbb".parse().unwrap());
// v.insert(owned(r), "<foo bar zot>".parse().unwrap());
// let w: &dyn ValueImpl<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, vv);
// }
// {
// use std::io::BufRead;
// for line in std::io::stdin().lock().lines() {
// let line = line.unwrap();
// let key = line.parse::<PlainValue<NoValue>>().unwrap();
// let val = w.get(&key);
// println!("{:?} == {:?} ==> {:?} == {:?}", line, &key, val, getit(&v, &line));
// }
// }
}
// // {
// // use std::io::BufRead;
// // for line in std::io::stdin().lock().lines() {
// // let line = line.unwrap();
// // let key = line.parse::<PlainValue<NoValue>>().unwrap();
// // let val = w.get(&key);
// // println!("{:?} == {:?} ==> {:?} == {:?}", line, &key, val, getit(&v, &line));
// // }
// // }
// }
#[test] fn value_size() {
println!("Value size {}", std::mem::size_of::<Value<'_, NoValue>>());
println!("&dyn ValueImpl size {}", std::mem::size_of::<&dyn ValueImpl<NoValue>>());
println!("Box dyn ValueImpl size {}", std::mem::size_of::<Box<dyn ValueImpl<NoValue>>>());
}
// #[test] fn value_size() {
// println!("Value size {}", std::mem::size_of::<Value<'_, NoValue>>());
// println!("&dyn ValueImpl size {}", std::mem::size_of::<&dyn ValueImpl<NoValue>>());
// println!("Box dyn ValueImpl size {}", std::mem::size_of::<Box<dyn ValueImpl<NoValue>>>());
// }
}
#[cfg(test)]

View File

@ -1,64 +1,89 @@
use super::Map;
use super::NestedValue;
use super::Record;
use super::Value;
use crate::Annotations;
use crate::ArcValue;
use crate::CompoundClass;
use crate::Map;
use crate::Record;
use crate::Value;
use crate::ValueClass;
use crate::ValueImpl;
pub fn merge_seqs<N: NestedValue>(mut a: Vec<N>, mut b: Vec<N>) -> Option<Vec<N>> {
pub fn merge_seqs<V: ValueImpl, W: ValueImpl<Embedded = V::Embedded>>(
mut a: Vec<Value<V>>,
mut b: Vec<Value<W>>,
) -> Option<Vec<ArcValue<V::Embedded>>> {
if a.len() > b.len() {
std::mem::swap(&mut a, &mut b);
}
let mut r = vec![];
let mut bi = b.into_iter();
for av in a.into_iter() {
r.push(merge2(av, bi.next().unwrap())?);
r.push(merge2(&*av, &*bi.next().unwrap())?);
}
r.extend(bi);
r.extend(bi.map(|bv| bv.value_clone()));
Some(r)
}
pub fn merge2<N: NestedValue>(v: N, w: N) -> Option<N> {
let (mut v_anns, v_val) = v.pieces();
let (w_anns, w_val) = w.pieces();
match &mut v_anns {
None => v_anns = w_anns,
Some(vs) => match w_anns {
None => (),
Some(ws) => vs.extend(ws.into_iter()),
pub fn merge2<V: ValueImpl, W: ValueImpl<Embedded = V::Embedded>>(v: &Value<V>, w: &Value<W>) -> Option<ArcValue<V::Embedded>> {
let anns = match (v.annotations(), w.annotations()) {
(Some(va), Some(wa)) => {
let mut a = va.to_vec();
a.extend(wa.to_vec());
a
}
}
if v_val == w_val {
Some(N::wrap(v_anns, v_val))
(Some(va), None) => va.to_vec(),
(None, Some(wa)) => wa.to_vec(),
(None, None) => vec![],
};
let r = if v == w {
Some(v.peeled().value_clone())
} else {
let maybe_merged = match v_val {
Value::Record(rv) =>
Some(Value::Record(Record(merge_seqs(rv.0, w_val.into_record()?.0)?))),
Value::Sequence(vs) =>
Some(Value::Sequence(merge_seqs(vs, w_val.into_sequence()?)?)),
Value::Set(_vs) =>
match v.value_class() {
ValueClass::Atomic(_) => None,
ValueClass::Embedded => None,
ValueClass::Compound(CompoundClass::Record) => if w.is_record() {
todo!()
// Some(owned(Record::new(merge2(&*v.label(), &*w.label())?,
// merge_seqs(v.iter().collect(), w.iter().collect())?)))
} else {
None
}
ValueClass::Compound(CompoundClass::Sequence) => if w.is_sequence() {
Some(owned(merge_seqs(v.iter().collect(), w.iter().collect())?))
} else {
None
}
ValueClass::Compound(CompoundClass::Set) =>
None, // unsure how to merge sets
Value::Dictionary(vs) => {
let mut ws = w_val.into_dictionary()?;
ValueClass::Compound(CompoundClass::Dictionary) => if w.is_dictionary() {
let mut ws: Map<_, _> = w.entries().collect();
let mut rs = Map::new();
for (k, vv) in vs.into_iter() {
for (k, vv) in v.entries() {
match ws.remove(&k) {
Some(wv) => { rs.insert(k, merge2(vv, wv)?); }
None => { rs.insert(k, vv); }
Some(wv) => { rs.insert(k.value_clone(), merge2(&*vv, &*wv)?); }
None => { rs.insert(k.value_clone(), vv.value_clone()); }
}
}
rs.extend(ws.into_iter());
Some(Value::Dictionary(rs))
rs.extend(ws.into_iter().map(|(k, wv)| (k.value_clone(), wv.value_clone())));
Some(owned(rs))
} else {
None
}
_ => None,
};
maybe_merged.map(|vw| N::wrap(v_anns, vw))
}
}
};
r.map(|r| if anns.is_empty() {
r
} else {
owned(Annotations::new(r, anns))
})
}
pub fn merge<N: NestedValue, I: IntoIterator<Item = N>>(vs: I) -> Option<N> {
pub fn merge<V: ValueImpl, I: IntoIterator<Item = Value<V>>>(vs: I) -> Option<ArcValue<V::Embedded>> {
let mut vs = vs.into_iter();
let mut v = vs.next().expect("at least one value in merge()");
let mut v = vs.next().expect("at least one value in merge()").value_clone();
for w in vs {
match merge2(v, w) {
match merge2(&*v, &*w) {
Some(merged) => v = merged,
None => return None,
}

View File

@ -1,6 +1,6 @@
pub mod constants;
pub mod reader;
pub mod view;
// pub mod view;
pub mod writer;
pub use reader::PackedReader;

View File

@ -4,7 +4,7 @@ use std::convert::TryInto;
use std::io;
use std::io::Write;
use super::constants::Tag;
use crate::{boundary as B, ValueImpl, Domain, DomainEncode, IOValue, IOValueDomainCodec, Writer};
use crate::{boundary as B, ValueImpl, DomainEncode, IOValue, IOValueDomainCodec, Writer};
struct Buffers<W: io::Write> {
base: W,
@ -36,9 +36,9 @@ pub struct PackedWriter<W: io::Write>(Buffers<W>);
impl PackedWriter<&mut Vec<u8>> {
#[inline(always)]
pub fn encode<D: Domain, Enc: DomainEncode<D>>(
pub fn encode<V: ValueImpl, Enc: DomainEncode<V::Embedded>>(
enc: &mut Enc,
v: &dyn ValueImpl<D>,
v: &V,
) -> io::Result<Vec<u8>> {
let mut buf: Vec<u8> = Vec::new();
v.write(&mut PackedWriter::new(&mut buf), enc)?;

File diff suppressed because it is too large Load Diff

View File

@ -7,8 +7,17 @@ use std::convert::TryFrom;
use std::convert::TryInto;
use std::fmt;
#[derive(Debug)]
pub struct OutOfRange(pub BigInt);
impl fmt::Display for OutOfRange {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "The value {:?} is out of range", &self.0)
}
}
impl std::error::Error for OutOfRange {}
impl From<OutOfRange> for crate::error::Error {
fn from(e: OutOfRange) -> Self {
crate::error::Error::NumberOutOfRange(e.0)

View File

@ -1,4 +1,3 @@
use crate::Domain;
use crate::DomainEncode;
use crate::IOValue;
use crate::IOValueDomainCodec;
@ -36,10 +35,10 @@ impl std::default::Default for CommaStyle {
}
impl TextWriter<&mut Vec<u8>> {
pub fn fmt_value<D: Domain, Enc: DomainEncode<D>>(
pub fn fmt_value<V: ValueImpl, Enc: DomainEncode<V::Embedded>>(
f: &mut std::fmt::Formatter<'_>,
enc: &mut Enc,
v: &dyn ValueImpl<D>,
v: &V,
) -> io::Result<()> {
let mut buf: Vec<u8> = Vec::new();
let mut w = TextWriter::new(&mut buf);
@ -49,9 +48,9 @@ impl TextWriter<&mut Vec<u8>> {
|_| io::Error::new(io::ErrorKind::Other, "could not append to Formatter"))
}
pub fn encode<D: Domain, Enc: DomainEncode<D>>(
pub fn encode<V: ValueImpl, Enc: DomainEncode<V::Embedded>>(
enc: &mut Enc,
v: &dyn ValueImpl<D>,
v: &V,
) -> io::Result<String> {
let mut buf: Vec<u8> = Vec::new();
v.write(&mut TextWriter::new(&mut buf), enc)?;

View File

@ -3,7 +3,6 @@ use std::io;
use crate::AtomClass;
use crate::CompoundClass;
use crate::Domain;
use crate::DomainEncode;
use crate::IOValueDomainCodec;
use crate::SignedInteger;
@ -70,10 +69,10 @@ pub trait Writer {
fn specialized(&mut self) -> Option<(&str, &mut dyn io::Write)> { None }
}
pub fn write_value<D: Domain, V: ValueImpl<D>>(
pub fn write_value<V: ValueImpl>(
w: &mut dyn Writer,
v: V,
enc: &mut dyn DomainEncode<D>,
v: &V,
enc: &mut dyn DomainEncode<V::Embedded>,
) -> io::Result<()> {
let annotations = v.annotations();
let mut annotation_b = B::Type::default();