refactored errors and ser to support nostd to-buffer encoding
This commit is contained in:
parent
c1b1cceaa1
commit
52ab4a1f7b
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "bipack_ru"
|
||||
version = "0.3.3"
|
||||
version = "0.4.0"
|
||||
edition = "2021"
|
||||
license = "Apache-2.0"
|
||||
description = "binary size-effective format used in Divan smart contracts, wasm bindings, network protocols, etc."
|
||||
|
@ -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)
|
||||
|
||||
The sample code (see `src/lib.rs` for more:)
|
||||
|
@ -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
|
||||
/// experimental.
|
||||
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
|
||||
@ -24,20 +24,20 @@ macro_rules! bipack {
|
||||
( $( $e: expr),* ) => {{
|
||||
let mut result = Vec::new();
|
||||
$(
|
||||
$e.bi_pack(&mut result);
|
||||
$e.bi_pack(&mut result).unwrap();
|
||||
)*
|
||||
result
|
||||
}};
|
||||
}
|
||||
|
||||
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())
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,7 @@
|
||||
|
||||
use std::iter::Iterator;
|
||||
use std::usize;
|
||||
use crate::bipack_source::Result;
|
||||
|
||||
const V0LIMIT: u64 = 1u64 << 6;
|
||||
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
|
||||
/// somehow, but for encoding it does not worth effort (data size could be estimated in advance).
|
||||
pub trait BipackSink {
|
||||
fn put_u8(self: &mut Self, data: u8);
|
||||
|
||||
fn put_fixed_bytes(self: &mut Self, data: &[u8]) {
|
||||
for b in data { self.put_u8(*b); }
|
||||
fn put_u8(self: &mut Self, data: u8) -> Result<()>;
|
||||
|
||||
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]) {
|
||||
self.put_unsigned(data.len());
|
||||
self.put_fixed_bytes(data);
|
||||
fn put_var_bytes(self: &mut Self, data: &[u8]) -> Result<()> {
|
||||
self.put_unsigned(data.len())?;
|
||||
self.put_fixed_bytes(data)
|
||||
}
|
||||
|
||||
fn put_str(self: &mut Self, str: &str) {
|
||||
self.put_var_bytes(str.as_bytes());
|
||||
fn put_str(self: &mut Self, str: &str) -> Result<()> {
|
||||
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];
|
||||
for i in (0..result.len()).rev() {
|
||||
result[i] = value as u8;
|
||||
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];
|
||||
for i in (0..result.len()).rev() {
|
||||
result[i] = value as u8;
|
||||
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];
|
||||
for i in (0..result.len()).rev() {
|
||||
result[i] = value as u8;
|
||||
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)
|
||||
}
|
||||
fn put_i32(self: &mut Self, value: i32) {
|
||||
fn put_i32(self: &mut Self, value: i32) -> Result<()> {
|
||||
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)
|
||||
}
|
||||
fn put_i8(self: &mut Self, value: i8) {
|
||||
fn put_i8(self: &mut Self, value: i8) -> Result<()>{
|
||||
self.put_u8(value as u8)
|
||||
}
|
||||
|
||||
/// 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.
|
||||
/// 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 mut encode_seq = |ty: u8, bytes: &[u64]| {
|
||||
if bytes.len() == 0 { self.put_u8(0); } else {
|
||||
let mut encode_seq = |ty: u8, bytes: &[u64]| -> Result<()> {
|
||||
if bytes.len() == 0 { self.put_u8(0)?; } else {
|
||||
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() {
|
||||
self.put_u8(bytes[i] as u8);
|
||||
self.put_u8(bytes[i] as u8)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
};
|
||||
|
||||
if value < V0LIMIT {
|
||||
encode_seq(0, &[value]);
|
||||
encode_seq(0, &[value])?;
|
||||
} else if value < V1LIMIT {
|
||||
encode_seq(1, &[value & 0x3F, value >> 6]);
|
||||
encode_seq(1, &[value & 0x3F, value >> 6])?;
|
||||
} else if value < V2LIMIT {
|
||||
encode_seq(2, &[value & 0x3f, value >> 6, value >> 14]);
|
||||
encode_seq(2, &[value & 0x3f, value >> 6, value >> 14])?;
|
||||
} else {
|
||||
encode_seq(3, &[value & 0x3f, value >> 6, value >> 14]);
|
||||
self.put_var_unsigned(value >> 22);
|
||||
encode_seq(3, &[value & 0x3f, value >> 6, value >> 14])?;
|
||||
self.put_var_unsigned(value >> 22)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 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
|
||||
/// 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) };
|
||||
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;
|
||||
loop {
|
||||
let x = rest & 127;
|
||||
rest = rest >> 7;
|
||||
if rest > 0 {
|
||||
self.put_u8((x | 0x80) as u8);
|
||||
self.put_u8((x | 0x80) as u8)?;
|
||||
} else {
|
||||
self.put_u8(x as u8)
|
||||
self.put_u8(x as u8)?
|
||||
}
|
||||
if rest == 0 { break; }
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -20,10 +20,19 @@ use crate::bipack_source::BipackError::NoDataError;
|
||||
pub type Result<T> = std::result::Result<T, BipackError>;
|
||||
|
||||
/// There is not enought data to fulfill the request
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[non_exhaustive]
|
||||
pub enum BipackError {
|
||||
NoDataError,
|
||||
BadEncoding(FromUtf8Error),
|
||||
BufferOverflow,
|
||||
Message(String),
|
||||
BadFormat(String),
|
||||
Eof,
|
||||
ExtraBytes,
|
||||
NotSupported,
|
||||
NotImplemented,
|
||||
NotPossible
|
||||
}
|
||||
|
||||
impl std::error::Error for BipackError {}
|
||||
|
26
src/buffer_sink.rs
Normal file
26
src/buffer_sink.rs
Normal 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(())
|
||||
}
|
||||
}
|
||||
}
|
42
src/de.rs
42
src/de.rs
@ -2,8 +2,8 @@ use serde::de::{self, DeserializeSeed, IntoDeserializer, MapAccess, SeqAccess, V
|
||||
use serde::de::value::U32Deserializer;
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::bipack_source::{BipackSource, SliceSource};
|
||||
use crate::error::{Error, Result};
|
||||
use crate::bipack_source::{BipackError, BipackSource, SliceSource};
|
||||
use crate::error::{Result};
|
||||
|
||||
pub struct Deserializer<T: BipackSource> {
|
||||
// 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> {
|
||||
type Error = Error;
|
||||
type Error = BipackError;
|
||||
|
||||
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> {
|
||||
@ -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> {
|
||||
Err(Error::NotImplemented)
|
||||
Err(BipackError::NotImplemented)
|
||||
}
|
||||
|
||||
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> {
|
||||
let ch = self.input.get_str()?;
|
||||
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 {
|
||||
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> {
|
||||
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> {
|
||||
Err(Error::NotPossible)
|
||||
Err(BipackError::NotPossible)
|
||||
}
|
||||
|
||||
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> {
|
||||
type Error = Error;
|
||||
type Error = BipackError;
|
||||
type Variant = Self;
|
||||
|
||||
#[inline]
|
||||
fn variant_seed<V: DeserializeSeed<'de>>(self, seed: V) -> Result<(V::Value, Self)> {
|
||||
let varint: u32 = self.input.get_unsigned()? as u32;
|
||||
let v = DeserializeSeed::deserialize::<U32Deserializer<Error>>(
|
||||
let v = DeserializeSeed::deserialize::<U32Deserializer<BipackError>>(
|
||||
seed,
|
||||
varint.into_deserializer())?;
|
||||
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> {
|
||||
type Error = Error;
|
||||
type Error = BipackError;
|
||||
|
||||
#[inline]
|
||||
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
|
||||
// through elements of the sequence.
|
||||
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>>
|
||||
where
|
||||
@ -242,7 +242,7 @@ struct SimpleMap<'a, T: BipackSource> {
|
||||
}
|
||||
|
||||
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> {
|
||||
if self.size < 1 {
|
||||
@ -264,10 +264,11 @@ mod tests {
|
||||
use std::fmt::Debug;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use crate::bipack_source::BipackError;
|
||||
|
||||
use crate::de::from_bytes;
|
||||
use crate::error::Result;
|
||||
use crate::ser::to_bytes;
|
||||
use crate::ser::{to_buffer, to_bytes};
|
||||
use crate::tools::to_dump;
|
||||
|
||||
#[test]
|
||||
@ -349,6 +350,17 @@ mod tests {
|
||||
let packed = to_bytes(x).unwrap();
|
||||
println!("packed {:?}:\n{}", x, to_dump(&packed) );
|
||||
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]
|
||||
|
47
src/error.rs
47
src/error.rs
@ -1,51 +1,20 @@
|
||||
use std;
|
||||
use std::fmt::{self, Display};
|
||||
use std::fmt::Display;
|
||||
|
||||
use serde::{de, ser};
|
||||
|
||||
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)]
|
||||
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 {
|
||||
impl ser::Error for BipackError {
|
||||
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 {
|
||||
Error::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))
|
||||
}
|
||||
BipackError::Message(msg.to_string())
|
||||
}
|
||||
}
|
||||
|
27
src/lib.rs
27
src/lib.rs
@ -124,6 +124,7 @@ pub mod de;
|
||||
pub mod crc;
|
||||
pub mod contrail;
|
||||
pub mod fixint;
|
||||
pub mod buffer_sink;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
@ -168,20 +169,20 @@ mod tests {
|
||||
#[test]
|
||||
fn fixed_pack() {
|
||||
let mut data: Vec<u8> = Vec::new();
|
||||
data.put_u8(7);
|
||||
data.put_u16(64000);
|
||||
data.put_u32(66000);
|
||||
data.put_u64(931127140399);
|
||||
data.put_u8(7).unwrap();
|
||||
data.put_u16(64000).unwrap();
|
||||
data.put_u32(66000).unwrap();
|
||||
data.put_u64(931127140399).unwrap();
|
||||
assert_eq!("07fa00000101d0000000d8cb80a02f", hex::encode(&data));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn smart_pack() {
|
||||
let mut data: Vec<u8> = Vec::new();
|
||||
data.put_u8(7);
|
||||
data.put_unsigned(64000u16);
|
||||
data.put_unsigned(66000u32);
|
||||
data.put_unsigned(931127140399u64);
|
||||
data.put_u8(7).unwrap();
|
||||
data.put_unsigned(64000u16).unwrap();
|
||||
data.put_unsigned(66000u32).unwrap();
|
||||
data.put_unsigned(931127140399u64).unwrap();
|
||||
// println!("?? {}", hex::encode(&data));
|
||||
assert_eq!("0702e803420704bf8002aec60d", hex::encode(&data));
|
||||
}
|
||||
@ -189,7 +190,7 @@ mod tests {
|
||||
#[test]
|
||||
fn pack_varbinaries_and_string() {
|
||||
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));
|
||||
let mut src = SliceSource::from(&data);
|
||||
assert_eq!("Hello, rupack!", src.get_str().unwrap());
|
||||
@ -199,7 +200,7 @@ mod tests {
|
||||
fn test_signed() -> Result<()> {
|
||||
fn test64(value: i64) -> Result<()> {
|
||||
let mut x = Vec::new();
|
||||
x.put_i64(value);
|
||||
x.put_i64(value).unwrap();
|
||||
assert_eq!(value, SliceSource::from(&x).get_i64()?);
|
||||
Ok(())
|
||||
}
|
||||
@ -210,7 +211,7 @@ mod tests {
|
||||
test64(-9223372036854775808)?;
|
||||
fn test32(value: i32) -> Result<()> {
|
||||
let mut x = Vec::new();
|
||||
x.put_i32(value);
|
||||
x.put_i32(value).unwrap();
|
||||
assert_eq!(value, SliceSource::from(&x).get_i32()?);
|
||||
Ok(())
|
||||
}
|
||||
@ -221,7 +222,7 @@ mod tests {
|
||||
test32(-2147483648)?;
|
||||
fn test16(value: i16) -> Result<()> {
|
||||
let mut x = Vec::new();
|
||||
x.put_i16(value);
|
||||
x.put_i16(value).unwrap();
|
||||
assert_eq!(value, SliceSource::from(&x).get_i16()?);
|
||||
Ok(())
|
||||
}
|
||||
@ -254,7 +255,7 @@ mod tests {
|
||||
fn test_varsigned() -> Result<()> {
|
||||
fn test(value: i64) -> Result<()> {
|
||||
let mut x = Vec::new();
|
||||
x.put_signed(value);
|
||||
x.put_signed(value).unwrap();
|
||||
assert_eq!(value, SliceSource::from(&x).get_signed()?);
|
||||
Ok(())
|
||||
}
|
||||
|
49
src/ser.rs
49
src/ser.rs
@ -1,7 +1,9 @@
|
||||
use serde::{ser, Serialize};
|
||||
|
||||
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> {
|
||||
// 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)
|
||||
}
|
||||
|
||||
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> {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
type Error = BipackError;
|
||||
type SerializeSeq = Self;
|
||||
type SerializeTuple = Self;
|
||||
type SerializeTupleStruct = Self;
|
||||
@ -28,17 +36,18 @@ impl<'a, S: BipackSink> ser::Serializer for &'a mut Serializer<S> {
|
||||
type SerializeStructVariant = Self;
|
||||
|
||||
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(())
|
||||
}
|
||||
|
||||
fn serialize_i8(self, v: i8) -> Result<()> {
|
||||
self.output.put_i8(v);
|
||||
self.output.put_i8(v)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
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<()> {
|
||||
@ -46,12 +55,12 @@ impl<'a, S: BipackSink> ser::Serializer for &'a mut Serializer<S> {
|
||||
}
|
||||
|
||||
fn serialize_i64(self, v: i64) -> Result<()> {
|
||||
self.output.put_signed(v);
|
||||
self.output.put_signed(v)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn serialize_u8(self, v: u8) -> Result<()> {
|
||||
self.output.put_u8(v);
|
||||
self.output.put_u8(v)?;
|
||||
Ok(())
|
||||
}
|
||||
fn serialize_u16(self, v: u16) -> Result<()> {
|
||||
@ -63,7 +72,7 @@ impl<'a, S: BipackSink> ser::Serializer for &'a mut Serializer<S> {
|
||||
Ok(())
|
||||
}
|
||||
fn serialize_u64(self, v: u64) -> Result<()> {
|
||||
self.output.put_unsigned(v);
|
||||
self.output.put_unsigned(v)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -82,12 +91,12 @@ impl<'a, S: BipackSink> ser::Serializer for &'a mut Serializer<S> {
|
||||
}
|
||||
|
||||
fn serialize_str(self, v: &str) -> Result<()> {
|
||||
self.output.put_str(v);
|
||||
self.output.put_str(v)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn serialize_bytes(self, v: &[u8]) -> Result<()> {
|
||||
self.output.put_var_bytes(v);
|
||||
self.output.put_var_bytes(v)?;
|
||||
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...
|
||||
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)
|
||||
}
|
||||
|
||||
@ -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> {
|
||||
self.output.put_unsigned(_len.unwrap_or(0));
|
||||
self.output.put_unsigned(_len.unwrap_or(0))?;
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
@ -197,7 +206,7 @@ impl<'a, S: BipackSink> ser::Serializer for &'a mut Serializer<S> {
|
||||
variant: &'static str,
|
||||
_len: usize,
|
||||
) -> Result<Self::SerializeStructVariant> {
|
||||
self.output.put_unsigned(_variant_index);
|
||||
self.output.put_unsigned(_variant_index)?;
|
||||
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.
|
||||
type Ok = ();
|
||||
// Must match the `Error` type of the serializer.
|
||||
type Error = Error;
|
||||
type Error = BipackError;
|
||||
|
||||
// Serialize a single element of the sequence.
|
||||
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> {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
type Error = BipackError;
|
||||
|
||||
fn serialize_element<T>(&mut self, value: &T) -> Result<()>
|
||||
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> {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
type Error = BipackError;
|
||||
|
||||
fn serialize_field<T>(&mut self, value: &T) -> Result<()>
|
||||
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> {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
type Error = BipackError;
|
||||
|
||||
fn serialize_field<T>(&mut self, value: &T) -> Result<()>
|
||||
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> {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
type Error = BipackError;
|
||||
|
||||
// The Serde data model allows map keys to be any serializable type. JSON
|
||||
// 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.
|
||||
impl<'a, S: BipackSink> ser::SerializeStruct for &'a mut Serializer<S> {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
type Error = BipackError;
|
||||
|
||||
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
|
||||
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> {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
type Error = BipackError;
|
||||
|
||||
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
|
||||
where
|
||||
|
Loading…
Reference in New Issue
Block a user