preserves/implementations/rust/preserves/src/value/packed/writer.rs

502 lines
16 KiB
Rust

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<T> {
Active(T),
Suspended,
}
impl<T> Suspendable<T> {
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<T> Deref for Suspendable<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
match self {
Suspendable::Suspended => panic!("Suspended Suspendable at deref"),
Suspendable::Active(t) => t
}
}
}
impl<T> DerefMut for Suspendable<T> {
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<W: std::io::Write>(Suspendable<W>);
impl PackedWriter<Vec<u8>> {
pub fn encode(v: &IOValue) -> std::io::Result<Vec<u8>> {
let mut buf: Vec<u8> = Vec::new();
let w = &mut PackedWriter::new(&mut buf);
w.write(v)?;
Ok(buf)
}
}
impl<W: std::io::Write> PackedWriter<W> {
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 !(1..=16).contains(&count) { 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<Vec<u8>>);
impl BinaryOrderWriter {
fn new() -> Self {
BinaryOrderWriter(vec![vec![]])
}
fn pop(&mut self) -> PackedWriter<Vec<u8>> {
PackedWriter::new(self.0.pop().unwrap())
}
fn push(&mut self, w: PackedWriter<Vec<u8>>) {
self.0.push(w.0.take())
}
fn items(&self) -> &Vec<Vec<u8>> {
&self.0
}
fn items_mut(&mut self) -> &mut Vec<Vec<u8>> {
&mut self.0
}
fn buffer(&mut self) -> &mut Vec<u8> {
self.0.last_mut().unwrap()
}
fn finish<W: WriteWriter>(mut self, w: &mut W) -> Result<()> {
if !self.buffer().is_empty() { 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<W: std::io::Write> WriteWriter for PackedWriter<W> {
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<T: WriteWriter> AnnotationWriter for T {
fn start_annotation(&mut self) -> Result<()> {
Ok(self.write_tag(Tag::Annotation)?)
}
fn start_value(&mut self) -> Result<()> {
Ok(())
}
}
impl<W: std::io::Write> CompoundWriter for PackedWriter<W> {
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<Vec<u8>>;
type SeqWriter = PackedWriter<Vec<u8>>;
type SetWriter = BinaryOrderWriter;
type EmbeddedWriter = PackedWriter<Vec<u8>>;
binary_order_writer_method!(mut align(natural_chunksize: u64) -> Result<()>);
fn start_annotations(&mut self) -> Result<Self::AnnWriter> {
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<usize>) -> Result<Self::SeqWriter> {
self.write_tag(Tag::Record)?;
Ok(self.pop())
}
fn start_sequence(&mut self, _item_count: Option<usize>) -> Result<Self::SeqWriter> {
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<usize>) -> Result<Self::SetWriter> {
self.write_tag(Tag::Set)?;
Ok(BinaryOrderWriter::new())
}
fn start_dictionary(&mut self, _entry_count: Option<usize>) -> Result<Self::SetWriter> {
self.write_tag(Tag::Dictionary)?;
Ok(BinaryOrderWriter::new())
}
fn end_set(&mut self, set: Self::SetWriter) -> Result<()> {
set.finish(self)
}
fn start_embedded(&mut self) -> Result<Self::EmbeddedWriter> {
self.write_tag(Tag::Embedded)?;
Ok(self.pop())
}
fn end_embedded(&mut self, ptr: Self::EmbeddedWriter) -> 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<W: std::io::Write> Writer for PackedWriter<W>
{
type AnnWriter = Self;
type SeqWriter = Self;
type SetWriter = BinaryOrderWriter;
type EmbeddedWriter = Self;
fn start_annotations(&mut self) -> Result<Self::AnnWriter> {
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<usize>) -> Result<Self::SeqWriter> {
self.write_tag(Tag::Record)?;
Ok(self.suspend())
}
fn start_sequence(&mut self, _item_count: Option<usize>) -> Result<Self::SeqWriter> {
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<usize>) -> Result<Self::SetWriter> {
self.write_tag(Tag::Set)?;
Ok(BinaryOrderWriter::new())
}
fn start_dictionary(&mut self, _entry_count: Option<usize>) -> Result<Self::SetWriter> {
self.write_tag(Tag::Dictionary)?;
Ok(BinaryOrderWriter::new())
}
fn end_set(&mut self, set: Self::SetWriter) -> Result<()> {
set.finish(self)
}
fn start_embedded(&mut self) -> Result<Self::EmbeddedWriter> {
self.write_tag(Tag::Embedded)?;
Ok(self.suspend())
}
fn end_embedded(&mut self, ann: Self::EmbeddedWriter) -> Result<()> {
self.resume(ann);
Ok(())
}
}