mirror of
https://github.com/wez/wezterm.git
synced 2024-12-24 22:01:47 +03:00
add varbincode
This commit is contained in:
parent
217ad94c80
commit
322f7c74e6
@ -30,6 +30,7 @@ boxfnonce = "0.1"
|
|||||||
rayon = "1.0"
|
rayon = "1.0"
|
||||||
promise = { path = "promise" }
|
promise = { path = "promise" }
|
||||||
base91 = { path = "base91" }
|
base91 = { path = "base91" }
|
||||||
|
varbincode = { path = "varbincode" }
|
||||||
varu64 = "0.6"
|
varu64 = "0.6"
|
||||||
bincode = "1.1"
|
bincode = "1.1"
|
||||||
lazy_static = "1.3"
|
lazy_static = "1.3"
|
||||||
|
13
varbincode/Cargo.toml
Normal file
13
varbincode/Cargo.toml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
[package]
|
||||||
|
authors = ["Wez Furlong <wez@wezfurlong.org>"]
|
||||||
|
name = "varbincode"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
byteorder = "1.3"
|
||||||
|
leb128 = "0.2"
|
||||||
|
serde = "1.0"
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
serde_derive = "~1.0"
|
9
varbincode/README.md
Normal file
9
varbincode/README.md
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
# varbincode
|
||||||
|
|
||||||
|
varbincode is a binary serialization format that uses variable
|
||||||
|
length encoding for integer values, which typically results in
|
||||||
|
reduced size of the encoded data.
|
||||||
|
|
||||||
|
It is losely based on `bincode` which is offered under an MIT
|
||||||
|
license (same as the wezterm crate from which `varbincode`
|
||||||
|
originates) and is Copyright 2014 Ty Overby.
|
382
varbincode/src/de.rs
Normal file
382
varbincode/src/de.rs
Normal file
@ -0,0 +1,382 @@
|
|||||||
|
use crate::error::{Error, Result};
|
||||||
|
use byteorder::{LittleEndian, ReadBytesExt};
|
||||||
|
use serde::de::IntoDeserializer;
|
||||||
|
|
||||||
|
pub struct Deserializer<'a> {
|
||||||
|
reader: &'a mut std::io::Read,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Deserializer<'a> {
|
||||||
|
pub fn new(reader: &'a mut std::io::Read) -> Self {
|
||||||
|
Self { reader }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_signed(&mut self) -> Result<i64> {
|
||||||
|
leb128::read::signed(&mut self.reader).map_err(Into::into)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_unsigned(&mut self) -> Result<u64> {
|
||||||
|
leb128::read::unsigned(&mut self.reader).map_err(Into::into)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_vec(&mut self) -> Result<Vec<u8>> {
|
||||||
|
let len: usize = serde::Deserialize::deserialize(&mut *self)?;
|
||||||
|
let mut result = vec![0u8; len];
|
||||||
|
self.reader.read_exact(&mut result)?;
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_string(&mut self) -> Result<String> {
|
||||||
|
let vec = self.read_vec()?;
|
||||||
|
String::from_utf8(vec).map_err(|e| Error::InvalidUtf8Encoding(e.utf8_error()).into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_uint {
|
||||||
|
($ty:ty, $dser_method:ident, $visitor_method:ident, $reader_method:ident) => {
|
||||||
|
#[inline]
|
||||||
|
fn $dser_method<V>(self, visitor: V) -> Result<V::Value>
|
||||||
|
where V: serde::de::Visitor<'de>,
|
||||||
|
{
|
||||||
|
let value = self.$reader_method()?;
|
||||||
|
if value > <$ty>::max_value() as u64 {
|
||||||
|
Err(Error::NumberOutOfRange)
|
||||||
|
} else {
|
||||||
|
visitor.$visitor_method(value as $ty)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_int {
|
||||||
|
($ty:ty, $dser_method:ident, $visitor_method:ident, $reader_method:ident) => {
|
||||||
|
#[inline]
|
||||||
|
fn $dser_method<V>(self, visitor: V) -> Result<V::Value>
|
||||||
|
where V: serde::de::Visitor<'de>,
|
||||||
|
{
|
||||||
|
let value = self.$reader_method()?;
|
||||||
|
if value < <$ty>::min_value() as i64 || value > <$ty>::max_value() as i64 {
|
||||||
|
Err(Error::NumberOutOfRange)
|
||||||
|
} else {
|
||||||
|
visitor.$visitor_method(value as $ty)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
macro_rules! impl_float {
|
||||||
|
($dser_method:ident, $visitor_method:ident, $reader_method:ident) => {
|
||||||
|
#[inline]
|
||||||
|
fn $dser_method<V>(self, visitor: V) -> Result<V::Value>
|
||||||
|
where V: serde::de::Visitor<'de>,
|
||||||
|
{
|
||||||
|
let value = self.reader.$reader_method::<LittleEndian>()?;
|
||||||
|
visitor.$visitor_method(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de, 'a, 'b> serde::Deserializer<'de> for &'a mut Deserializer<'b> {
|
||||||
|
type Error = Error;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value>
|
||||||
|
where
|
||||||
|
V: serde::de::Visitor<'de>,
|
||||||
|
{
|
||||||
|
visitor.visit_u8(self.reader.read_u8()?)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn deserialize_i8<V>(self, visitor: V) -> Result<V::Value>
|
||||||
|
where
|
||||||
|
V: serde::de::Visitor<'de>,
|
||||||
|
{
|
||||||
|
visitor.visit_i8(self.reader.read_i8()?)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_uint!(u16, deserialize_u16, visit_u16, read_unsigned);
|
||||||
|
impl_uint!(u32, deserialize_u32, visit_u32, read_unsigned);
|
||||||
|
impl_uint!(u64, deserialize_u64, visit_u64, read_unsigned);
|
||||||
|
|
||||||
|
impl_int!(i16, deserialize_i16, visit_i16, read_signed);
|
||||||
|
impl_int!(i32, deserialize_i32, visit_i32, read_signed);
|
||||||
|
impl_int!(i64, deserialize_i64, visit_i64, read_signed);
|
||||||
|
|
||||||
|
impl_float!(deserialize_f32, visit_f32, read_f32);
|
||||||
|
impl_float!(deserialize_f64, visit_f64, read_f64);
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn deserialize_any<V>(self, _visitor: V) -> Result<V::Value>
|
||||||
|
where
|
||||||
|
V: serde::de::Visitor<'de>,
|
||||||
|
{
|
||||||
|
Err(Error::DeserializeAnyNotSupported)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value>
|
||||||
|
where
|
||||||
|
V: serde::de::Visitor<'de>,
|
||||||
|
{
|
||||||
|
let value: u8 = serde::Deserialize::deserialize(self)?;
|
||||||
|
match value {
|
||||||
|
1 => visitor.visit_bool(true),
|
||||||
|
0 => visitor.visit_bool(false),
|
||||||
|
value => Err(Error::InvalidBoolEncoding(value).into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value>
|
||||||
|
where
|
||||||
|
V: serde::de::Visitor<'de>,
|
||||||
|
{
|
||||||
|
visitor.visit_unit()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_char<V>(self, visitor: V) -> Result<V::Value>
|
||||||
|
where
|
||||||
|
V: serde::de::Visitor<'de>,
|
||||||
|
{
|
||||||
|
let value: u32 = serde::Deserialize::deserialize(self)?;
|
||||||
|
match std::char::from_u32(value) {
|
||||||
|
Some(c) => visitor.visit_char(c),
|
||||||
|
None => Err(Error::InvalidCharEncoding(value)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_str<V>(self, visitor: V) -> Result<V::Value>
|
||||||
|
where
|
||||||
|
V: serde::de::Visitor<'de>,
|
||||||
|
{
|
||||||
|
visitor.visit_string(self.read_string()?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_string<V>(self, visitor: V) -> Result<V::Value>
|
||||||
|
where
|
||||||
|
V: serde::de::Visitor<'de>,
|
||||||
|
{
|
||||||
|
visitor.visit_string(self.read_string()?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_bytes<V>(self, visitor: V) -> Result<V::Value>
|
||||||
|
where
|
||||||
|
V: serde::de::Visitor<'de>,
|
||||||
|
{
|
||||||
|
visitor.visit_byte_buf(self.read_vec()?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_byte_buf<V>(self, visitor: V) -> Result<V::Value>
|
||||||
|
where
|
||||||
|
V: serde::de::Visitor<'de>,
|
||||||
|
{
|
||||||
|
visitor.visit_byte_buf(self.read_vec()?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_enum<V>(
|
||||||
|
self,
|
||||||
|
_enum: &'static str,
|
||||||
|
_variants: &'static [&'static str],
|
||||||
|
visitor: V,
|
||||||
|
) -> Result<V::Value>
|
||||||
|
where
|
||||||
|
V: serde::de::Visitor<'de>,
|
||||||
|
{
|
||||||
|
visitor.visit_enum(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_tuple<V>(self, len: usize, visitor: V) -> Result<V::Value>
|
||||||
|
where
|
||||||
|
V: serde::de::Visitor<'de>,
|
||||||
|
{
|
||||||
|
visitor.visit_seq(Access {
|
||||||
|
deserializer: self,
|
||||||
|
len: len,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value>
|
||||||
|
where
|
||||||
|
V: serde::de::Visitor<'de>,
|
||||||
|
{
|
||||||
|
let value: u8 = serde::de::Deserialize::deserialize(&mut *self)?;
|
||||||
|
match value {
|
||||||
|
0 => visitor.visit_none(),
|
||||||
|
1 => visitor.visit_some(&mut *self),
|
||||||
|
v => Err(Error::InvalidTagEncoding(v as usize).into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value>
|
||||||
|
where
|
||||||
|
V: serde::de::Visitor<'de>,
|
||||||
|
{
|
||||||
|
let len = serde::Deserialize::deserialize(&mut *self)?;
|
||||||
|
|
||||||
|
self.deserialize_tuple(len, visitor)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_map<V>(self, visitor: V) -> Result<V::Value>
|
||||||
|
where
|
||||||
|
V: serde::de::Visitor<'de>,
|
||||||
|
{
|
||||||
|
let len = serde::Deserialize::deserialize(&mut *self)?;
|
||||||
|
|
||||||
|
visitor.visit_map(Access {
|
||||||
|
deserializer: self,
|
||||||
|
len: len,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_struct<V>(
|
||||||
|
self,
|
||||||
|
_name: &str,
|
||||||
|
fields: &'static [&'static str],
|
||||||
|
visitor: V,
|
||||||
|
) -> Result<V::Value>
|
||||||
|
where
|
||||||
|
V: serde::de::Visitor<'de>,
|
||||||
|
{
|
||||||
|
self.deserialize_tuple(fields.len(), visitor)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_identifier<V>(self, _visitor: V) -> Result<V::Value>
|
||||||
|
where
|
||||||
|
V: serde::de::Visitor<'de>,
|
||||||
|
{
|
||||||
|
Err(Error::DeserializeIdentifierNotSupported)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_newtype_struct<V>(self, _name: &str, visitor: V) -> Result<V::Value>
|
||||||
|
where
|
||||||
|
V: serde::de::Visitor<'de>,
|
||||||
|
{
|
||||||
|
visitor.visit_newtype_struct(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_unit_struct<V>(self, _name: &'static str, visitor: V) -> Result<V::Value>
|
||||||
|
where
|
||||||
|
V: serde::de::Visitor<'de>,
|
||||||
|
{
|
||||||
|
visitor.visit_unit()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_tuple_struct<V>(
|
||||||
|
self,
|
||||||
|
_name: &'static str,
|
||||||
|
len: usize,
|
||||||
|
visitor: V,
|
||||||
|
) -> Result<V::Value>
|
||||||
|
where
|
||||||
|
V: serde::de::Visitor<'de>,
|
||||||
|
{
|
||||||
|
self.deserialize_tuple(len, visitor)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_ignored_any<V>(self, _visitor: V) -> Result<V::Value>
|
||||||
|
where
|
||||||
|
V: serde::de::Visitor<'de>,
|
||||||
|
{
|
||||||
|
Err(Error::DeserializeIgnoredAnyNotSupported)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_human_readable(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Access<'a, 'b> {
|
||||||
|
deserializer: &'a mut Deserializer<'b>,
|
||||||
|
len: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de, 'a, 'b> serde::de::SeqAccess<'de> for Access<'a, 'b> {
|
||||||
|
type Error = Error;
|
||||||
|
|
||||||
|
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>>
|
||||||
|
where
|
||||||
|
T: serde::de::DeserializeSeed<'de>,
|
||||||
|
{
|
||||||
|
if self.len > 0 {
|
||||||
|
self.len -= 1;
|
||||||
|
let value = serde::de::DeserializeSeed::deserialize(seed, &mut *self.deserializer)?;
|
||||||
|
Ok(Some(value))
|
||||||
|
} else {
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn size_hint(&self) -> Option<usize> {
|
||||||
|
Some(self.len)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de, 'a, 'b> serde::de::MapAccess<'de> for Access<'a, 'b> {
|
||||||
|
type Error = Error;
|
||||||
|
|
||||||
|
fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>>
|
||||||
|
where
|
||||||
|
K: serde::de::DeserializeSeed<'de>,
|
||||||
|
{
|
||||||
|
if self.len > 0 {
|
||||||
|
self.len -= 1;
|
||||||
|
let key = serde::de::DeserializeSeed::deserialize(seed, &mut *self.deserializer)?;
|
||||||
|
Ok(Some(key))
|
||||||
|
} else {
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value>
|
||||||
|
where
|
||||||
|
V: serde::de::DeserializeSeed<'de>,
|
||||||
|
{
|
||||||
|
let value = serde::de::DeserializeSeed::deserialize(seed, &mut *self.deserializer)?;
|
||||||
|
Ok(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn size_hint(&self) -> Option<usize> {
|
||||||
|
Some(self.len)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de, 'a, 'b> serde::de::EnumAccess<'de> for &'a mut Deserializer<'b> {
|
||||||
|
type Error = Error;
|
||||||
|
type Variant = Self;
|
||||||
|
|
||||||
|
fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant)>
|
||||||
|
where
|
||||||
|
V: serde::de::DeserializeSeed<'de>,
|
||||||
|
{
|
||||||
|
let idx: u32 = serde::de::Deserialize::deserialize(&mut *self)?;
|
||||||
|
let val: Result<_> = seed.deserialize(idx.into_deserializer());
|
||||||
|
Ok((val?, self))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de, 'a, 'b> serde::de::VariantAccess<'de> for &'a mut Deserializer<'b> {
|
||||||
|
type Error = Error;
|
||||||
|
|
||||||
|
fn unit_variant(self) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value>
|
||||||
|
where
|
||||||
|
T: serde::de::DeserializeSeed<'de>,
|
||||||
|
{
|
||||||
|
serde::de::DeserializeSeed::deserialize(seed, self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn tuple_variant<V>(self, len: usize, visitor: V) -> Result<V::Value>
|
||||||
|
where
|
||||||
|
V: serde::de::Visitor<'de>,
|
||||||
|
{
|
||||||
|
serde::de::Deserializer::deserialize_tuple(self, len, visitor)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn struct_variant<V>(self, fields: &'static [&'static str], visitor: V) -> Result<V::Value>
|
||||||
|
where
|
||||||
|
V: serde::de::Visitor<'de>,
|
||||||
|
{
|
||||||
|
serde::de::Deserializer::deserialize_tuple(self, fields.len(), visitor)
|
||||||
|
}
|
||||||
|
}
|
72
varbincode/src/error.rs
Normal file
72
varbincode/src/error.rs
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
use serde::{de, ser};
|
||||||
|
use std::fmt::{self, Display};
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
pub enum Error {
|
||||||
|
Message(String),
|
||||||
|
Io(String),
|
||||||
|
SequenceMustHaveLength,
|
||||||
|
LebOverflow,
|
||||||
|
DeserializeAnyNotSupported,
|
||||||
|
DeserializeIdentifierNotSupported,
|
||||||
|
DeserializeIgnoredAnyNotSupported,
|
||||||
|
InvalidBoolEncoding(u8),
|
||||||
|
InvalidCharEncoding(u32),
|
||||||
|
InvalidUtf8Encoding(std::str::Utf8Error),
|
||||||
|
InvalidTagEncoding(usize),
|
||||||
|
NumberOutOfRange,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type Result<T> = std::result::Result<T, Error>;
|
||||||
|
|
||||||
|
impl ser::Error for Error {
|
||||||
|
fn custom<T: Display>(msg: T) -> Self {
|
||||||
|
Error::Message(msg.to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl de::Error for Error {
|
||||||
|
fn custom<T: Display>(msg: T) -> Self {
|
||||||
|
Error::Message(msg.to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<std::io::Error> for Error {
|
||||||
|
fn from(err: std::io::Error) -> Error {
|
||||||
|
Error::Io(format!("{}", err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<leb128::read::Error> for Error {
|
||||||
|
fn from(err: leb128::read::Error) -> Error {
|
||||||
|
match err {
|
||||||
|
leb128::read::Error::IoError(err) => Error::Io(format!("{}", err)),
|
||||||
|
leb128::read::Error::Overflow => Error::LebOverflow,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for Error {
|
||||||
|
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
formatter.write_str(std::error::Error::description(self))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::error::Error for Error {
|
||||||
|
fn description(&self) -> &str {
|
||||||
|
match *self {
|
||||||
|
Error::Message(ref msg) => msg,
|
||||||
|
Error::Io(ref msg) => msg,
|
||||||
|
Error::SequenceMustHaveLength => "SequenceMustHaveLength",
|
||||||
|
Error::DeserializeAnyNotSupported => "DeserializeAnyNotSupported",
|
||||||
|
Error::LebOverflow => "LEB128 Overflow",
|
||||||
|
Error::InvalidBoolEncoding(_) => "Invalid Bool Encoding",
|
||||||
|
Error::InvalidCharEncoding(_) => "Invalid char encoding",
|
||||||
|
Error::DeserializeIdentifierNotSupported => "DeserializeIdentifierNotSupported",
|
||||||
|
Error::DeserializeIgnoredAnyNotSupported => "DeserializeIgnoredAnyNotSupported",
|
||||||
|
Error::InvalidUtf8Encoding(_) => "InvalidUtf8Encoding",
|
||||||
|
Error::InvalidTagEncoding(_) => "InvalidTagEncoding",
|
||||||
|
Error::NumberOutOfRange => "NumberOutOfRange",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
26
varbincode/src/lib.rs
Normal file
26
varbincode/src/lib.rs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
//! varbincode is a binary serialization format that uses variable
|
||||||
|
//! length encoding for integer values, which typically results in
|
||||||
|
//! reduced size of the encoded data.
|
||||||
|
pub mod de;
|
||||||
|
pub mod error;
|
||||||
|
pub mod ser;
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test;
|
||||||
|
|
||||||
|
/// A convenience function for serializing a value as a byte vector
|
||||||
|
/// See also `ser::Serializer`.
|
||||||
|
pub fn serialize<T: serde::Serialize>(t: &T) -> Result<Vec<u8>, error::Error> {
|
||||||
|
let mut result = Vec::new();
|
||||||
|
let mut s = ser::Serializer::new(&mut result);
|
||||||
|
t.serialize(&mut s)?;
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A convenience function for deserializing from a stream.
|
||||||
|
/// See also `de::Deserializer`.
|
||||||
|
pub fn deserialize<T: serde::de::DeserializeOwned, R: std::io::Read>(
|
||||||
|
mut r: R,
|
||||||
|
) -> Result<T, error::Error> {
|
||||||
|
let mut d = de::Deserializer::new(&mut r);
|
||||||
|
serde::Deserialize::deserialize(&mut d)
|
||||||
|
}
|
345
varbincode/src/ser.rs
Normal file
345
varbincode/src/ser.rs
Normal file
@ -0,0 +1,345 @@
|
|||||||
|
use crate::error::Error;
|
||||||
|
use byteorder::{LittleEndian, WriteBytesExt};
|
||||||
|
use serde::ser;
|
||||||
|
|
||||||
|
pub struct Serializer<'a> {
|
||||||
|
writer: &'a mut std::io::Write,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Serializer<'a> {
|
||||||
|
pub fn new(writer: &'a mut std::io::Write) -> Self {
|
||||||
|
Self { writer }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_signed(&mut self, val: i64) -> Result<usize, std::io::Error> {
|
||||||
|
leb128::write::signed(&mut self.writer, val)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_unsigned(&mut self, val: u64) -> Result<usize, std::io::Error> {
|
||||||
|
leb128::write::unsigned(&mut self.writer, val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'b> ser::Serializer for &'a mut Serializer<'b> {
|
||||||
|
type Ok = ();
|
||||||
|
type Error = Error;
|
||||||
|
type SerializeSeq = Self;
|
||||||
|
type SerializeTuple = Self;
|
||||||
|
type SerializeTupleStruct = Self;
|
||||||
|
type SerializeTupleVariant = Self;
|
||||||
|
type SerializeMap = Self;
|
||||||
|
type SerializeStruct = Self;
|
||||||
|
type SerializeStructVariant = Self;
|
||||||
|
|
||||||
|
fn serialize_bool(self, v: bool) -> Result<(), Error> {
|
||||||
|
self.write_unsigned(if v { 1 } else { 0 })?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize_unit(self) -> Result<(), Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize_unit_struct(self, _: &'static str) -> Result<(), Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize_u8(self, v: u8) -> Result<(), Error> {
|
||||||
|
self.writer.write_u8(v as _)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize_u16(self, v: u16) -> Result<(), Error> {
|
||||||
|
self.write_unsigned(v as _)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize_u32(self, v: u32) -> Result<(), Error> {
|
||||||
|
self.write_unsigned(v as _)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize_u64(self, v: u64) -> Result<(), Error> {
|
||||||
|
self.write_unsigned(v as _)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize_i8(self, v: i8) -> Result<(), Error> {
|
||||||
|
self.writer.write_i8(v as _)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize_i16(self, v: i16) -> Result<(), Error> {
|
||||||
|
self.write_signed(v as _)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize_i32(self, v: i32) -> Result<(), Error> {
|
||||||
|
self.write_signed(v as _)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize_i64(self, v: i64) -> Result<(), Error> {
|
||||||
|
self.write_signed(v as _)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize_f32(self, v: f32) -> Result<(), Error> {
|
||||||
|
self.writer.write_f32::<LittleEndian>(v)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize_f64(self, v: f64) -> Result<(), Error> {
|
||||||
|
self.writer.write_f64::<LittleEndian>(v)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize_str(self, v: &str) -> Result<(), Error> {
|
||||||
|
self.serialize_bytes(v.as_bytes())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize_char(self, c: char) -> Result<(), Error> {
|
||||||
|
self.serialize_u32(c as u32)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize_bytes(self, v: &[u8]) -> Result<(), Error> {
|
||||||
|
self.serialize_u64(v.len() as u64)?;
|
||||||
|
self.writer.write_all(v)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize_none(self) -> Result<(), Error> {
|
||||||
|
self.serialize_u8(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize_some<T: serde::Serialize + ?Sized>(self, v: &T) -> Result<(), Error> {
|
||||||
|
self.serialize_u8(1)?;
|
||||||
|
v.serialize(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, Error> {
|
||||||
|
let len = len.ok_or(Error::SequenceMustHaveLength)?;
|
||||||
|
self.serialize_u64(len as u64)?;
|
||||||
|
Ok(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple, Error> {
|
||||||
|
Ok(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize_tuple_struct(
|
||||||
|
self,
|
||||||
|
_name: &'static str,
|
||||||
|
_len: usize,
|
||||||
|
) -> Result<Self::SerializeTupleStruct, Error> {
|
||||||
|
Ok(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize_tuple_variant(
|
||||||
|
self,
|
||||||
|
_name: &'static str,
|
||||||
|
variant_index: u32,
|
||||||
|
_variant: &'static str,
|
||||||
|
_len: usize,
|
||||||
|
) -> Result<Self::SerializeTupleVariant, Error> {
|
||||||
|
self.serialize_u32(variant_index)?;
|
||||||
|
Ok(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, Error> {
|
||||||
|
let len = len.ok_or(Error::SequenceMustHaveLength)?;
|
||||||
|
self.serialize_u64(len as u64)?;
|
||||||
|
Ok(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize_struct(
|
||||||
|
self,
|
||||||
|
_name: &'static str,
|
||||||
|
_len: usize,
|
||||||
|
) -> Result<Self::SerializeStruct, Error> {
|
||||||
|
Ok(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize_struct_variant(
|
||||||
|
self,
|
||||||
|
_name: &'static str,
|
||||||
|
variant_index: u32,
|
||||||
|
_variant: &'static str,
|
||||||
|
_len: usize,
|
||||||
|
) -> Result<Self::SerializeStructVariant, Error> {
|
||||||
|
self.serialize_u32(variant_index)?;
|
||||||
|
Ok(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize_newtype_struct<T: ?Sized>(
|
||||||
|
self,
|
||||||
|
_name: &'static str,
|
||||||
|
value: &T,
|
||||||
|
) -> Result<(), Error>
|
||||||
|
where
|
||||||
|
T: serde::ser::Serialize,
|
||||||
|
{
|
||||||
|
value.serialize(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize_newtype_variant<T: ?Sized>(
|
||||||
|
self,
|
||||||
|
_name: &'static str,
|
||||||
|
variant_index: u32,
|
||||||
|
_variant: &'static str,
|
||||||
|
value: &T,
|
||||||
|
) -> Result<(), Error>
|
||||||
|
where
|
||||||
|
T: serde::ser::Serialize,
|
||||||
|
{
|
||||||
|
self.serialize_u32(variant_index)?;
|
||||||
|
value.serialize(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize_unit_variant(
|
||||||
|
self,
|
||||||
|
_name: &'static str,
|
||||||
|
variant_index: u32,
|
||||||
|
_variant: &'static str,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
self.serialize_u32(variant_index)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_human_readable(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'b> ser::SerializeSeq for &'a mut Serializer<'b> {
|
||||||
|
type Ok = ();
|
||||||
|
type Error = Error;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
|
||||||
|
where
|
||||||
|
T: serde::ser::Serialize,
|
||||||
|
{
|
||||||
|
value.serialize(&mut **self)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn end(self) -> Result<(), Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'b> ser::SerializeTuple for &'a mut Serializer<'b> {
|
||||||
|
type Ok = ();
|
||||||
|
type Error = Error;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
|
||||||
|
where
|
||||||
|
T: serde::ser::Serialize,
|
||||||
|
{
|
||||||
|
value.serialize(&mut **self)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn end(self) -> Result<(), Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'b> ser::SerializeTupleStruct for &'a mut Serializer<'b> {
|
||||||
|
type Ok = ();
|
||||||
|
type Error = Error;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
|
||||||
|
where
|
||||||
|
T: serde::ser::Serialize,
|
||||||
|
{
|
||||||
|
value.serialize(&mut **self)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn end(self) -> Result<(), Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'b> ser::SerializeTupleVariant for &'a mut Serializer<'b> {
|
||||||
|
type Ok = ();
|
||||||
|
type Error = Error;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
|
||||||
|
where
|
||||||
|
T: serde::ser::Serialize,
|
||||||
|
{
|
||||||
|
value.serialize(&mut **self)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn end(self) -> Result<(), Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'b> ser::SerializeMap for &'a mut Serializer<'b> {
|
||||||
|
type Ok = ();
|
||||||
|
type Error = Error;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn serialize_key<K: ?Sized>(&mut self, value: &K) -> Result<(), Error>
|
||||||
|
where
|
||||||
|
K: serde::ser::Serialize,
|
||||||
|
{
|
||||||
|
value.serialize(&mut **self)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn serialize_value<V: ?Sized>(&mut self, value: &V) -> Result<(), Error>
|
||||||
|
where
|
||||||
|
V: serde::ser::Serialize,
|
||||||
|
{
|
||||||
|
value.serialize(&mut **self)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn end(self) -> Result<(), Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'b> ser::SerializeStruct for &'a mut Serializer<'b> {
|
||||||
|
type Ok = ();
|
||||||
|
type Error = Error;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn serialize_field<T: ?Sized>(&mut self, _key: &'static str, value: &T) -> Result<(), Error>
|
||||||
|
where
|
||||||
|
T: serde::ser::Serialize,
|
||||||
|
{
|
||||||
|
value.serialize(&mut **self)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn end(self) -> Result<(), Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'b> ser::SerializeStructVariant for &'a mut Serializer<'b> {
|
||||||
|
type Ok = ();
|
||||||
|
type Error = Error;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn serialize_field<T: ?Sized>(&mut self, _key: &'static str, value: &T) -> Result<(), Error>
|
||||||
|
where
|
||||||
|
T: serde::ser::Serialize,
|
||||||
|
{
|
||||||
|
value.serialize(&mut **self)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn end(self) -> Result<(), Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
141
varbincode/src/test.rs
Normal file
141
varbincode/src/test.rs
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
use super::{deserialize, error::Error, serialize};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use serde_derive::*;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
fn same<'de, T: serde::de::DeserializeOwned + Serialize + std::fmt::Debug + PartialEq>(a: T) {
|
||||||
|
let encoded = serialize(&a).unwrap();
|
||||||
|
let decoded: T = deserialize(encoded.as_slice()).unwrap();
|
||||||
|
assert_eq!(decoded, a);
|
||||||
|
eprintln!("{:?} encoded as {:?}", a, encoded);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test() {
|
||||||
|
same(0u8);
|
||||||
|
same(1u8);
|
||||||
|
same(1i8);
|
||||||
|
same(0i8);
|
||||||
|
same(0u16);
|
||||||
|
same(255u16);
|
||||||
|
same(0xffffu16);
|
||||||
|
same(0x7fffi16);
|
||||||
|
same(-0x7fffi16);
|
||||||
|
same(0x00ff_ffffu32);
|
||||||
|
same(0xffff_ffffu32);
|
||||||
|
same(0x00ff_ffffu64);
|
||||||
|
same(0xffff_ffffu64);
|
||||||
|
same(0xffff_ffff_ffffu64);
|
||||||
|
same(0xffff_ffff_ffff_ffffu64);
|
||||||
|
same(0f32);
|
||||||
|
same(10.5f32);
|
||||||
|
same(10.5f64);
|
||||||
|
same(-10.5f64);
|
||||||
|
|
||||||
|
same("".to_string());
|
||||||
|
same("hello".to_string());
|
||||||
|
|
||||||
|
same((1u8,));
|
||||||
|
same((1u8, 2, 3));
|
||||||
|
same((1u8, "foo".to_string()));
|
||||||
|
|
||||||
|
same(true);
|
||||||
|
same(false);
|
||||||
|
|
||||||
|
same(Some(true));
|
||||||
|
same(None::<bool>);
|
||||||
|
|
||||||
|
same('c');
|
||||||
|
same(b'c');
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_structs() {
|
||||||
|
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
||||||
|
struct Struct {
|
||||||
|
a: isize,
|
||||||
|
b: String,
|
||||||
|
c: bool,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
||||||
|
struct Outer {
|
||||||
|
inner: Struct,
|
||||||
|
b: bool,
|
||||||
|
second: Struct,
|
||||||
|
};
|
||||||
|
|
||||||
|
same(Struct {
|
||||||
|
a: -42,
|
||||||
|
b: "hello".to_string(),
|
||||||
|
c: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
same(Outer {
|
||||||
|
inner: Struct {
|
||||||
|
a: 1,
|
||||||
|
b: "bee".to_string(),
|
||||||
|
c: false,
|
||||||
|
},
|
||||||
|
b: true,
|
||||||
|
second: Struct {
|
||||||
|
a: 2,
|
||||||
|
b: "other".to_string(),
|
||||||
|
c: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
||||||
|
struct NewType(usize);
|
||||||
|
same(NewType(123));
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
||||||
|
struct NewTypeTuple(usize, bool);
|
||||||
|
same(NewTypeTuple(123, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_enum() {
|
||||||
|
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
||||||
|
enum TestEnum {
|
||||||
|
NoArg,
|
||||||
|
OneArg(usize),
|
||||||
|
Args(usize, usize),
|
||||||
|
AnotherNoArg,
|
||||||
|
StructLike { x: usize, y: f32 },
|
||||||
|
}
|
||||||
|
same(TestEnum::NoArg);
|
||||||
|
same(TestEnum::OneArg(4));
|
||||||
|
same(TestEnum::Args(4, 5));
|
||||||
|
same(TestEnum::AnotherNoArg);
|
||||||
|
same(TestEnum::StructLike { x: 4, y: 3.14159 });
|
||||||
|
same(vec![
|
||||||
|
TestEnum::NoArg,
|
||||||
|
TestEnum::OneArg(5),
|
||||||
|
TestEnum::AnotherNoArg,
|
||||||
|
TestEnum::StructLike { x: 4, y: 1.4 },
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_vec() {
|
||||||
|
let v: Vec<u8> = vec![];
|
||||||
|
same(v);
|
||||||
|
same(vec![1u64]);
|
||||||
|
same(vec![1u64, 2, 3, 4, 5, 6]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_map() {
|
||||||
|
let mut m = HashMap::new();
|
||||||
|
m.insert(4u64, "foo".to_string());
|
||||||
|
m.insert(0u64, "bar".to_string());
|
||||||
|
same(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_fixed_size_array() {
|
||||||
|
same([24u32; 32]);
|
||||||
|
same([1u64, 2, 3, 4, 5, 6, 7, 8]);
|
||||||
|
same([0u8; 19]);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user