//! Generic [Writer] trait for unparsing Preserves [Value]s, implemented by code that provides //! each specific transfer syntax. use super::boundary as B; use super::repr::{Double, NestedValue, Value}; use super::signed_integer::SignedIntegerRepr; use super::DomainEncode; use num::bigint::BigInt; use std::io; #[doc(hidden)] /// Utility trait for tracking unparser state during production of compound `Value`s. pub trait CompoundWriter: Writer { fn boundary(&mut self, b: &B::Type) -> io::Result<()>; } /// Generic unparser for Preserves. pub trait Writer: Sized { // Hiding these from the documentation for the moment because I don't want to have to // document the whole Boundary thing. #[doc(hidden)] type AnnWriter: CompoundWriter; #[doc(hidden)] type RecWriter: CompoundWriter; #[doc(hidden)] type SeqWriter: CompoundWriter; #[doc(hidden)] type SetWriter: CompoundWriter; #[doc(hidden)] type DictWriter: CompoundWriter; #[doc(hidden)] type EmbeddedWriter: Writer; #[doc(hidden)] fn start_annotations(&mut self) -> io::Result; #[doc(hidden)] fn end_annotations(&mut self, ann: Self::AnnWriter) -> io::Result<()>; #[doc(hidden)] fn write_bool(&mut self, v: bool) -> io::Result<()>; #[doc(hidden)] fn write_f64(&mut self, v: f64) -> io::Result<()>; #[doc(hidden)] fn write_i8(&mut self, v: i8) -> io::Result<()>; #[doc(hidden)] fn write_u8(&mut self, v: u8) -> io::Result<()>; #[doc(hidden)] fn write_i16(&mut self, v: i16) -> io::Result<()>; #[doc(hidden)] fn write_u16(&mut self, v: u16) -> io::Result<()>; #[doc(hidden)] fn write_i32(&mut self, v: i32) -> io::Result<()>; #[doc(hidden)] fn write_u32(&mut self, v: u32) -> io::Result<()>; #[doc(hidden)] fn write_i64(&mut self, v: i64) -> io::Result<()>; #[doc(hidden)] fn write_u64(&mut self, v: u64) -> io::Result<()>; #[doc(hidden)] fn write_i128(&mut self, v: i128) -> io::Result<()>; #[doc(hidden)] fn write_u128(&mut self, v: u128) -> io::Result<()>; #[doc(hidden)] fn write_int(&mut self, v: &BigInt) -> io::Result<()>; #[doc(hidden)] fn write_string(&mut self, v: &str) -> io::Result<()>; #[doc(hidden)] fn write_bytes(&mut self, v: &[u8]) -> io::Result<()>; #[doc(hidden)] fn write_symbol(&mut self, v: &str) -> io::Result<()>; #[doc(hidden)] fn start_record(&mut self, field_count: Option) -> io::Result; #[doc(hidden)] fn end_record(&mut self, rec: Self::RecWriter) -> io::Result<()>; #[doc(hidden)] fn start_sequence(&mut self, item_count: Option) -> io::Result; #[doc(hidden)] fn end_sequence(&mut self, seq: Self::SeqWriter) -> io::Result<()>; #[doc(hidden)] fn start_set(&mut self, item_count: Option) -> io::Result; #[doc(hidden)] fn end_set(&mut self, set: Self::SetWriter) -> io::Result<()>; #[doc(hidden)] fn start_dictionary(&mut self, entry_count: Option) -> io::Result; #[doc(hidden)] fn end_dictionary(&mut self, dict: Self::DictWriter) -> io::Result<()>; #[doc(hidden)] fn start_embedded(&mut self) -> io::Result; #[doc(hidden)] fn end_embedded(&mut self, ptr: Self::EmbeddedWriter) -> io::Result<()>; /// Flushes any buffered output. fn flush(&mut self) -> io::Result<()>; //--------------------------------------------------------------------------- /// Writes [NestedValue] `v` to the output of this [Writer]. fn write>( &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()?; let mut b = B::Type::default(); for ann in anns { b.shift(Some(B::Item::Annotation)); a.boundary(&b)?; a.write(enc, ann)?; } b.shift(Some(B::Item::AnnotatedValue)); a.boundary(&b)?; a.write_value(enc, v.value())?; b.shift(None); a.boundary(&b)?; self.end_annotations(a)?; } } Ok(()) } /// Writes [Value] `v` to the output of this [Writer]. fn write_value>( &mut self, enc: &mut Enc, v: &Value, ) -> io::Result<()> { match v { Value::Boolean(b) => self.write_bool(*b), 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()))?; let mut b = B::start(B::Item::RecordLabel); c.boundary(&b)?; c.write(enc, r.label())?; for f in r.fields() { b.shift(Some(B::Item::RecordField)); c.boundary(&b)?; c.write(enc, f)?; } b.shift(None); c.boundary(&b)?; self.end_record(c) } Value::Sequence(vs) => { let mut c = self.start_sequence(Some(vs.len()))?; let mut b = B::Type::default(); for v in vs { b.shift(Some(B::Item::SequenceValue)); c.boundary(&b)?; c.write(enc, v)?; } b.shift(None); c.boundary(&b)?; self.end_sequence(c) } Value::Set(vs) => { let mut c = self.start_set(Some(vs.len()))?; let mut b = B::Type::default(); for v in vs { b.shift(Some(B::Item::SetValue)); c.boundary(&b)?; c.write(enc, v)?; } b.shift(None); c.boundary(&b)?; self.end_set(c) } Value::Dictionary(vs) => { let mut c = self.start_dictionary(Some(vs.len()))?; let mut b = B::Type::default(); for (k, v) in vs { b.shift(Some(B::Item::DictionaryKey)); c.boundary(&b)?; c.write(enc, k)?; b.shift(Some(B::Item::DictionaryValue)); c.boundary(&b)?; c.write(enc, v)?; } b.shift(None); c.boundary(&b)?; self.end_dictionary(c) } Value::Embedded(d) => { let mut c = self.start_embedded()?; enc.encode_embedded(&mut c, d)?; self.end_embedded(c) } } } } /// Writes a [varint](https://protobuf.dev/programming-guides/encoding/#varints) to `w`. /// Returns the number of bytes written. /// /// ```text /// varint(n) = [n] if n < 128 /// [(n & 127) | 128] ++ varint(n >> 7) if n ≥ 128 /// ``` 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; } } }