584 lines
16 KiB
Rust
584 lines
16 KiB
Rust
//! 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<W: io::Write>(Suspendable<W>);
|
|
|
|
impl PackedWriter<&mut Vec<u8>> {
|
|
/// Encodes `v` to a byte vector.
|
|
#[inline(always)]
|
|
pub fn encode<N: NestedValue, Enc: DomainEncode<N::Embedded>>(
|
|
enc: &mut Enc,
|
|
v: &N,
|
|
) -> io::Result<Vec<u8>> {
|
|
let mut buf: Vec<u8> = 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<Vec<u8>> {
|
|
Self::encode(&mut IOValueDomainCodec, v)
|
|
}
|
|
}
|
|
|
|
impl<W: io::Write> PackedWriter<W> {
|
|
/// 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<Vec<u8>>);
|
|
|
|
impl BinaryOrderWriter {
|
|
#[inline(always)]
|
|
fn new() -> Self {
|
|
BinaryOrderWriter(vec![vec![]])
|
|
}
|
|
|
|
#[inline(always)]
|
|
fn pop(&mut self) -> PackedWriter<Vec<u8>> {
|
|
PackedWriter::new(self.0.pop().unwrap())
|
|
}
|
|
|
|
#[inline(always)]
|
|
fn push(&mut self, w: PackedWriter<Vec<u8>>) {
|
|
self.0.push(w.0.take())
|
|
}
|
|
|
|
#[inline(always)]
|
|
fn items(&self) -> &Vec<Vec<u8>> {
|
|
&self.0
|
|
}
|
|
|
|
#[inline(always)]
|
|
fn items_mut(&mut self) -> &mut Vec<Vec<u8>> {
|
|
&mut self.0
|
|
}
|
|
|
|
#[inline(always)]
|
|
fn buffer(&mut self) -> &mut Vec<u8> {
|
|
self.0.last_mut().unwrap()
|
|
}
|
|
|
|
#[inline(always)]
|
|
fn finish<W: WriteWriter>(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<W: io::Write> WriteWriter for PackedWriter<W> {
|
|
#[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<W: io::Write> CompoundWriter for PackedWriter<W> {
|
|
#[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<Vec<u8>>;
|
|
type RecWriter = PackedWriter<Vec<u8>>;
|
|
type SeqWriter = PackedWriter<Vec<u8>>;
|
|
type SetWriter = BinaryOrderWriter;
|
|
type DictWriter = BinaryOrderWriter;
|
|
type EmbeddedWriter = PackedWriter<Vec<u8>>;
|
|
|
|
#[inline(always)]
|
|
fn start_annotations(&mut self) -> io::Result<Self::AnnWriter> {
|
|
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_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<usize>) -> io::Result<Self::RecWriter> {
|
|
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<usize>) -> io::Result<Self::SeqWriter> {
|
|
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<usize>) -> io::Result<Self::SetWriter> {
|
|
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<usize>) -> io::Result<Self::DictWriter> {
|
|
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::EmbeddedWriter> {
|
|
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<W: io::Write> Writer for PackedWriter<W> {
|
|
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<Self::AnnWriter> {
|
|
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_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<usize>) -> io::Result<Self::RecWriter> {
|
|
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<usize>) -> io::Result<Self::SeqWriter> {
|
|
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<usize>) -> io::Result<Self::SetWriter> {
|
|
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<usize>) -> io::Result<Self::DictWriter> {
|
|
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::EmbeddedWriter> {
|
|
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()
|
|
}
|
|
}
|