use num::bigint::BigInt; use std::io; use super::DomainEncode; use super::signed_integer::SignedIntegerRepr; use super::repr::{Embeddable, Value, NestedValue, Float, Double}; pub trait AnnotationWriter: Writer { fn start_annotation(&mut self) -> io::Result<()>; fn start_value(&mut self) -> io::Result<()>; } pub trait CompoundWriter: Writer { fn extend(&mut self) -> io::Result<()>; fn delimit(&mut self) -> io::Result<()>; } pub trait Writer: Sized { type AnnWriter: AnnotationWriter; type SeqWriter: CompoundWriter; type SetWriter: CompoundWriter; type EmbeddedWriter: Writer; fn align(&mut self, natural_chunksize: u64) -> io::Result<()>; fn start_annotations(&mut self) -> io::Result; fn end_annotations(&mut self, ann: Self::AnnWriter) -> io::Result<()>; fn write_bool(&mut self, v: bool) -> io::Result<()>; fn write_f32(&mut self, v: f32) -> io::Result<()>; fn write_f64(&mut self, v: f64) -> io::Result<()>; fn write_i8(&mut self, v: i8) -> io::Result<()>; fn write_u8(&mut self, v: u8) -> io::Result<()>; fn write_i16(&mut self, v: i16) -> io::Result<()>; fn write_u16(&mut self, v: u16) -> io::Result<()>; fn write_i32(&mut self, v: i32) -> io::Result<()>; fn write_u32(&mut self, v: u32) -> io::Result<()>; fn write_i64(&mut self, v: i64) -> io::Result<()>; fn write_u64(&mut self, v: u64) -> io::Result<()>; fn write_i128(&mut self, v: i128) -> io::Result<()>; fn write_u128(&mut self, v: u128) -> io::Result<()>; fn write_int(&mut self, v: &BigInt) -> io::Result<()>; fn write_string(&mut self, v: &str) -> io::Result<()>; fn write_bytes(&mut self, v: &[u8]) -> io::Result<()>; fn write_symbol(&mut self, v: &str) -> io::Result<()>; fn start_record(&mut self, field_count: Option) -> io::Result; fn start_sequence(&mut self, item_count: Option) -> io::Result; fn end_seq(&mut self, seq: Self::SeqWriter) -> io::Result<()>; fn start_set(&mut self, item_count: Option) -> io::Result; fn start_dictionary(&mut self, entry_count: Option) -> io::Result; fn end_set(&mut self, set: Self::SetWriter) -> io::Result<()>; fn start_embedded(&mut self) -> io::Result; fn end_embedded(&mut self, ptr: Self::EmbeddedWriter) -> io::Result<()>; //--------------------------------------------------------------------------- fn write, Enc: DomainEncode>( &mut self, enc: &mut Enc, v: &N, ) -> io::Result<()> { match v.annotations().maybe_slice() { None => { self.write_value(enc, v.value())?; } Some(anns) => { let mut a = self.start_annotations()?; for ann in anns { a.start_annotation()?; a.write(enc, ann)?; } a.start_value()?; a.write_value(enc, v.value())?; self.end_annotations(a)?; } } Ok(()) } fn write_value, Enc: DomainEncode>( &mut self, enc: &mut Enc, v: &Value, ) -> io::Result<()> { match v { Value::Boolean(b) => self.write_bool(*b), Value::Float(Float(f)) => self.write_f32(*f), Value::Double(Double(d)) => self.write_f64(*d), Value::SignedInteger(n) => match n.repr() { SignedIntegerRepr::I128(i) => self.write_i128(*i), SignedIntegerRepr::U128(u) => self.write_u128(*u), SignedIntegerRepr::Big(n) => self.write_int(n), } Value::String(s) => self.write_string(s), Value::ByteString(bs) => self.write_bytes(bs), Value::Symbol(s) => self.write_symbol(s), Value::Record(r) => { let mut c = self.start_record(Some(r.arity()))?; c.extend()?; c.write(enc, r.label())?; c.delimit()?; for f in r.fields() { c.extend()?; c.write(enc, f)?; c.delimit()?; } self.end_seq(c) } Value::Sequence(vs) => { let mut c = self.start_sequence(Some(vs.len()))?; for v in vs { c.extend()?; c.write(enc, v)?; c.delimit()?; } self.end_seq(c) } Value::Set(vs) => { let mut c = self.start_set(Some(vs.len()))?; for v in vs { c.extend()?; c.write(enc, v)?; c.delimit()?; } self.end_set(c) } Value::Dictionary(vs) => { let mut c = self.start_dictionary(Some(vs.len()))?; for (k, v) in vs { c.extend()?; c.write(enc, k)?; c.write(enc, v)?; c.delimit()?; } self.end_set(c) } Value::Embedded(d) => { let mut c = self.start_embedded()?; enc.encode_embedded(&mut c, d)?; self.end_embedded(c) } } } } pub fn varint(w: &mut W, mut v: u64) -> io::Result { let mut byte_count = 0; loop { byte_count += 1; if v < 128 { w.write_all(&[v as u8])?; return Ok(byte_count); } else { w.write_all(&[((v & 0x7f) + 128) as u8])?; v >>= 7; } } }