use std::mem;
use std::io::{ Write, BufWriter };
use std::iter::FromIterator;
use std::convert::{ TryFrom, TryInto };
use std::fmt::Display;
use std::ops::Range;
use std::collections::BTreeMap;
use serde::ser::{
Serialize, Serializer, Error as SerError,
SerializeSeq, SerializeTuple, SerializeTupleStruct,
SerializeMap, SerializeStruct,
SerializeTupleVariant, SerializeStructVariant,
};
use byteorder::{ ByteOrder, LittleEndian };
use crate::error::{ Error, ResultExt };
use crate::format::*;
pub fn to_writer<W, T>(writer: W, value: &T) -> Result<(), Error>
where
W: Write,
T: ?Sized + Serialize,
{
let mut serializer = BinarySerializer::new();
value.serialize(&mut serializer)?;
serializer.finalize(writer)
}
pub fn to_writer_buffered<W, T>(writer: W, value: &T) -> Result<(), Error>
where
W: Write,
T: ?Sized + Serialize,
{
to_writer(BufWriter::new(writer), value)
}
pub fn to_bytes<T>(value: &T) -> Result<Vec<u8>, Error>
where
T: ?Sized + Serialize,
{
let mut buf = Vec::with_capacity(4096);
to_writer(&mut buf, value)?;
buf.shrink_to_fit();
Ok(buf)
}
fn encode_uint(x: u64, buf: &mut [u8; 8]) -> (u8, &[u8]) {
if let Ok(x) = u8::try_from(x) {
buf[0] = x;
(0b0000_0000, &buf[..1])
} else if let Ok(x) = u16::try_from(x) {
LittleEndian::write_u16(buf, x);
(0b0000_0001, &buf[..2])
} else if let Ok(x) = u32::try_from(x) {
LittleEndian::write_u32(buf, x);
(0b0000_0010, &buf[..4])
} else {
LittleEndian::write_u64(buf, x);
(0b0000_0011, &buf[..8])
}
}
#[allow(clippy::cast_sign_loss)]
fn encode_int(x: i64, buf: &mut [u8; 8]) -> (u8, &[u8]) {
if let Ok(x) = i8::try_from(x) {
buf[0] = x as u8;
(0b0000_0000, &buf[..1])
} else if let Ok(x) = i16::try_from(x) {
LittleEndian::write_u16(buf, x as u16);
(0b0000_0001, &buf[..2])
} else if let Ok(x) = i32::try_from(x) {
LittleEndian::write_u32(buf, x as u32);
(0b0000_0010, &buf[..4])
} else {
LittleEndian::write_u64(buf, x as u64);
(0b0000_0011, &buf[..8])
}
}
fn write_length_or_index<W: Write>(
mut writer: W,
len: usize,
small_major: Option<u8>, big_major: u8,
big_minor: u8,
) -> Result<(), Error> {
if big_major & MAJOR_TYPE_MASK != big_major {
return Err(Error::new("bug: major type for big representation exceeds mask"));
}
if big_minor & MINOR_TYPE_MASK != big_minor {
return Err(Error::new("bug: minor type for big representation exceeds mask"));
}
if let Some(major) = small_major {
if major & MAJOR_TYPE_MASK != major {
return Err(Error::new("bug: major type for small representation exceeds mask"));
}
if let Ok(u) = SmallUint::try_from(len) {
let byte = u.encode(major);
return writer.write_all(&[byte]).conv_err();
}
}
let mut tmp_buf = [0; 8];
let (log_len_len, buf) = encode_uint(len.try_into()?, &mut tmp_buf);
let marker = big_major | big_minor | (log_len_len & LOG_LENGTH_MASK);
if log_len_len & LOG_LENGTH_MASK != log_len_len {
return Err(Error::new("bug: log length exceeds mask"));
}
writer.write_all(&[marker])?;
writer.write_all(buf).conv_err()
}
fn complex_type_count_buf_size(count: usize) -> Result<usize, Error> {
if SmallUint::try_from(count).is_ok() {
Ok(1) } else {
let (log_len, _) = encode_uint(count.try_into()?, &mut [0; 8]);
Ok(1 + (1 << log_len)) }
}
fn write_complex_type_count_exact(
buf: &mut [u8],
count: usize,
small_major: u8,
big_minor: u8,
) -> Result<(), Error> {
let buf_len = buf.len();
let err = || Err(Error::custom(format_args!(
"can't encode count {} into buffer of size {}; \
incorrect size hint from array/tuple/map/struct",
count, buf_len
)));
let (tag, bytes) = buf.split_first_mut().expect("empty count buffer");
#[allow(clippy::identity_op)]
match bytes.len() {
0 => if let Ok(u) = SmallUint::try_from(count) {
*tag = u.encode(small_major);
} else {
err()?
},
1 => if let Ok(n) = u8::try_from(count) {
*tag = MAJOR_TYPE_BIG_VALUE | big_minor | 0x00;
bytes[0] = n;
} else {
err()?
},
2 => if let Ok(n) = u16::try_from(count) {
*tag = MAJOR_TYPE_BIG_VALUE | big_minor | 0x01;
LittleEndian::write_u16(bytes, n);
} else {
err()?
},
4 => if let Ok(n) = u32::try_from(count) {
*tag = MAJOR_TYPE_BIG_VALUE | big_minor | 0x02;
LittleEndian::write_u32(bytes, n);
} else {
err()?
},
8 => if let Ok(n) = u64::try_from(count) {
*tag = MAJOR_TYPE_BIG_VALUE | big_minor | 0x03;
LittleEndian::write_u64(bytes, n);
} else {
err()?
},
_ => err()?
}
Ok(())
}
trait Internable: AsRef<[u8]> + Into<Vec<u8>> {
const SYMBOL_TYPE: SymbolType;
}
impl Internable for &[u8] {
const SYMBOL_TYPE: SymbolType = SymbolType::Blob;
}
impl Internable for &str {
const SYMBOL_TYPE: SymbolType = SymbolType::Str;
}
impl Internable for String {
const SYMBOL_TYPE: SymbolType = SymbolType::Str;
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
enum SymbolType {
Blob,
Str,
}
impl SymbolType {
const fn value_major(self) -> u8 {
match self {
SymbolType::Blob => MAJOR_TYPE_SMALL_BLOB,
SymbolType::Str => MAJOR_TYPE_SMALL_STRING,
}
}
const fn value_minor(self) -> u8 {
match self {
SymbolType::Blob => MINOR_TYPE_BLOB,
SymbolType::Str => MINOR_TYPE_STRING,
}
}
const fn empty_tag(self) -> u8 {
match self {
SymbolType::Blob => VALUE_BYTE_EMPTY_BLOB,
SymbolType::Str => VALUE_BYTE_EMPTY_STRING,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
struct SymbolMeta {
index: usize,
use_count: usize,
ty: SymbolType,
}
impl SymbolMeta {
fn new<T: Internable>(index: usize) -> Self {
SymbolMeta {
index: index,
use_count: 1,
ty: T::SYMBOL_TYPE,
}
}
fn use_as<T: Internable>(&mut self) {
self.use_count += 1;
match T::SYMBOL_TYPE {
SymbolType::Blob => {} SymbolType::Str => {
self.ty = SymbolType::Str;
}
}
}
const fn is_multi_use(&self) -> bool {
self.use_count > 1
}
const fn symtab_major(&self) -> u8 {
match self.ty {
SymbolType::Blob => if self.is_multi_use() {
MAJOR_TYPE_SMALL_BLOB_MULTI
} else {
MAJOR_TYPE_SMALL_BLOB_ONCE
},
SymbolType::Str => if self.is_multi_use() {
MAJOR_TYPE_SMALL_STRING_MULTI
} else {
MAJOR_TYPE_SMALL_STRING_ONCE
},
}
}
const fn symtab_minor(&self) -> u8 {
match self.ty {
SymbolType::Blob => if self.is_multi_use() {
MINOR_TYPE_BLOB_MULTI
} else {
MINOR_TYPE_BLOB_ONCE
},
SymbolType::Str => if self.is_multi_use() {
MINOR_TYPE_STRING_MULTI
} else {
MINOR_TYPE_STRING_ONCE
},
}
}
}
#[derive(Debug, Clone)]
pub struct BinarySerializer {
body: Vec<u8>,
bytes_to_meta: BTreeMap<Box<[u8]>, SymbolMeta>,
}
impl BinarySerializer {
#[must_use]
pub fn new() -> Self {
BinarySerializer {
body: Vec::with_capacity(4096),
bytes_to_meta: BTreeMap::new(),
}
}
pub fn finalize<W: Write>(mut self, mut writer: W) -> Result<(), Error> {
self.write_header(&mut writer)?;
writer.write_all(&self.body)?;
writer.flush().conv_err()
}
fn write_header<W: Write>(&mut self, mut writer: W) -> Result<(), Error> {
if self.bytes_to_meta.is_empty() {
return Ok(());
}
write_length_or_index(&mut writer,
self.bytes_to_meta.len(),
None,
MAJOR_TYPE_SIMPLE,
MINOR_TYPE_SYMTAB)?;
let sorted_by_index = {
let map = mem::take(&mut self.bytes_to_meta);
let mut v = Vec::from_iter(map);
v.sort_by_key(|&(_, meta)| meta.index);
v
};
for (i, (buf, meta)) in sorted_by_index.into_iter().enumerate() {
if i != meta.index {
return Err(Error::new("bug: non-bijective string interning"));
}
write_length_or_index(&mut writer,
buf.len(),
Some(meta.symtab_major()),
MAJOR_TYPE_BIG_SYMBOL,
meta.symtab_minor())?;
if meta.is_multi_use() {
write_length_or_index(&mut writer,
meta.use_count,
Some(MAJOR_TYPE_SMALL_UINT),
MAJOR_TYPE_BIG_VALUE,
MINOR_TYPE_UINT)?;
}
writer.write_all(&*buf)?;
}
Ok(())
}
fn write_interned_symbol<T>(&mut self, value: T) -> Result<(), Error>
where
T: Internable,
{
let byte_slice = value.as_ref();
if byte_slice.is_empty() {
self.body.push(T::SYMBOL_TYPE.empty_tag());
return Ok(());
}
let index = match self.bytes_to_meta.get_mut(byte_slice) {
Some(meta) => {
meta.use_as::<T>();
meta.index
}
None => {
let index = self.bytes_to_meta.len();
let meta = SymbolMeta::new::<T>(index);
let byte_buf = value.into().into();
self.bytes_to_meta.insert(byte_buf, meta);
index
}
};
write_length_or_index(&mut self.body,
index,
Some(T::SYMBOL_TYPE.value_major()),
MAJOR_TYPE_BIG_VALUE,
T::SYMBOL_TYPE.value_minor())
}
}
impl Default for BinarySerializer {
fn default() -> Self {
BinarySerializer::new()
}
}
impl<'a> Serializer for &'a mut BinarySerializer {
type Ok = ();
type Error = Error;
type SerializeSeq = BinaryComplexSerializer<'a>;
type SerializeTuple = BinaryComplexSerializer<'a>;
type SerializeTupleStruct = BinaryComplexSerializer<'a>;
type SerializeTupleVariant = BinaryComplexSerializer<'a>;
type SerializeMap = BinaryComplexSerializer<'a>;
type SerializeStruct = BinaryComplexSerializer<'a>;
type SerializeStructVariant = BinaryComplexSerializer<'a>;
fn is_human_readable(&self) -> bool {
false
}
fn serialize_bool(self, v: bool) -> Result<Self::Ok, Self::Error> {
self.body.push(if v {
VALUE_BYTE_TRUE
} else {
VALUE_BYTE_FALSE
});
Ok(())
}
fn serialize_i8(self, v: i8) -> Result<Self::Ok, Self::Error> {
self.serialize_i64(v.into())
}
fn serialize_i16(self, v: i16) -> Result<Self::Ok, Self::Error> {
self.serialize_i64(v.into())
}
fn serialize_i32(self, v: i32) -> Result<Self::Ok, Self::Error> {
self.serialize_i64(v.into())
}
fn serialize_i64(self, v: i64) -> Result<Self::Ok, Self::Error> {
if let Ok(i) = SmallInt::try_from(v) {
self.body.push(i.encode());
} else {
let mut tmp_buf = [0; 8];
let (log_len, buf) = encode_int(v, &mut tmp_buf);
let major_minor = MAJOR_TYPE_BIG_VALUE | MINOR_TYPE_INT;
let tag = major_minor | (log_len & LOG_LENGTH_MASK);
self.body.push(tag);
self.body.extend(buf);
}
Ok(())
}
fn serialize_i128(self, v: i128) -> Result<Self::Ok, Self::Error> {
self.serialize_i64(v.try_into()?)
}
fn serialize_u8(self, v: u8) -> Result<Self::Ok, Self::Error> {
self.serialize_u64(v.into())
}
fn serialize_u16(self, v: u16) -> Result<Self::Ok, Self::Error> {
self.serialize_u64(v.into())
}
fn serialize_u32(self, v: u32) -> Result<Self::Ok, Self::Error> {
self.serialize_u64(v.into())
}
fn serialize_u64(self, v: u64) -> Result<Self::Ok, Self::Error> {
if let Ok(u) = SmallUint::try_from(v) {
let byte = u.encode(MAJOR_TYPE_SMALL_UINT);
self.body.push(byte);
} else {
let mut tmp_buf = [0; 8];
let (log_len, buf) = encode_uint(v, &mut tmp_buf);
let major_minor = MAJOR_TYPE_BIG_VALUE | MINOR_TYPE_UINT;
let tag = major_minor | (log_len & LOG_LENGTH_MASK);
self.body.push(tag);
self.body.extend(buf);
}
Ok(())
}
fn serialize_u128(self, v: u128) -> Result<Self::Ok, Self::Error> {
self.serialize_u64(v.try_into()?)
}
fn serialize_f32(self, v: f32) -> Result<Self::Ok, Self::Error> {
if v.is_nan() {
self.serialize_none()
} else {
let tag = MAJOR_TYPE_BIG_VALUE | MINOR_TYPE_FLOAT | 0b0000_0010;
let mut buf = [0; 4];
LittleEndian::write_u32(&mut buf, v.to_bits());
self.body.push(tag);
self.body.extend(&buf);
Ok(())
}
}
fn serialize_f64(self, v: f64) -> Result<Self::Ok, Self::Error> {
if v.is_nan() {
self.serialize_none()
} else {
let tag = MAJOR_TYPE_BIG_VALUE | MINOR_TYPE_FLOAT | 0b0000_0011;
let mut buf = [0; 8];
LittleEndian::write_u64(&mut buf, v.to_bits());
self.body.push(tag);
self.body.extend(&buf);
Ok(())
}
}
fn serialize_char(self, v: char) -> Result<Self::Ok, Self::Error> {
self.serialize_str(v.encode_utf8(&mut [0; 4]))
}
fn serialize_str(self, v: &str) -> Result<Self::Ok, Self::Error> {
self.write_interned_symbol(v)
}
fn serialize_bytes(self, v: &[u8]) -> Result<Self::Ok, Self::Error> {
self.write_interned_symbol(v)
}
fn collect_str<T: ?Sized + Display>(self, v: &T) -> Result<Self::Ok, Self::Error> {
self.write_interned_symbol(v.to_string())
}
fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
self.body.push(VALUE_BYTE_NULL);
Ok(())
}
fn serialize_some<T: ?Sized + Serialize>(self, value: &T) -> Result<Self::Ok, Self::Error> {
self.body.push(VALUE_BYTE_OPT);
value.serialize(self)
}
fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
self.serialize_none()
}
fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok, Self::Error> {
self.serialize_unit()
}
fn serialize_unit_variant(
self,
_name: &'static str,
_variant_index: u32,
variant: &'static str,
) -> Result<Self::Ok, Self::Error> {
self.serialize_str(variant)
}
fn serialize_newtype_struct<T: ?Sized + Serialize>(
self,
_name: &'static str,
value: &T,
) -> Result<Self::Ok, Self::Error> {
value.serialize(self)
}
fn serialize_newtype_variant<T: ?Sized + Serialize>(
self,
_name: &'static str,
_variant_index: u32,
variant: &'static str,
value: &T,
) -> Result<Self::Ok, Self::Error> {
self.body.push(MAJOR_TYPE_SMALL_MAP | 0x01);
variant.serialize(&mut *self)?;
value.serialize(self)
}
fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
BinaryComplexSerializer::new(self, len)
}
fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, Self::Error> {
self.serialize_seq(len.into())
}
fn serialize_tuple_struct(
self,
_name: &'static str,
len: usize,
) -> Result<Self::SerializeTupleStruct, Self::Error> {
self.serialize_tuple(len)
}
fn serialize_tuple_variant(
self,
_name: &'static str,
_variant_index: u32,
variant: &'static str,
len: usize,
) -> Result<Self::SerializeTupleVariant, Self::Error> {
BinaryComplexSerializer::new_enum(self, variant, len)
}
fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
BinaryComplexSerializer::new(self, len)
}
fn serialize_struct(
self,
_name: &'static str,
len: usize,
) -> Result<Self::SerializeStruct, Self::Error> {
self.serialize_map(len.into())
}
fn serialize_struct_variant(
self,
_name: &'static str,
_variant_index: u32,
variant: &'static str,
len: usize,
) -> Result<Self::SerializeStructVariant, Self::Error> {
BinaryComplexSerializer::new_enum(self, variant, len)
}
}
#[derive(Debug)]
pub struct BinaryComplexSerializer<'a> {
serializer: &'a mut BinarySerializer,
count_so_far: usize,
count_range: Range<usize>,
}
impl<'a> BinaryComplexSerializer<'a> {
fn new_priv(ser: &'a mut BinarySerializer, length: usize) -> Result<Self, Error> {
let buf_size = complex_type_count_buf_size(length)?;
let body_size_before = ser.body.len();
let body_size_after = body_size_before + buf_size;
ser.body.resize(body_size_after, 0x00);
Ok(BinaryComplexSerializer {
serializer: ser,
count_so_far: 0,
count_range: body_size_before..body_size_after,
})
}
fn new(ser: &'a mut BinarySerializer, length: Option<usize>) -> Result<Self, Error> {
Self::new_priv(ser, length.unwrap_or(usize::MAX))
}
fn new_enum(
ser: &'a mut BinarySerializer,
variant: &str,
length: usize,
) -> Result<Self, Error> {
ser.body.push(MAJOR_TYPE_SMALL_MAP | 0x01);
variant.serialize(&mut *ser)?;
Self::new_priv(ser, length)
}
}
impl<'a> SerializeSeq for BinaryComplexSerializer<'a> {
type Ok = ();
type Error = Error;
fn serialize_element<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), Self::Error> {
self.count_so_far += 1;
value.serialize(&mut *self.serializer)
}
fn end(self) -> Result<Self::Ok, Self::Error> {
write_complex_type_count_exact(
&mut self.serializer.body[self.count_range],
self.count_so_far,
MAJOR_TYPE_SMALL_ARRAY,
MINOR_TYPE_ARRAY,
)
}
}
impl<'a> SerializeTuple for BinaryComplexSerializer<'a> {
type Ok = <Self as SerializeSeq>::Ok;
type Error = <Self as SerializeSeq>::Error;
fn serialize_element<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), Self::Error> {
SerializeSeq::serialize_element(self, value)
}
fn end(self) -> Result<Self::Ok, Self::Error> {
SerializeSeq::end(self)
}
}
impl<'a> SerializeTupleStruct for BinaryComplexSerializer<'a> {
type Ok = <Self as SerializeTuple>::Ok;
type Error = <Self as SerializeTuple>::Error;
fn serialize_field<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), Self::Error> {
SerializeTuple::serialize_element(self, value)
}
fn end(self) -> Result<Self::Ok, Self::Error> {
SerializeTuple::end(self)
}
}
impl<'a> SerializeMap for BinaryComplexSerializer<'a> {
type Ok = ();
type Error = Error;
fn serialize_key<T: ?Sized + Serialize>(&mut self, key: &T) -> Result<(), Self::Error> {
self.count_so_far += 1;
key.serialize(&mut *self.serializer)
}
fn serialize_value<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), Self::Error> {
value.serialize(&mut *self.serializer)
}
fn end(self) -> Result<Self::Ok, Self::Error> {
write_complex_type_count_exact(
&mut self.serializer.body[self.count_range],
self.count_so_far,
MAJOR_TYPE_SMALL_MAP,
MINOR_TYPE_MAP,
)
}
}
impl<'a> SerializeStruct for BinaryComplexSerializer<'a> {
type Ok = <Self as SerializeMap>::Ok;
type Error = <Self as SerializeMap>::Error;
fn serialize_field<T: ?Sized + Serialize>(
&mut self,
key: &'static str,
value: &T
) -> Result<(), Self::Error> {
self.serialize_entry(key, value)
}
fn end(self) -> Result<Self::Ok, Self::Error> {
SerializeMap::end(self)
}
}
impl<'a> SerializeTupleVariant for BinaryComplexSerializer<'a> {
type Ok = <Self as SerializeTuple>::Ok;
type Error = <Self as SerializeTuple>::Error;
fn serialize_field<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), Self::Error> {
SerializeTuple::serialize_element(self, value)
}
fn end(self) -> Result<Self::Ok, Self::Error> {
SerializeTuple::end(self)
}
}
impl<'a> SerializeStructVariant for BinaryComplexSerializer<'a> {
type Ok = <Self as SerializeStruct>::Ok;
type Error = <Self as SerializeStruct>::Error;
fn serialize_field<T: ?Sized + Serialize>(
&mut self,
key: &'static str,
value: &T
) -> Result<(), Self::Error> {
self.serialize_entry(key, value)
}
fn end(self) -> Result<Self::Ok, Self::Error> {
SerializeStruct::end(self)
}
}
#[cfg(test)]
mod tests {
use crate::error::Result;
use super::complex_type_count_buf_size;
#[test]
fn complex_type_count_buf_size_works() -> Result<()> {
assert_eq!(complex_type_count_buf_size(0)?, 1);
assert_eq!(complex_type_count_buf_size(31)?, 1);
assert_eq!(complex_type_count_buf_size(32)?, 2);
assert_eq!(complex_type_count_buf_size(255)?, 2);
assert_eq!(complex_type_count_buf_size(256)?, 3);
assert_eq!(complex_type_count_buf_size(65535)?, 3);
#[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))]
{
assert_eq!(complex_type_count_buf_size(65536)?, 5);
assert_eq!(complex_type_count_buf_size(4294967295)?, 5);
}
#[cfg(target_pointer_width = "64")]
{
assert_eq!(complex_type_count_buf_size(4294967296)?, 9);
assert_eq!(complex_type_count_buf_size(18446744073709551615)?, 9);
}
Ok(())
}
}