//! Implementation of [Writer] for the binary encoding. use super::super::boundary as B; use super::super::suspendable::Suspendable; use super::super::DomainEncode; use super::super::IOValue; use super::super::IOValueDomainCodec; use super::super::NestedValue; use super::constants::Tag; use num::bigint::BigInt; use num::cast::ToPrimitive; use std::convert::TryInto; use std::io; use std::ops::DerefMut; use super::super::writer::{varint, CompoundWriter, Writer}; /// The binary encoding Preserves writer. pub struct PackedWriter(Suspendable); impl PackedWriter<&mut Vec> { /// Encodes `v` to a byte vector. #[inline(always)] pub fn encode>( enc: &mut Enc, v: &N, ) -> io::Result> { let mut buf: Vec = Vec::new(); PackedWriter::new(&mut buf).write(enc, v)?; Ok(buf) } /// Encodes `v` to a byte vector. #[inline(always)] pub fn encode_iovalue(v: &IOValue) -> io::Result> { Self::encode(&mut IOValueDomainCodec, v) } } impl PackedWriter { /// Construct a writer from the given byte sink `write`. #[inline(always)] pub fn new(write: W) -> Self { PackedWriter(Suspendable::new(write)) } /// Retrieve a mutable reference to the underlying byte sink. #[inline(always)] pub fn w(&mut self) -> &mut W { self.0.deref_mut() } #[doc(hidden)] #[inline(always)] pub fn write_byte(&mut self, b: u8) -> io::Result<()> { self.w().write_all(&[b]) } #[doc(hidden)] #[inline(always)] pub fn write_integer(&mut self, bs: &[u8]) -> io::Result<()> { self.write_atom(Tag::SignedInteger, bs) } #[doc(hidden)] #[inline(always)] pub fn write_atom(&mut self, tag: Tag, bs: &[u8]) -> io::Result<()> { self.write_byte(tag.into())?; varint(&mut self.w(), bs.len().try_into().unwrap())?; self.w().write_all(bs) } #[doc(hidden)] #[inline(always)] pub fn suspend(&mut self) -> Self { PackedWriter(self.0.suspend()) } #[doc(hidden)] #[inline(always)] pub fn resume(&mut self, other: Self) { self.0.resume(other.0) } } #[doc(hidden)] pub struct BinaryOrderWriter(Vec>); impl BinaryOrderWriter { #[inline(always)] fn new() -> Self { BinaryOrderWriter(vec![vec![]]) } #[inline(always)] fn pop(&mut self) -> PackedWriter> { PackedWriter::new(self.0.pop().unwrap()) } #[inline(always)] fn push(&mut self, w: PackedWriter>) { self.0.push(w.0.take()) } #[inline(always)] fn items(&self) -> &Vec> { &self.0 } #[inline(always)] fn items_mut(&mut self) -> &mut Vec> { &mut self.0 } #[inline(always)] fn buffer(&mut self) -> &mut Vec { self.0.last_mut().unwrap() } #[inline(always)] fn finish(mut self, w: &mut W) -> io::Result<()> { if !self.buffer().is_empty() { panic!("Missing final boundary()"); } self.items_mut().pop(); self.items_mut().sort(); for bs in self.items() { w.write_raw_bytes(&bs)?; } w.write_tag(Tag::End)?; Ok(()) } } #[doc(hidden)] pub trait WriteWriter: Writer { fn write_raw_bytes(&mut self, v: &[u8]) -> io::Result<()>; #[inline(always)] fn write_tag(&mut self, tag: Tag) -> io::Result<()> { self.write_raw_bytes(&[tag.into()]) } } impl WriteWriter for PackedWriter { #[inline(always)] fn write_raw_bytes(&mut self, v: &[u8]) -> io::Result<()> { self.w().write_all(v) } } impl WriteWriter for BinaryOrderWriter { #[inline(always)] fn write_raw_bytes(&mut self, v: &[u8]) -> io::Result<()> { use io::Write; self.buffer().write_all(v) } } impl CompoundWriter for PackedWriter { #[inline(always)] fn boundary(&mut self, b: &B::Type) -> io::Result<()> { if let Some(B::Item::Annotation) = b.opening { self.write_tag(Tag::Annotation)?; } Ok(()) } } impl CompoundWriter for BinaryOrderWriter { #[inline(always)] fn boundary(&mut self, b: &B::Type) -> io::Result<()> { match b.closing { Some(B::Item::DictionaryValue) | Some(B::Item::RecordField) | Some(B::Item::SequenceValue) | Some(B::Item::SetValue) => self.items_mut().push(vec![]), _ => (), } Ok(()) } } macro_rules! binary_order_writer_method { (mut $n:ident ($($argname:ident : $argty:ty),*) -> $retty:ty) => (#[inline(always)] fn $n (&mut self, $($argname : $argty),*) -> $retty { (&mut PackedWriter::new(self.buffer())).$n($($argname),*) }); } impl Writer for BinaryOrderWriter { type AnnWriter = PackedWriter>; type RecWriter = PackedWriter>; type SeqWriter = PackedWriter>; type SetWriter = BinaryOrderWriter; type DictWriter = BinaryOrderWriter; type EmbeddedWriter = PackedWriter>; #[inline(always)] fn start_annotations(&mut self) -> io::Result { Ok(self.pop()) } #[inline(always)] fn end_annotations(&mut self, ann: Self::AnnWriter) -> io::Result<()> { self.push(ann); Ok(()) } binary_order_writer_method!(mut write_bool(v: bool) -> io::Result<()>); binary_order_writer_method!(mut write_f32(v: f32) -> io::Result<()>); binary_order_writer_method!(mut write_f64(v: f64) -> io::Result<()>); binary_order_writer_method!(mut write_i8(v: i8) -> io::Result<()>); binary_order_writer_method!(mut write_u8(v: u8) -> io::Result<()>); binary_order_writer_method!(mut write_i16(v: i16) -> io::Result<()>); binary_order_writer_method!(mut write_u16(v: u16) -> io::Result<()>); binary_order_writer_method!(mut write_i32(v: i32) -> io::Result<()>); binary_order_writer_method!(mut write_u32(v: u32) -> io::Result<()>); binary_order_writer_method!(mut write_i64(v: i64) -> io::Result<()>); binary_order_writer_method!(mut write_u64(v: u64) -> io::Result<()>); binary_order_writer_method!(mut write_i128(v: i128) -> io::Result<()>); binary_order_writer_method!(mut write_u128(v: u128) -> io::Result<()>); binary_order_writer_method!(mut write_int(v: &BigInt) -> io::Result<()>); binary_order_writer_method!(mut write_string(v: &str) -> io::Result<()>); binary_order_writer_method!(mut write_bytes(v: &[u8]) -> io::Result<()>); binary_order_writer_method!(mut write_symbol(v: &str) -> io::Result<()>); #[inline(always)] fn start_record(&mut self, _field_count: Option) -> io::Result { self.write_tag(Tag::Record)?; Ok(self.pop()) } #[inline(always)] fn end_record(&mut self, rec: Self::RecWriter) -> io::Result<()> { self.push(rec); self.write_tag(Tag::End) } #[inline(always)] fn start_sequence(&mut self, _item_count: Option) -> io::Result { self.write_tag(Tag::Sequence)?; Ok(self.pop()) } #[inline(always)] fn end_sequence(&mut self, seq: Self::SeqWriter) -> io::Result<()> { self.push(seq); self.write_tag(Tag::End) } #[inline(always)] fn start_set(&mut self, _item_count: Option) -> io::Result { self.write_tag(Tag::Set)?; Ok(BinaryOrderWriter::new()) } #[inline(always)] fn end_set(&mut self, set: Self::SetWriter) -> io::Result<()> { set.finish(self) } #[inline(always)] fn start_dictionary(&mut self, _entry_count: Option) -> io::Result { self.write_tag(Tag::Dictionary)?; Ok(BinaryOrderWriter::new()) } #[inline(always)] fn end_dictionary(&mut self, dict: Self::DictWriter) -> io::Result<()> { dict.finish(self) } #[inline(always)] fn start_embedded(&mut self) -> io::Result { self.write_tag(Tag::Embedded)?; Ok(self.pop()) } #[inline(always)] fn end_embedded(&mut self, ptr: Self::EmbeddedWriter) -> io::Result<()> { self.push(ptr); Ok(()) } #[inline(always)] fn flush(&mut self) -> io::Result<()> { Ok(()) } } macro_rules! fits_in_bytes { ($v:ident, $limit:literal) => {{ let bits = $limit * 8 - 1; $v >= -(1 << bits) && $v < (1 << bits) }}; } impl Writer for PackedWriter { type AnnWriter = Self; type RecWriter = Self; type SeqWriter = Self; type SetWriter = BinaryOrderWriter; type DictWriter = BinaryOrderWriter; type EmbeddedWriter = Self; #[inline(always)] fn start_annotations(&mut self) -> io::Result { Ok(self.suspend()) } #[inline(always)] fn end_annotations(&mut self, ann: Self::AnnWriter) -> io::Result<()> { self.resume(ann); Ok(()) } #[inline(always)] fn write_bool(&mut self, v: bool) -> io::Result<()> { self.write_tag(if v { Tag::True } else { Tag::False }) } #[inline(always)] fn write_f32(&mut self, v: f32) -> io::Result<()> { self.write_tag(Tag::Ieee754)?; self.write_byte(4)?; self.write_raw_bytes(&u32::to_be_bytes(f32::to_bits(v))) } #[inline(always)] fn write_f64(&mut self, v: f64) -> io::Result<()> { self.write_tag(Tag::Ieee754)?; self.write_byte(8)?; self.write_raw_bytes(&u64::to_be_bytes(f64::to_bits(v))) } #[inline(always)] fn write_i8(&mut self, v: i8) -> io::Result<()> { if v == 0 { return self.write_integer(&[]); } self.write_integer(&[v as u8]) } #[inline(always)] fn write_u8(&mut self, v: u8) -> io::Result<()> { if let Ok(w) = v.try_into() { return self.write_i8(w); } self.write_integer(&[0, v]) } #[inline(always)] fn write_i16(&mut self, v: i16) -> io::Result<()> { if let Ok(w) = v.try_into() { return self.write_i8(w); } self.write_integer(&[(v >> 8) as u8, (v & 255) as u8]) } #[inline(always)] fn write_u16(&mut self, v: u16) -> io::Result<()> { if let Ok(w) = v.try_into() { return self.write_i16(w); } self.write_integer(&[0, (v >> 8) as u8, (v & 255) as u8]) } #[inline(always)] fn write_i32(&mut self, v: i32) -> io::Result<()> { if let Ok(w) = v.try_into() { return self.write_i16(w); } if fits_in_bytes!(v, 3) { return self.write_integer(&[(v >> 16) as u8, (v >> 8) as u8, (v & 255) as u8]); } self.write_integer(&[ (v >> 24) as u8, (v >> 16) as u8, (v >> 8) as u8, (v & 255) as u8, ]) } #[inline(always)] fn write_u32(&mut self, v: u32) -> io::Result<()> { if let Ok(w) = v.try_into() { return self.write_i32(w); } self.write_integer(&[ 0, (v >> 24) as u8, (v >> 16) as u8, (v >> 8) as u8, (v & 255) as u8, ]) } #[inline(always)] fn write_i64(&mut self, v: i64) -> io::Result<()> { if let Ok(w) = v.try_into() { return self.write_i32(w); } if fits_in_bytes!(v, 5) { return self.write_integer(&[ (v >> 32) as u8, (v >> 24) as u8, (v >> 16) as u8, (v >> 8) as u8, (v & 255) as u8, ]); } if fits_in_bytes!(v, 6) { return self.write_integer(&[ (v >> 40) as u8, (v >> 32) as u8, (v >> 24) as u8, (v >> 16) as u8, (v >> 8) as u8, (v & 255) as u8, ]); } if fits_in_bytes!(v, 7) { return self.write_integer(&[ (v >> 48) as u8, (v >> 40) as u8, (v >> 32) as u8, (v >> 24) as u8, (v >> 16) as u8, (v >> 8) as u8, (v & 255) as u8, ]); } self.write_integer(&[ (v >> 56) as u8, (v >> 48) as u8, (v >> 40) as u8, (v >> 32) as u8, (v >> 24) as u8, (v >> 16) as u8, (v >> 8) as u8, (v & 255) as u8, ]) } #[inline(always)] fn write_u64(&mut self, v: u64) -> io::Result<()> { if let Ok(w) = v.try_into() { return self.write_i64(w); } self.write_integer(&[ 0, (v >> 56) as u8, (v >> 48) as u8, (v >> 40) as u8, (v >> 32) as u8, (v >> 24) as u8, (v >> 16) as u8, (v >> 8) as u8, (v & 255) as u8, ]) } #[inline(always)] fn write_i128(&mut self, v: i128) -> io::Result<()> { if let Ok(w) = v.try_into() { return self.write_i64(w); } let bs: [u8; 16] = v.to_be_bytes(); if fits_in_bytes!(v, 9) { return self.write_integer(&bs[7..]); } if fits_in_bytes!(v, 10) { return self.write_integer(&bs[6..]); } if fits_in_bytes!(v, 11) { return self.write_integer(&bs[5..]); } if fits_in_bytes!(v, 12) { return self.write_integer(&bs[4..]); } if fits_in_bytes!(v, 13) { return self.write_integer(&bs[3..]); } if fits_in_bytes!(v, 14) { return self.write_integer(&bs[2..]); } if fits_in_bytes!(v, 15) { return self.write_integer(&bs[1..]); } self.write_integer(&bs) } #[inline(always)] fn write_u128(&mut self, v: u128) -> io::Result<()> { if let Ok(w) = v.try_into() { return self.write_i128(w); } let bs: [u8; 16] = v.to_be_bytes(); self.write_tag(Tag::SignedInteger)?; varint(&mut self.w(), 17)?; self.write_byte(0)?; self.write_raw_bytes(&bs) } #[inline(always)] fn write_int(&mut self, v: &BigInt) -> io::Result<()> { match v.to_i8() { Some(n) => self.write_i8(n), None => match v.to_i128() { Some(n) => self.write_i128(n), None => self.write_integer(&v.to_signed_bytes_be()), }, } } #[inline(always)] fn write_string(&mut self, v: &str) -> io::Result<()> { self.write_atom(Tag::String, v.as_bytes()) } #[inline(always)] fn write_bytes(&mut self, v: &[u8]) -> io::Result<()> { self.write_atom(Tag::ByteString, v) } #[inline(always)] fn write_symbol(&mut self, v: &str) -> io::Result<()> { self.write_atom(Tag::Symbol, v.as_bytes()) } #[inline(always)] fn start_record(&mut self, _field_count: Option) -> io::Result { self.write_tag(Tag::Record)?; Ok(self.suspend()) } #[inline(always)] fn end_record(&mut self, rec: Self::RecWriter) -> io::Result<()> { self.resume(rec); self.write_tag(Tag::End) } #[inline(always)] fn start_sequence(&mut self, _item_count: Option) -> io::Result { self.write_tag(Tag::Sequence)?; Ok(self.suspend()) } #[inline(always)] fn end_sequence(&mut self, seq: Self::SeqWriter) -> io::Result<()> { self.resume(seq); self.write_tag(Tag::End) } #[inline(always)] fn start_set(&mut self, _item_count: Option) -> io::Result { self.write_tag(Tag::Set)?; Ok(BinaryOrderWriter::new()) } #[inline(always)] fn end_set(&mut self, set: Self::SetWriter) -> io::Result<()> { set.finish(self) } #[inline(always)] fn start_dictionary(&mut self, _entry_count: Option) -> io::Result { self.write_tag(Tag::Dictionary)?; Ok(BinaryOrderWriter::new()) } #[inline(always)] fn end_dictionary(&mut self, dict: Self::DictWriter) -> io::Result<()> { dict.finish(self) } #[inline(always)] fn start_embedded(&mut self) -> io::Result { self.write_tag(Tag::Embedded)?; Ok(self.suspend()) } #[inline(always)] fn end_embedded(&mut self, ann: Self::EmbeddedWriter) -> io::Result<()> { self.resume(ann); Ok(()) } #[inline(always)] fn flush(&mut self) -> io::Result<()> { self.0.flush() } }