refactored errors and ser to support nostd to-buffer encoding

This commit is contained in:
Sergey Chernov 2023-11-28 00:58:33 +03:00
parent c1b1cceaa1
commit 52ab4a1f7b
10 changed files with 170 additions and 127 deletions

View File

@ -1,6 +1,6 @@
[package] [package]
name = "bipack_ru" name = "bipack_ru"
version = "0.3.3" version = "0.4.0"
edition = "2021" edition = "2021"
license = "Apache-2.0" license = "Apache-2.0"
description = "binary size-effective format used in Divan smart contracts, wasm bindings, network protocols, etc." description = "binary size-effective format used in Divan smart contracts, wasm bindings, network protocols, etc."

View File

@ -44,6 +44,13 @@ pub struct DefinitelyBigEndian {
} }
``` ```
## Fixed or variable length arrays?
When encoding arrays, the rule is simple:
- dynamic arrays (arrays, vectors, etc) are encoding with size, as variable-length
- fixed-size arrays, like tuples `(1,2,3,4,5)`, or something like `[u32; 5]` are encoded as fixed-size entities.
# Direct usage (no serde) # Direct usage (no serde)
The sample code (see `src/lib.rs` for more:) The sample code (see `src/lib.rs` for more:)

View File

@ -4,7 +4,7 @@ use crate::bipack_source::{BipackSource, Result};
/// The trait to unpack to be used in serializer to come. Please don't use it, it is /// The trait to unpack to be used in serializer to come. Please don't use it, it is
/// experimental. /// experimental.
pub trait BiPackable { pub trait BiPackable {
fn bi_pack(self: &Self, sink: &mut impl BipackSink); fn bi_pack(self: &Self, sink: &mut impl BipackSink) -> Result<()>;
} }
/// The trait need by [bipack()] macro and in the serializer to come, packs some /// The trait need by [bipack()] macro and in the serializer to come, packs some
@ -24,20 +24,20 @@ macro_rules! bipack {
( $( $e: expr),* ) => {{ ( $( $e: expr),* ) => {{
let mut result = Vec::new(); let mut result = Vec::new();
$( $(
$e.bi_pack(&mut result); $e.bi_pack(&mut result).unwrap();
)* )*
result result
}}; }};
} }
impl<T: IntoU64 + Copy> BiPackable for T { impl<T: IntoU64 + Copy> BiPackable for T {
fn bi_pack(self: &Self, sink: &mut impl BipackSink) { fn bi_pack(self: &Self, sink: &mut impl BipackSink) -> Result<()> {
sink.put_unsigned(self.into_u64()) sink.put_unsigned(self.into_u64())
} }
} }
impl BiPackable for &str { impl BiPackable for &str {
fn bi_pack(self: &Self, sink: &mut impl BipackSink) { fn bi_pack(self: &Self, sink: &mut impl BipackSink) -> Result<()> {
sink.put_str(self) sink.put_str(self)
} }
} }

View File

@ -14,6 +14,7 @@
use std::iter::Iterator; use std::iter::Iterator;
use std::usize; use std::usize;
use crate::bipack_source::Result;
const V0LIMIT: u64 = 1u64 << 6; const V0LIMIT: u64 = 1u64 << 6;
const V1LIMIT: u64 = 1u64 << 14; const V1LIMIT: u64 = 1u64 << 14;
@ -48,85 +49,89 @@ into_u64!(u8, u16, u32, usize, u64);
/// sink you can create one that ignores extra data when overflow is detected and report it /// sink you can create one that ignores extra data when overflow is detected and report it
/// somehow, but for encoding it does not worth effort (data size could be estimated in advance). /// somehow, but for encoding it does not worth effort (data size could be estimated in advance).
pub trait BipackSink { pub trait BipackSink {
fn put_u8(self: &mut Self, data: u8);
fn put_fixed_bytes(self: &mut Self, data: &[u8]) { fn put_u8(self: &mut Self, data: u8) -> Result<()>;
for b in data { self.put_u8(*b); }
fn put_fixed_bytes(self: &mut Self, data: &[u8]) -> Result<()> {
for b in data { self.put_u8(*b)?; }
Ok(())
} }
fn put_var_bytes(self: &mut Self, data: &[u8]) { fn put_var_bytes(self: &mut Self, data: &[u8]) -> Result<()> {
self.put_unsigned(data.len()); self.put_unsigned(data.len())?;
self.put_fixed_bytes(data); self.put_fixed_bytes(data)
} }
fn put_str(self: &mut Self, str: &str) { fn put_str(self: &mut Self, str: &str) -> Result<()> {
self.put_var_bytes(str.as_bytes()); self.put_var_bytes(str.as_bytes())
} }
fn put_u16(self: &mut Self, mut value: u16) { fn put_u16(self: &mut Self, mut value: u16) -> Result<()>{
let mut result = [0u8; 2]; let mut result = [0u8; 2];
for i in (0..result.len()).rev() { for i in (0..result.len()).rev() {
result[i] = value as u8; result[i] = value as u8;
value = value >> 8; value = value >> 8;
} }
self.put_fixed_bytes(&result); self.put_fixed_bytes(&result)
} }
fn put_u32(self: &mut Self, mut value: u32) { fn put_u32(self: &mut Self, mut value: u32) -> Result<()> {
let mut result = [0u8; 4]; let mut result = [0u8; 4];
for i in (0..result.len()).rev() { for i in (0..result.len()).rev() {
result[i] = value as u8; result[i] = value as u8;
value = value >> 8; value = value >> 8;
} }
self.put_fixed_bytes(&result); self.put_fixed_bytes(&result)
} }
fn put_u64(self: &mut Self, mut value: u64) { fn put_u64(self: &mut Self, mut value: u64) -> Result<()> {
let mut result = [0u8; 8]; let mut result = [0u8; 8];
for i in (0..result.len()).rev() { for i in (0..result.len()).rev() {
result[i] = value as u8; result[i] = value as u8;
value = value >> 8; value = value >> 8;
} }
self.put_fixed_bytes(&result); self.put_fixed_bytes(&result)
} }
fn put_i64(self: &mut Self, value: i64) { fn put_i64(self: &mut Self, value: i64) -> Result<()> {
self.put_u64(value as u64) self.put_u64(value as u64)
} }
fn put_i32(self: &mut Self, value: i32) { fn put_i32(self: &mut Self, value: i32) -> Result<()> {
self.put_u32(value as u32) self.put_u32(value as u32)
} }
fn put_i16(self: &mut Self, value: i16) { fn put_i16(self: &mut Self, value: i16) -> Result<()> {
self.put_u16(value as u16) self.put_u16(value as u16)
} }
fn put_i8(self: &mut Self, value: i8) { fn put_i8(self: &mut Self, value: i8) -> Result<()>{
self.put_u8(value as u8) self.put_u8(value as u8)
} }
/// Put unsigned value to compressed variable-length format, `Smartint` in the bipack /// Put unsigned value to compressed variable-length format, `Smartint` in the bipack
/// terms. This format is used to store size of variable-length binaries and strings. /// terms. This format is used to store size of variable-length binaries and strings.
/// Use [crate::bipack_source::BipackSource::get_unsigned] to unpack it. /// Use [crate::bipack_source::BipackSource::get_unsigned] to unpack it.
fn put_unsigned<T: IntoU64>(self: &mut Self, number: T) { fn put_unsigned<T: IntoU64>(self: &mut Self, number: T) -> Result<()> {
let value = number.into_u64(); let value = number.into_u64();
let mut encode_seq = |ty: u8, bytes: &[u64]| { let mut encode_seq = |ty: u8, bytes: &[u64]| -> Result<()> {
if bytes.len() == 0 { self.put_u8(0); } else { if bytes.len() == 0 { self.put_u8(0)?; } else {
if bytes[0] as u64 > V0LIMIT { panic!("first byte is too big (internal error)"); } if bytes[0] as u64 > V0LIMIT { panic!("first byte is too big (internal error)"); }
self.put_u8((ty & 0x03) | ((bytes[0] as u8) << 2)); self.put_u8((ty & 0x03) | ((bytes[0] as u8) << 2))?;
for i in 1..bytes.len() { for i in 1..bytes.len() {
self.put_u8(bytes[i] as u8); self.put_u8(bytes[i] as u8)?;
} }
} }
Ok(())
}; };
if value < V0LIMIT { if value < V0LIMIT {
encode_seq(0, &[value]); encode_seq(0, &[value])?;
} else if value < V1LIMIT { } else if value < V1LIMIT {
encode_seq(1, &[value & 0x3F, value >> 6]); encode_seq(1, &[value & 0x3F, value >> 6])?;
} else if value < V2LIMIT { } else if value < V2LIMIT {
encode_seq(2, &[value & 0x3f, value >> 6, value >> 14]); encode_seq(2, &[value & 0x3f, value >> 6, value >> 14])?;
} else { } else {
encode_seq(3, &[value & 0x3f, value >> 6, value >> 14]); encode_seq(3, &[value & 0x3f, value >> 6, value >> 14])?;
self.put_var_unsigned(value >> 22); self.put_var_unsigned(value >> 22)?;
} }
Ok(())
} }
/// Put variable-length encoded integer value. it is packed just like variable-length /// Put variable-length encoded integer value. it is packed just like variable-length
@ -135,30 +140,35 @@ pub trait BipackSink {
/// ///
/// Note that for really big number using [BipackSink::put_i64] could be more effective /// Note that for really big number using [BipackSink::put_i64] could be more effective
/// than the variable-length. /// than the variable-length.
fn put_signed(self: &mut Self, val: i64) { fn put_signed(self: &mut Self, val: i64) -> Result<()> {
let (neg, val) = if val < 0 { (1, -val) } else { (0, val) }; let (neg, val) = if val < 0 { (1, -val) } else { (0, val) };
self.put_unsigned( (neg as u64) | ((val as u64) << 1) ); self.put_unsigned( (neg as u64) | ((val as u64) << 1) )
} }
fn put_var_unsigned(self: &mut Self, value: u64) { fn put_var_unsigned(self: &mut Self, value: u64) -> Result<()>{
let mut rest = value; let mut rest = value;
loop { loop {
let x = rest & 127; let x = rest & 127;
rest = rest >> 7; rest = rest >> 7;
if rest > 0 { if rest > 0 {
self.put_u8((x | 0x80) as u8); self.put_u8((x | 0x80) as u8)?;
} else { } else {
self.put_u8(x as u8) self.put_u8(x as u8)?
} }
if rest == 0 { break; } if rest == 0 { break; }
} }
Ok(())
} }
} }
impl BipackSink for Vec<u8> { impl BipackSink for Vec<u8> {
fn put_u8(self: &mut Self, data: u8) { fn put_u8(self: &mut Self, data: u8) -> Result<()> {
self.push(data); self.push(data);
Ok(())
} }
} }

View File

@ -20,10 +20,19 @@ use crate::bipack_source::BipackError::NoDataError;
pub type Result<T> = std::result::Result<T, BipackError>; pub type Result<T> = std::result::Result<T, BipackError>;
/// There is not enought data to fulfill the request /// There is not enought data to fulfill the request
#[derive(Debug, Clone)] #[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum BipackError { pub enum BipackError {
NoDataError, NoDataError,
BadEncoding(FromUtf8Error), BadEncoding(FromUtf8Error),
BufferOverflow,
Message(String),
BadFormat(String),
Eof,
ExtraBytes,
NotSupported,
NotImplemented,
NotPossible
} }
impl std::error::Error for BipackError {} impl std::error::Error for BipackError {}

26
src/buffer_sink.rs Normal file
View File

@ -0,0 +1,26 @@
use crate::bipack_sink::BipackSink;
use crate::bipack_source::BipackError;
use crate::bipack_source::Result;
pub struct BufferSink<'a> {
pub buffer: & 'a mut [u8],
pub pos: usize
}
impl<'a> BufferSink<'a> {
pub fn result_slice(self) -> & 'a [u8] {
&self.buffer[0..self.pos]
}
}
impl<'a> BipackSink for BufferSink<'a> {
fn put_u8(self: &mut Self, data: u8) -> Result<()> {
if self.pos >= self.buffer.len() {
Err(BipackError::BufferOverflow)
} else {
self.buffer[self.pos] = data;
self.pos+=1;
Ok(())
}
}
}

View File

@ -2,8 +2,8 @@ use serde::de::{self, DeserializeSeed, IntoDeserializer, MapAccess, SeqAccess, V
use serde::de::value::U32Deserializer; use serde::de::value::U32Deserializer;
use serde::Deserialize; use serde::Deserialize;
use crate::bipack_source::{BipackSource, SliceSource}; use crate::bipack_source::{BipackError, BipackSource, SliceSource};
use crate::error::{Error, Result}; use crate::error::{Result};
pub struct Deserializer<T: BipackSource> { pub struct Deserializer<T: BipackSource> {
// This string starts with the input data and characters are truncated off // This string starts with the input data and characters are truncated off
@ -17,10 +17,10 @@ pub fn from_bytes<'de, T: Deserialize<'de>>(source: &[u8]) -> Result<T> {
} }
impl<'de, 'a, T: BipackSource> de::Deserializer<'de> for &'a mut Deserializer<T> { impl<'de, 'a, T: BipackSource> de::Deserializer<'de> for &'a mut Deserializer<T> {
type Error = Error; type Error = BipackError;
fn deserialize_any<V>(self, visitor: V) -> std::result::Result<V::Value, Self::Error> where V: Visitor<'de> { fn deserialize_any<V>(self, visitor: V) -> std::result::Result<V::Value, Self::Error> where V: Visitor<'de> {
Err(Error::NotPossible) Err(BipackError::NotPossible)
} }
fn deserialize_bool<V>(self, visitor: V) -> std::result::Result<V::Value, Self::Error> where V: Visitor<'de> { fn deserialize_bool<V>(self, visitor: V) -> std::result::Result<V::Value, Self::Error> where V: Visitor<'de> {
@ -60,17 +60,17 @@ impl<'de, 'a, T: BipackSource> de::Deserializer<'de> for &'a mut Deserializer<T
} }
fn deserialize_f32<V>(self, visitor: V) -> std::result::Result<V::Value, Self::Error> where V: Visitor<'de> { fn deserialize_f32<V>(self, visitor: V) -> std::result::Result<V::Value, Self::Error> where V: Visitor<'de> {
Err(Error::NotImplemented) Err(BipackError::NotImplemented)
} }
fn deserialize_f64<V>(self, visitor: V) -> std::result::Result<V::Value, Self::Error> where V: Visitor<'de> { fn deserialize_f64<V>(self, visitor: V) -> std::result::Result<V::Value, Self::Error> where V: Visitor<'de> {
Err(Error::NotImplemented) Err(BipackError::NotImplemented)
} }
fn deserialize_char<V>(self, visitor: V) -> std::result::Result<V::Value, Self::Error> where V: Visitor<'de> { fn deserialize_char<V>(self, visitor: V) -> std::result::Result<V::Value, Self::Error> where V: Visitor<'de> {
let ch = self.input.get_str()?; let ch = self.input.get_str()?;
if ch.len() != 1 { if ch.len() != 1 {
Err(Error::BadFormat(format!("Char length is {}, should be 1 {:?}", ch.len(), ch))) Err(BipackError::BadFormat(format!("Char length is {}, should be 1 {:?}", ch.len(), ch)))
} else { } else {
visitor.visit_char(ch.chars().next().unwrap()) visitor.visit_char(ch.chars().next().unwrap())
} }
@ -149,11 +149,11 @@ impl<'de, 'a, T: BipackSource> de::Deserializer<'de> for &'a mut Deserializer<T
} }
fn deserialize_identifier<V>(self, visitor: V) -> std::result::Result<V::Value, Self::Error> where V: Visitor<'de> { fn deserialize_identifier<V>(self, visitor: V) -> std::result::Result<V::Value, Self::Error> where V: Visitor<'de> {
Err(Error::NotPossible) Err(BipackError::NotPossible)
} }
fn deserialize_ignored_any<V>(self, visitor: V) -> std::result::Result<V::Value, Self::Error> where V: Visitor<'de> { fn deserialize_ignored_any<V>(self, visitor: V) -> std::result::Result<V::Value, Self::Error> where V: Visitor<'de> {
Err(Error::NotPossible) Err(BipackError::NotPossible)
} }
fn is_human_readable(&self) -> bool { fn is_human_readable(&self) -> bool {
@ -162,13 +162,13 @@ impl<'de, 'a, T: BipackSource> de::Deserializer<'de> for &'a mut Deserializer<T
} }
impl<'de, 'a, T: BipackSource> serde::de::EnumAccess<'de> for &'a mut Deserializer<T> { impl<'de, 'a, T: BipackSource> serde::de::EnumAccess<'de> for &'a mut Deserializer<T> {
type Error = Error; type Error = BipackError;
type Variant = Self; type Variant = Self;
#[inline] #[inline]
fn variant_seed<V: DeserializeSeed<'de>>(self, seed: V) -> Result<(V::Value, Self)> { fn variant_seed<V: DeserializeSeed<'de>>(self, seed: V) -> Result<(V::Value, Self)> {
let varint: u32 = self.input.get_unsigned()? as u32; let varint: u32 = self.input.get_unsigned()? as u32;
let v = DeserializeSeed::deserialize::<U32Deserializer<Error>>( let v = DeserializeSeed::deserialize::<U32Deserializer<BipackError>>(
seed, seed,
varint.into_deserializer())?; varint.into_deserializer())?;
Ok((v, self)) Ok((v, self))
@ -176,7 +176,7 @@ impl<'de, 'a, T: BipackSource> serde::de::EnumAccess<'de> for &'a mut Deserializ
} }
impl<'de, 'a, T: BipackSource> serde::de::VariantAccess<'de> for &'a mut Deserializer<T> { impl<'de, 'a, T: BipackSource> serde::de::VariantAccess<'de> for &'a mut Deserializer<T> {
type Error = Error; type Error = BipackError;
#[inline] #[inline]
fn unit_variant(self) -> Result<()> { fn unit_variant(self) -> Result<()> {
@ -221,7 +221,7 @@ impl<'a, T: BipackSource> SimpleSeq<'a, T> {
// `SeqAccess` is provided to the `Visitor` to give it the ability to iterate // `SeqAccess` is provided to the `Visitor` to give it the ability to iterate
// through elements of the sequence. // through elements of the sequence.
impl<'de, 'a, T: BipackSource> SeqAccess<'de> for SimpleSeq<'a, T> { impl<'de, 'a, T: BipackSource> SeqAccess<'de> for SimpleSeq<'a, T> {
type Error = Error; type Error = BipackError;
fn next_element_seed<S>(&mut self, seed: S) -> Result<Option<S::Value>> fn next_element_seed<S>(&mut self, seed: S) -> Result<Option<S::Value>>
where where
@ -242,7 +242,7 @@ struct SimpleMap<'a, T: BipackSource> {
} }
impl<'de, 'a, T: BipackSource> MapAccess<'de> for SimpleMap<'a,T> { impl<'de, 'a, T: BipackSource> MapAccess<'de> for SimpleMap<'a,T> {
type Error = Error; type Error = BipackError;
fn next_key_seed<K>(&mut self, seed: K) -> std::result::Result<Option<K::Value>, Self::Error> where K: DeserializeSeed<'de> { fn next_key_seed<K>(&mut self, seed: K) -> std::result::Result<Option<K::Value>, Self::Error> where K: DeserializeSeed<'de> {
if self.size < 1 { if self.size < 1 {
@ -264,10 +264,11 @@ mod tests {
use std::fmt::Debug; use std::fmt::Debug;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::bipack_source::BipackError;
use crate::de::from_bytes; use crate::de::from_bytes;
use crate::error::Result; use crate::error::Result;
use crate::ser::to_bytes; use crate::ser::{to_buffer, to_bytes};
use crate::tools::to_dump; use crate::tools::to_dump;
#[test] #[test]
@ -349,6 +350,17 @@ mod tests {
let packed = to_bytes(x).unwrap(); let packed = to_bytes(x).unwrap();
println!("packed {:?}:\n{}", x, to_dump(&packed) ); println!("packed {:?}:\n{}", x, to_dump(&packed) );
assert_eq!(*x, from_bytes(&packed).unwrap()); assert_eq!(*x, from_bytes(&packed).unwrap());
let mut buffer = [0u8; 128];
let packed2 = to_buffer(x, & mut buffer).unwrap();
assert_eq!(*x, from_bytes(&packed2).unwrap());
if packed.len() > 1 {
let mut small_buffer = [0u8; 1];
let result = to_buffer(x, & mut small_buffer);
assert_eq!(true, result.is_err());
assert_eq!(BipackError::BufferOverflow, result.err().unwrap());
}
} }
#[test] #[test]

View File

@ -1,51 +1,20 @@
use std; use std;
use std::fmt::{self, Display}; use std::fmt::Display;
use serde::{de, ser}; use serde::{de, ser};
use crate::bipack_source::BipackError; use crate::bipack_source::BipackError;
pub type Result<T> = std::result::Result<T, Error>; pub type Result<T> = std::result::Result<T, BipackError>;
#[derive(Debug)] impl ser::Error for BipackError {
pub enum Error {
Message(String),
BadFormat(String),
Eof,
ExtraBytes,
BadEncoding,
NotSupported,
NotImplemented,
NotPossible
}
impl Display for Error {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
match self {
Error::Message(msg) => formatter.write_str(msg),
_ => write!(formatter, "BiPack error: {:?}", self),
}
}
}
impl std::error::Error for Error {}
impl ser::Error for Error {
fn custom<T: Display>(msg: T) -> Self { fn custom<T: Display>(msg: T) -> Self {
Error::Message(msg.to_string()) BipackError::Message(msg.to_string())
} }
} }
impl de::Error for Error { impl de::Error for BipackError {
fn custom<T: Display>(msg: T) -> Self { fn custom<T: Display>(msg: T) -> Self {
Error::Message(msg.to_string()) BipackError::Message(msg.to_string())
}
}
impl From<BipackError> for Error {
fn from(value: BipackError) -> Self {
match &value {
BipackError::NoDataError => Error::Eof,
BipackError::BadEncoding(_) => Error::BadEncoding,
// other => Error::Message(format!("BiPack error: {}", value))
}
} }
} }

View File

@ -124,6 +124,7 @@ pub mod de;
pub mod crc; pub mod crc;
pub mod contrail; pub mod contrail;
pub mod fixint; pub mod fixint;
pub mod buffer_sink;
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
@ -168,20 +169,20 @@ mod tests {
#[test] #[test]
fn fixed_pack() { fn fixed_pack() {
let mut data: Vec<u8> = Vec::new(); let mut data: Vec<u8> = Vec::new();
data.put_u8(7); data.put_u8(7).unwrap();
data.put_u16(64000); data.put_u16(64000).unwrap();
data.put_u32(66000); data.put_u32(66000).unwrap();
data.put_u64(931127140399); data.put_u64(931127140399).unwrap();
assert_eq!("07fa00000101d0000000d8cb80a02f", hex::encode(&data)); assert_eq!("07fa00000101d0000000d8cb80a02f", hex::encode(&data));
} }
#[test] #[test]
fn smart_pack() { fn smart_pack() {
let mut data: Vec<u8> = Vec::new(); let mut data: Vec<u8> = Vec::new();
data.put_u8(7); data.put_u8(7).unwrap();
data.put_unsigned(64000u16); data.put_unsigned(64000u16).unwrap();
data.put_unsigned(66000u32); data.put_unsigned(66000u32).unwrap();
data.put_unsigned(931127140399u64); data.put_unsigned(931127140399u64).unwrap();
// println!("?? {}", hex::encode(&data)); // println!("?? {}", hex::encode(&data));
assert_eq!("0702e803420704bf8002aec60d", hex::encode(&data)); assert_eq!("0702e803420704bf8002aec60d", hex::encode(&data));
} }
@ -189,7 +190,7 @@ mod tests {
#[test] #[test]
fn pack_varbinaries_and_string() { fn pack_varbinaries_and_string() {
let mut data = Vec::<u8>::new(); let mut data = Vec::<u8>::new();
data.put_str("Hello, rupack!"); data.put_str("Hello, rupack!").unwrap();
println!("size ${}\n{}",data.len(), to_dump(&data)); println!("size ${}\n{}",data.len(), to_dump(&data));
let mut src = SliceSource::from(&data); let mut src = SliceSource::from(&data);
assert_eq!("Hello, rupack!", src.get_str().unwrap()); assert_eq!("Hello, rupack!", src.get_str().unwrap());
@ -199,7 +200,7 @@ mod tests {
fn test_signed() -> Result<()> { fn test_signed() -> Result<()> {
fn test64(value: i64) -> Result<()> { fn test64(value: i64) -> Result<()> {
let mut x = Vec::new(); let mut x = Vec::new();
x.put_i64(value); x.put_i64(value).unwrap();
assert_eq!(value, SliceSource::from(&x).get_i64()?); assert_eq!(value, SliceSource::from(&x).get_i64()?);
Ok(()) Ok(())
} }
@ -210,7 +211,7 @@ mod tests {
test64(-9223372036854775808)?; test64(-9223372036854775808)?;
fn test32(value: i32) -> Result<()> { fn test32(value: i32) -> Result<()> {
let mut x = Vec::new(); let mut x = Vec::new();
x.put_i32(value); x.put_i32(value).unwrap();
assert_eq!(value, SliceSource::from(&x).get_i32()?); assert_eq!(value, SliceSource::from(&x).get_i32()?);
Ok(()) Ok(())
} }
@ -221,7 +222,7 @@ mod tests {
test32(-2147483648)?; test32(-2147483648)?;
fn test16(value: i16) -> Result<()> { fn test16(value: i16) -> Result<()> {
let mut x = Vec::new(); let mut x = Vec::new();
x.put_i16(value); x.put_i16(value).unwrap();
assert_eq!(value, SliceSource::from(&x).get_i16()?); assert_eq!(value, SliceSource::from(&x).get_i16()?);
Ok(()) Ok(())
} }
@ -254,7 +255,7 @@ mod tests {
fn test_varsigned() -> Result<()> { fn test_varsigned() -> Result<()> {
fn test(value: i64) -> Result<()> { fn test(value: i64) -> Result<()> {
let mut x = Vec::new(); let mut x = Vec::new();
x.put_signed(value); x.put_signed(value).unwrap();
assert_eq!(value, SliceSource::from(&x).get_signed()?); assert_eq!(value, SliceSource::from(&x).get_signed()?);
Ok(()) Ok(())
} }

View File

@ -1,7 +1,9 @@
use serde::{ser, Serialize}; use serde::{ser, Serialize};
use crate::bipack_sink::{BipackSink, IntoU64}; use crate::bipack_sink::{BipackSink, IntoU64};
use crate::error::{Error, Result}; use crate::bipack_source::BipackError;
use crate::buffer_sink::BufferSink;
use crate::error::{Result};
pub struct Serializer<S: BipackSink> { pub struct Serializer<S: BipackSink> {
// This string starts empty and JSON is appended as values are serialized. // This string starts empty and JSON is appended as values are serialized.
@ -16,9 +18,15 @@ pub fn to_bytes<T>(value: &T) -> Result<Vec<u8>>
Ok(serializer.output) Ok(serializer.output)
} }
pub fn to_buffer<'a, T: Serialize>(value: &T, buffer: & 'a mut [u8]) -> Result<& 'a [u8]> {
let mut serializer = Serializer { output: BufferSink { buffer: buffer, pos: 0}};
value.serialize(&mut serializer)?;
Ok(serializer.output.result_slice())
}
impl<'a, S: BipackSink> ser::Serializer for &'a mut Serializer<S> { impl<'a, S: BipackSink> ser::Serializer for &'a mut Serializer<S> {
type Ok = (); type Ok = ();
type Error = Error; type Error = BipackError;
type SerializeSeq = Self; type SerializeSeq = Self;
type SerializeTuple = Self; type SerializeTuple = Self;
type SerializeTupleStruct = Self; type SerializeTupleStruct = Self;
@ -28,17 +36,18 @@ impl<'a, S: BipackSink> ser::Serializer for &'a mut Serializer<S> {
type SerializeStructVariant = Self; type SerializeStructVariant = Self;
fn serialize_bool(self, v: bool) -> Result<()> { fn serialize_bool(self, v: bool) -> Result<()> {
self.output.put_u8(if v { 1 } else { 0 }); self.output.put_u8(if v { 1 } else { 0 })?;
Ok(()) Ok(())
} }
fn serialize_i8(self, v: i8) -> Result<()> { fn serialize_i8(self, v: i8) -> Result<()> {
self.output.put_i8(v); self.output.put_i8(v)?;
Ok(()) Ok(())
} }
fn serialize_i16(self, v: i16) -> Result<()> { fn serialize_i16(self, v: i16) -> Result<()> {
self.serialize_i64(i64::from(v)) self.serialize_i64(i64::from(v))?;
Ok(())
} }
fn serialize_i32(self, v: i32) -> Result<()> { fn serialize_i32(self, v: i32) -> Result<()> {
@ -46,12 +55,12 @@ impl<'a, S: BipackSink> ser::Serializer for &'a mut Serializer<S> {
} }
fn serialize_i64(self, v: i64) -> Result<()> { fn serialize_i64(self, v: i64) -> Result<()> {
self.output.put_signed(v); self.output.put_signed(v)?;
Ok(()) Ok(())
} }
fn serialize_u8(self, v: u8) -> Result<()> { fn serialize_u8(self, v: u8) -> Result<()> {
self.output.put_u8(v); self.output.put_u8(v)?;
Ok(()) Ok(())
} }
fn serialize_u16(self, v: u16) -> Result<()> { fn serialize_u16(self, v: u16) -> Result<()> {
@ -63,7 +72,7 @@ impl<'a, S: BipackSink> ser::Serializer for &'a mut Serializer<S> {
Ok(()) Ok(())
} }
fn serialize_u64(self, v: u64) -> Result<()> { fn serialize_u64(self, v: u64) -> Result<()> {
self.output.put_unsigned(v); self.output.put_unsigned(v)?;
Ok(()) Ok(())
} }
@ -82,12 +91,12 @@ impl<'a, S: BipackSink> ser::Serializer for &'a mut Serializer<S> {
} }
fn serialize_str(self, v: &str) -> Result<()> { fn serialize_str(self, v: &str) -> Result<()> {
self.output.put_str(v); self.output.put_str(v)?;
Ok(()) Ok(())
} }
fn serialize_bytes(self, v: &[u8]) -> Result<()> { fn serialize_bytes(self, v: &[u8]) -> Result<()> {
self.output.put_var_bytes(v); self.output.put_var_bytes(v)?;
Ok(()) Ok(())
} }
@ -149,7 +158,7 @@ impl<'a, S: BipackSink> ser::Serializer for &'a mut Serializer<S> {
/// We expect it to use with vairable-length arrays... /// We expect it to use with vairable-length arrays...
fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq> { fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq> {
self.output.put_unsigned(_len.unwrap_or(0)); self.output.put_unsigned(_len.unwrap_or(0))?;
Ok(self) Ok(self)
} }
@ -178,7 +187,7 @@ impl<'a, S: BipackSink> ser::Serializer for &'a mut Serializer<S> {
} }
fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap> { fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap> {
self.output.put_unsigned(_len.unwrap_or(0)); self.output.put_unsigned(_len.unwrap_or(0))?;
Ok(self) Ok(self)
} }
@ -197,7 +206,7 @@ impl<'a, S: BipackSink> ser::Serializer for &'a mut Serializer<S> {
variant: &'static str, variant: &'static str,
_len: usize, _len: usize,
) -> Result<Self::SerializeStructVariant> { ) -> Result<Self::SerializeStructVariant> {
self.output.put_unsigned(_variant_index); self.output.put_unsigned(_variant_index)?;
Ok(self) Ok(self)
} }
} }
@ -206,7 +215,7 @@ impl<'a, S: BipackSink> ser::SerializeSeq for &'a mut Serializer<S> {
// Must match the `Ok` type of the serializer. // Must match the `Ok` type of the serializer.
type Ok = (); type Ok = ();
// Must match the `Error` type of the serializer. // Must match the `Error` type of the serializer.
type Error = Error; type Error = BipackError;
// Serialize a single element of the sequence. // Serialize a single element of the sequence.
fn serialize_element<T>(&mut self, value: &T) -> Result<()> fn serialize_element<T>(&mut self, value: &T) -> Result<()>
@ -224,7 +233,7 @@ impl<'a, S: BipackSink> ser::SerializeSeq for &'a mut Serializer<S> {
impl<'a, S: BipackSink> ser::SerializeTuple for &'a mut Serializer<S> { impl<'a, S: BipackSink> ser::SerializeTuple for &'a mut Serializer<S> {
type Ok = (); type Ok = ();
type Error = Error; type Error = BipackError;
fn serialize_element<T>(&mut self, value: &T) -> Result<()> fn serialize_element<T>(&mut self, value: &T) -> Result<()>
where where
@ -240,7 +249,7 @@ impl<'a, S: BipackSink> ser::SerializeTuple for &'a mut Serializer<S> {
impl<'a, S: BipackSink> ser::SerializeTupleStruct for &'a mut Serializer<S> { impl<'a, S: BipackSink> ser::SerializeTupleStruct for &'a mut Serializer<S> {
type Ok = (); type Ok = ();
type Error = Error; type Error = BipackError;
fn serialize_field<T>(&mut self, value: &T) -> Result<()> fn serialize_field<T>(&mut self, value: &T) -> Result<()>
where where
@ -256,7 +265,7 @@ impl<'a, S: BipackSink> ser::SerializeTupleStruct for &'a mut Serializer<S> {
impl<'a, S: BipackSink> ser::SerializeTupleVariant for &'a mut Serializer<S> { impl<'a, S: BipackSink> ser::SerializeTupleVariant for &'a mut Serializer<S> {
type Ok = (); type Ok = ();
type Error = Error; type Error = BipackError;
fn serialize_field<T>(&mut self, value: &T) -> Result<()> fn serialize_field<T>(&mut self, value: &T) -> Result<()>
where where
@ -272,7 +281,7 @@ impl<'a, S: BipackSink> ser::SerializeTupleVariant for &'a mut Serializer<S> {
impl<'a, S: BipackSink> ser::SerializeMap for &'a mut Serializer<S> { impl<'a, S: BipackSink> ser::SerializeMap for &'a mut Serializer<S> {
type Ok = (); type Ok = ();
type Error = Error; type Error = BipackError;
// The Serde data model allows map keys to be any serializable type. JSON // The Serde data model allows map keys to be any serializable type. JSON
// only allows string keys so the implementation below will produce invalid // only allows string keys so the implementation below will produce invalid
@ -308,7 +317,7 @@ impl<'a, S: BipackSink> ser::SerializeMap for &'a mut Serializer<S> {
// constant strings. // constant strings.
impl<'a, S: BipackSink> ser::SerializeStruct for &'a mut Serializer<S> { impl<'a, S: BipackSink> ser::SerializeStruct for &'a mut Serializer<S> {
type Ok = (); type Ok = ();
type Error = Error; type Error = BipackError;
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()> fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
where where
@ -324,7 +333,7 @@ impl<'a, S: BipackSink> ser::SerializeStruct for &'a mut Serializer<S> {
impl<'a, S: BipackSink> ser::SerializeStructVariant for &'a mut Serializer<S> { impl<'a, S: BipackSink> ser::SerializeStructVariant for &'a mut Serializer<S> {
type Ok = (); type Ok = ();
type Error = Error; type Error = BipackError;
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()> fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
where where