use num_bigint::BigInt; use std::io; use crate::AtomClass; use crate::CompoundClass; use crate::Domain; use crate::DomainEncode; use crate::IOValueDomainCodec; use crate::SignedInteger; use crate::ValueClass; use crate::boundary as B; use crate::signed_integer::SignedIntegerRepr; use crate::ValueImpl; pub trait Writer { fn boundary(&mut self, b: &B::Type) -> io::Result<()>; fn start_annotations(&mut self) -> io::Result<()>; fn end_annotations(&mut self) -> 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_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) -> io::Result<()>; fn end_record(&mut self) -> io::Result<()>; fn start_sequence(&mut self) -> io::Result<()>; fn end_sequence(&mut self) -> io::Result<()>; fn start_set(&mut self) -> io::Result<()>; fn end_set(&mut self) -> io::Result<()>; fn start_dictionary(&mut self) -> io::Result<()>; fn end_dictionary(&mut self) -> io::Result<()>; fn start_embedded(&mut self) -> io::Result<()>; fn end_embedded(&mut self) -> io::Result<()>; fn flush(&mut self) -> io::Result<()>; //--------------------------------------------------------------------------- fn write_i8(&mut self, v: i8) -> io::Result<()> { self.write_i128(v as i128) } fn write_u8(&mut self, v: u8) -> io::Result<()> { self.write_u128(v as u128) } fn write_i16(&mut self, v: i16) -> io::Result<()> { self.write_i128(v as i128) } fn write_u16(&mut self, v: u16) -> io::Result<()> { self.write_u128(v as u128) } fn write_i32(&mut self, v: i32) -> io::Result<()> { self.write_i128(v as i128) } fn write_u32(&mut self, v: u32) -> io::Result<()> { self.write_u128(v as u128) } fn write_i64(&mut self, v: i64) -> io::Result<()> { self.write_i128(v as i128) } fn write_u64(&mut self, v: u64) -> io::Result<()> { self.write_u128(v as u128) } fn write_signed_integer(&mut self, v: &SignedInteger) -> io::Result<()> { match v.repr() { SignedIntegerRepr::I128(i) => self.write_i128(*i), SignedIntegerRepr::U128(u) => self.write_u128(*u), SignedIntegerRepr::Big(n) => self.write_int(n), } } fn specialized(&mut self) -> Option<(&str, &mut dyn io::Write)> { None } } pub fn write_value( w: &mut dyn Writer, v: &dyn ValueImpl, enc: &mut dyn DomainEncode, ) -> io::Result<()> { let annotations = v.annotations(); let mut annotation_b = B::Type::default(); let has_annotations = if let Some(anns) = annotations { if anns.is_empty() { false } else { w.start_annotations()?; for ann in &anns[..] { annotation_b.shift(Some(B::Item::Annotation)); w.boundary(&annotation_b)?; ann.write(w, &mut IOValueDomainCodec)?; } annotation_b.shift(Some(B::Item::AnnotatedValue)); w.boundary(&annotation_b)?; true } } else { false }; match v.value_class() { ValueClass::Atomic(a) => match a { AtomClass::Boolean => w.write_bool(v.as_boolean().unwrap())?, AtomClass::Float => w.write_f32(v.as_float().unwrap())?, AtomClass::Double => w.write_f64(v.as_double().unwrap())?, AtomClass::SignedInteger => w.write_signed_integer(&v.as_signed_integer().unwrap())?, AtomClass::String => w.write_string(&v.as_string().unwrap())?, AtomClass::ByteString => w.write_bytes(&v.as_bytestring().unwrap())?, AtomClass::Symbol => w.write_symbol(&v.as_symbol().unwrap())?, } ValueClass::Compound(c) => match c { CompoundClass::Record => { w.start_record()?; let mut b = B::start(B::Item::RecordLabel); w.boundary(&b)?; v.label().write(w, enc)?; for e in v.iter() { b.shift(Some(B::Item::RecordField)); w.boundary(&b)?; e.write(w, enc)?; } b.shift(None); w.boundary(&b)?; w.end_record()? } CompoundClass::Sequence => { w.start_sequence()?; let mut b = B::Type::default(); for e in v.iter() { b.shift(Some(B::Item::SequenceValue)); w.boundary(&b)?; e.write(w, enc)?; } b.shift(None); w.boundary(&b)?; w.end_sequence()? } CompoundClass::Set => { w.start_set()?; let mut b = B::Type::default(); for e in v.iter() { b.shift(Some(B::Item::SetValue)); w.boundary(&b)?; e.write(w, enc)?; } b.shift(None); w.boundary(&b)?; w.end_set()? } CompoundClass::Dictionary => { w.start_dictionary()?; let mut b = B::Type::default(); for (k, v) in v.entries() { b.shift(Some(B::Item::DictionaryKey)); w.boundary(&b)?; k.write(w, enc)?; b.shift(Some(B::Item::DictionaryValue)); w.boundary(&b)?; v.write(w, enc)?; } b.shift(None); w.boundary(&b)?; w.end_dictionary()? } } ValueClass::Embedded => { w.start_embedded()?; enc.encode_embedded(w, &v.as_embedded().unwrap())?; w.end_embedded()? } } if has_annotations { annotation_b.shift(None); w.boundary(&annotation_b)?; w.end_annotations()? } Ok(()) }