use num; use num::bigint::BigInt; use num::cast::ToPrimitive; use std::convert::TryInto; use std::mem; use std::ops::{Deref, DerefMut}; use super::constants::Tag; use super::super::IOValue; use super::super::writer::{Writer, AnnotationWriter, CompoundWriter, Result, varint}; pub enum Suspendable { Active(T), Suspended, } impl Suspendable { pub fn new(t: T) -> Self { Suspendable::Active(t) } pub fn suspend(&mut self) -> Self { match self { Suspendable::Active(_) => mem::replace(self, Suspendable::Suspended), Suspendable::Suspended => panic!("Attempt to suspend suspended Suspendable"), } } pub fn resume(&mut self, other: Self) { match self { Suspendable::Suspended => match other { Suspendable::Active(_) => *self = other, Suspendable::Suspended => panic!("Attempt to resume from suspended Suspendable"), }, Suspendable::Active(_) => panic!("Attempt to resume non-suspended Suspendable"), } } pub fn take(self) -> T { match self { Suspendable::Active(t) => t, Suspendable::Suspended => panic!("Attempt to take from suspended Suspendable"), } } } impl Deref for Suspendable { type Target = T; fn deref(&self) -> &Self::Target { match self { Suspendable::Suspended => panic!("Suspended Suspendable at deref"), Suspendable::Active(t) => t } } } impl DerefMut for Suspendable { fn deref_mut(&mut self) -> &mut Self::Target { match self { Suspendable::Suspended => panic!("Empty Suspendable at deref_mut"), Suspendable::Active(t) => t } } } pub struct PackedWriter(Suspendable); impl PackedWriter> { pub fn encode(v: &IOValue) -> std::io::Result> { let mut buf: Vec = Vec::new(); let w = &mut PackedWriter::new(&mut buf); w.write(v)?; Ok(buf) } } impl PackedWriter { pub fn new(write: W) -> Self { PackedWriter(Suspendable::new(write)) } pub fn w(&mut self) -> &mut W { self.0.deref_mut() } pub fn write_byte(&mut self, b: u8) -> Result<()> { self.w().write_all(&[b]) } pub fn write_medium_integer(&mut self, bs: &[u8]) -> Result<()> { let count: u8 = bs.len().try_into().unwrap(); if count > 16 || count < 1 { panic!("Invalid medium_integer count: {}", count) } self.write_byte(Tag::MediumInteger(count).into())?; self.w().write_all(bs) } pub fn write_atom(&mut self, tag: Tag, bs: &[u8]) -> Result<()> { self.write_byte(tag.into())?; varint(&mut self.w(), bs.len().try_into().unwrap())?; self.w().write_all(bs) } pub fn suspend(&mut self) -> Self { PackedWriter(self.0.suspend()) } pub fn resume(&mut self, other: Self) { self.0.resume(other.0) } } pub struct BinaryOrderWriter(Vec>); impl BinaryOrderWriter { fn new() -> Self { BinaryOrderWriter(vec![vec![]]) } fn pop(&mut self) -> PackedWriter> { PackedWriter::new(self.0.pop().unwrap()) } fn push(&mut self, w: PackedWriter>) { self.0.push(w.0.take()) } fn items(&self) -> &Vec> { &self.0 } fn items_mut(&mut self) -> &mut Vec> { &mut self.0 } fn buffer(&mut self) -> &mut Vec { self.0.last_mut().unwrap() } fn finish(mut self, w: &mut W) -> Result<()> { if self.buffer().len() != 0 { panic!("Missing final delimit()"); } self.items_mut().pop(); self.items_mut().sort(); for bs in self.items() { w.write_raw_bytes(&bs)?; } w.write_tag(Tag::End)?; Ok(()) } } pub trait WriteWriter: Writer { fn write_raw_bytes(&mut self, v: &[u8]) -> Result<()>; fn write_tag(&mut self, tag: Tag) -> Result<()> { self.write_raw_bytes(&[tag.into()]) } } impl WriteWriter for PackedWriter { fn write_raw_bytes(&mut self, v: &[u8]) -> Result<()> { self.w().write_all(v) } } impl WriteWriter for BinaryOrderWriter { fn write_raw_bytes(&mut self, v: &[u8]) -> Result<()> { use std::io::Write; self.buffer().write_all(v) } } impl AnnotationWriter for T { fn start_annotation(&mut self) -> Result<()> { Ok(self.write_tag(Tag::Annotation)?) } fn start_value(&mut self) -> Result<()> { Ok(()) } } impl CompoundWriter for PackedWriter { fn extend(&mut self) -> Result<()> { Ok(()) } fn delimit(&mut self) -> Result<()> { Ok(()) } } impl CompoundWriter for BinaryOrderWriter { fn extend(&mut self) -> Result<()> { Ok(()) } fn delimit(&mut self) -> Result<()> { self.items_mut().push(vec![]); Ok(()) } } macro_rules! binary_order_writer_method { (mut $n:ident ($($argname:ident : $argty:ty),*) -> $retty:ty) => (fn $n (&mut self, $($argname : $argty),*) -> $retty { (&mut PackedWriter::new(self.buffer())).$n($($argname),*) }); } impl Writer for BinaryOrderWriter { type AnnWriter = PackedWriter>; type SeqWriter = PackedWriter>; type SetWriter = BinaryOrderWriter; type PointerWriter = PackedWriter>; binary_order_writer_method!(mut align(natural_chunksize: u64) -> Result<()>); fn start_annotations(&mut self) -> Result { Ok(self.pop()) } fn end_annotations(&mut self, ann: Self::AnnWriter) -> Result<()> { self.push(ann); Ok(()) } binary_order_writer_method!(mut write_bool(v: bool) -> Result<()>); binary_order_writer_method!(mut write_f32(v: f32) -> Result<()>); binary_order_writer_method!(mut write_f64(v: f64) -> Result<()>); binary_order_writer_method!(mut write_i8(v: i8) -> Result<()>); binary_order_writer_method!(mut write_u8(v: u8) -> Result<()>); binary_order_writer_method!(mut write_i16(v: i16) -> Result<()>); binary_order_writer_method!(mut write_u16(v: u16) -> Result<()>); binary_order_writer_method!(mut write_i32(v: i32) -> Result<()>); binary_order_writer_method!(mut write_u32(v: u32) -> Result<()>); binary_order_writer_method!(mut write_i64(v: i64) -> Result<()>); binary_order_writer_method!(mut write_u64(v: u64) -> Result<()>); binary_order_writer_method!(mut write_i128(v: i128) -> Result<()>); binary_order_writer_method!(mut write_u128(v: u128) -> Result<()>); binary_order_writer_method!(mut write_int(v: &BigInt) -> Result<()>); binary_order_writer_method!(mut write_string(v: &str) -> Result<()>); binary_order_writer_method!(mut write_bytes(v: &[u8]) -> Result<()>); binary_order_writer_method!(mut write_symbol(v: &str) -> Result<()>); fn start_record(&mut self, _field_count: Option) -> Result { self.write_tag(Tag::Record)?; Ok(self.pop()) } fn start_sequence(&mut self, _item_count: Option) -> Result { self.write_tag(Tag::Sequence)?; Ok(self.pop()) } fn end_seq(&mut self, seq: Self::SeqWriter) -> Result<()> { self.push(seq); self.write_tag(Tag::End) } fn start_set(&mut self, _item_count: Option) -> Result { self.write_tag(Tag::Set)?; Ok(BinaryOrderWriter::new()) } fn start_dictionary(&mut self, _entry_count: Option) -> Result { self.write_tag(Tag::Dictionary)?; Ok(BinaryOrderWriter::new()) } fn end_set(&mut self, set: Self::SetWriter) -> Result<()> { set.finish(self) } fn start_pointer(&mut self) -> Result { self.write_tag(Tag::Pointer)?; Ok(self.pop()) } fn end_pointer(&mut self, ptr: Self::PointerWriter) -> Result<()> { self.push(ptr); Ok(()) } } macro_rules! fits_in_bytes { ($v:ident, $limit:literal) => ({ let bits = $limit * 8 - 1; $v >= -(2 << bits) && $v < (2 << bits) }) } impl Writer for PackedWriter { type AnnWriter = Self; type SeqWriter = Self; type SetWriter = BinaryOrderWriter; type PointerWriter = Self; fn start_annotations(&mut self) -> Result { Ok(self.suspend()) } fn end_annotations(&mut self, ann: Self::AnnWriter) -> Result<()> { self.resume(ann); Ok(()) } fn align(&mut self, _natural_chunksize: u64) -> Result<()> { Ok(()) } fn write_bool(&mut self, v: bool) -> Result<()> { self.write_tag(if v { Tag::True } else { Tag::False }) } fn write_f32(&mut self, v: f32) -> Result<()> { self.write_tag(Tag::Float)?; self.write_raw_bytes(&u32::to_be_bytes(f32::to_bits(v))) } fn write_f64(&mut self, v: f64) -> Result<()> { self.write_tag(Tag::Double)?; self.write_raw_bytes(&u64::to_be_bytes(f64::to_bits(v))) } fn write_i8(&mut self, v: i8) -> Result<()> { if v >= -3 && v <= 12 { return self.write_tag(Tag::SmallInteger(v)) } self.write_medium_integer(&[v as u8]) } fn write_u8(&mut self, v: u8) -> Result<()> { if let Ok(w) = v.try_into() { return self.write_i8(w) } self.write_medium_integer(&[0, v]) } fn write_i16(&mut self, v: i16) -> Result<()> { if let Ok(w) = v.try_into() { return self.write_i8(w) } self.write_medium_integer(&[(v >> 8) as u8, (v & 255) as u8]) } fn write_u16(&mut self, v: u16) -> Result<()> { if let Ok(w) = v.try_into() { return self.write_i16(w) } self.write_medium_integer(&[0, (v >> 8) as u8, (v & 255) as u8]) } fn write_i32(&mut self, v: i32) -> Result<()> { if let Ok(w) = v.try_into() { return self.write_i16(w) } if fits_in_bytes!(v, 3) { return self.write_medium_integer(&[(v >> 16) as u8, (v >> 8) as u8, (v & 255) as u8]); } self.write_medium_integer(&[(v >> 24) as u8, (v >> 16) as u8, (v >> 8) as u8, (v & 255) as u8]) } fn write_u32(&mut self, v: u32) -> Result<()> { if let Ok(w) = v.try_into() { return self.write_i32(w) } self.write_medium_integer(&[0, (v >> 24) as u8, (v >> 16) as u8, (v >> 8) as u8, (v & 255) as u8]) } fn write_i64(&mut self, v: i64) -> Result<()> { if let Ok(w) = v.try_into() { return self.write_i32(w) } if fits_in_bytes!(v, 5) { return self.write_medium_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_medium_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_medium_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_medium_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]) } fn write_u64(&mut self, v: u64) -> Result<()> { if let Ok(w) = v.try_into() { return self.write_i64(w) } self.write_medium_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]) } fn write_i128(&mut self, v: i128) -> 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_medium_integer(&bs[7..]); } if fits_in_bytes!(v, 10) { return self.write_medium_integer(&bs[6..]); } if fits_in_bytes!(v, 11) { return self.write_medium_integer(&bs[5..]); } if fits_in_bytes!(v, 12) { return self.write_medium_integer(&bs[4..]); } if fits_in_bytes!(v, 13) { return self.write_medium_integer(&bs[3..]); } if fits_in_bytes!(v, 14) { return self.write_medium_integer(&bs[2..]); } if fits_in_bytes!(v, 15) { return self.write_medium_integer(&bs[1..]); } self.write_medium_integer(&bs) } fn write_u128(&mut self, v: u128) -> 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) } fn write_int(&mut self, v: &BigInt) -> 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_atom(Tag::SignedInteger, &v.to_signed_bytes_be()), } } } } fn write_string(&mut self, v: &str) -> Result<()> { self.write_atom(Tag::String, v.as_bytes()) } fn write_bytes(&mut self, v: &[u8]) -> Result<()> { self.write_atom(Tag::ByteString, v) } fn write_symbol(&mut self, v: &str) -> Result<()> { self.write_atom(Tag::Symbol, v.as_bytes()) } fn start_record(&mut self, _field_count: Option) -> Result { self.write_tag(Tag::Record)?; Ok(self.suspend()) } fn start_sequence(&mut self, _item_count: Option) -> Result { self.write_tag(Tag::Sequence)?; Ok(self.suspend()) } fn end_seq(&mut self, seq: Self::SeqWriter) -> Result<()> { self.resume(seq); self.write_tag(Tag::End) } fn start_set(&mut self, _item_count: Option) -> Result { self.write_tag(Tag::Set)?; Ok(BinaryOrderWriter::new()) } fn start_dictionary(&mut self, _entry_count: Option) -> Result { self.write_tag(Tag::Dictionary)?; Ok(BinaryOrderWriter::new()) } fn end_set(&mut self, set: Self::SetWriter) -> Result<()> { set.finish(self) } fn start_pointer(&mut self) -> Result { self.write_tag(Tag::Pointer)?; Ok(self.suspend()) } fn end_pointer(&mut self, ann: Self::PointerWriter) -> Result<()> { self.resume(ann); Ok(()) } }