diff --git a/Cargo.toml b/Cargo.toml index 43c2b4e..ad23f6b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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." diff --git a/README.md b/README.md index 7f3e2b2..4e8c5c0 100644 --- a/README.md +++ b/README.md @@ -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:) diff --git a/src/bipack.rs b/src/bipack.rs index 9f48d5c..512e94f 100644 --- a/src/bipack.rs +++ b/src/bipack.rs @@ -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 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) } } diff --git a/src/bipack_sink.rs b/src/bipack_sink.rs index 1fc08a9..c91611c 100644 --- a/src/bipack_sink.rs +++ b/src/bipack_sink.rs @@ -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(self: &mut Self, number: T) { + fn put_unsigned(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 { - fn put_u8(self: &mut Self, data: u8) { + fn put_u8(self: &mut Self, data: u8) -> Result<()> { self.push(data); + Ok(()) } } + + + diff --git a/src/bipack_source.rs b/src/bipack_source.rs index 22383e5..f946599 100644 --- a/src/bipack_source.rs +++ b/src/bipack_source.rs @@ -20,10 +20,19 @@ use crate::bipack_source::BipackError::NoDataError; pub type Result = std::result::Result; /// 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 {} diff --git a/src/buffer_sink.rs b/src/buffer_sink.rs new file mode 100644 index 0000000..95113a2 --- /dev/null +++ b/src/buffer_sink.rs @@ -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(()) + } + } +} \ No newline at end of file diff --git a/src/de.rs b/src/de.rs index 631cfce..5861962 100644 --- a/src/de.rs +++ b/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 { // 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 { } impl<'de, 'a, T: BipackSource> de::Deserializer<'de> for &'a mut Deserializer { - type Error = Error; + type Error = BipackError; fn deserialize_any(self, visitor: V) -> std::result::Result where V: Visitor<'de> { - Err(Error::NotPossible) + Err(BipackError::NotPossible) } fn deserialize_bool(self, visitor: V) -> std::result::Result where V: Visitor<'de> { @@ -60,17 +60,17 @@ impl<'de, 'a, T: BipackSource> de::Deserializer<'de> for &'a mut Deserializer(self, visitor: V) -> std::result::Result where V: Visitor<'de> { - Err(Error::NotImplemented) + Err(BipackError::NotImplemented) } fn deserialize_f64(self, visitor: V) -> std::result::Result where V: Visitor<'de> { - Err(Error::NotImplemented) + Err(BipackError::NotImplemented) } fn deserialize_char(self, visitor: V) -> std::result::Result 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(self, visitor: V) -> std::result::Result where V: Visitor<'de> { - Err(Error::NotPossible) + Err(BipackError::NotPossible) } fn deserialize_ignored_any(self, visitor: V) -> std::result::Result 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 serde::de::EnumAccess<'de> for &'a mut Deserializer { - type Error = Error; + type Error = BipackError; type Variant = Self; #[inline] fn variant_seed>(self, seed: V) -> Result<(V::Value, Self)> { let varint: u32 = self.input.get_unsigned()? as u32; - let v = DeserializeSeed::deserialize::>( + let v = DeserializeSeed::deserialize::>( 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 { - 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(&mut self, seed: S) -> Result> 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(&mut self, seed: K) -> std::result::Result, 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] diff --git a/src/error.rs b/src/error.rs index ca8d4db..49e020b 100644 --- a/src/error.rs +++ b/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 = std::result::Result; +pub type Result = std::result::Result; -#[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(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(msg: T) -> Self { - Error::Message(msg.to_string()) - } -} - -impl From 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()) } } diff --git a/src/lib.rs b/src/lib.rs index 6457c38..72981f0 100644 --- a/src/lib.rs +++ b/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 = 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 = 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::::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(()) } diff --git a/src/ser.rs b/src/ser.rs index 82c58d9..b7d8483 100644 --- a/src/ser.rs +++ b/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 { // This string starts empty and JSON is appended as values are serialized. @@ -16,9 +18,15 @@ pub fn to_bytes(value: &T) -> Result> 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 { 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 { 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 { } 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 { 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 { } 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 { /// We expect it to use with vairable-length arrays... fn serialize_seq(self, _len: Option) -> Result { - 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 { } fn serialize_map(self, _len: Option) -> Result { - 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 { variant: &'static str, _len: usize, ) -> Result { - 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 { // 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(&mut self, value: &T) -> Result<()> @@ -224,7 +233,7 @@ impl<'a, S: BipackSink> ser::SerializeSeq for &'a mut Serializer { impl<'a, S: BipackSink> ser::SerializeTuple for &'a mut Serializer { type Ok = (); - type Error = Error; + type Error = BipackError; fn serialize_element(&mut self, value: &T) -> Result<()> where @@ -240,7 +249,7 @@ impl<'a, S: BipackSink> ser::SerializeTuple for &'a mut Serializer { impl<'a, S: BipackSink> ser::SerializeTupleStruct for &'a mut Serializer { type Ok = (); - type Error = Error; + type Error = BipackError; fn serialize_field(&mut self, value: &T) -> Result<()> where @@ -256,7 +265,7 @@ impl<'a, S: BipackSink> ser::SerializeTupleStruct for &'a mut Serializer { impl<'a, S: BipackSink> ser::SerializeTupleVariant for &'a mut Serializer { type Ok = (); - type Error = Error; + type Error = BipackError; fn serialize_field(&mut self, value: &T) -> Result<()> where @@ -272,7 +281,7 @@ impl<'a, S: BipackSink> ser::SerializeTupleVariant for &'a mut Serializer { impl<'a, S: BipackSink> ser::SerializeMap for &'a mut Serializer { 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 { // constant strings. impl<'a, S: BipackSink> ser::SerializeStruct for &'a mut Serializer { type Ok = (); - type Error = Error; + type Error = BipackError; fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<()> where @@ -324,7 +333,7 @@ impl<'a, S: BipackSink> ser::SerializeStruct for &'a mut Serializer { impl<'a, S: BipackSink> ser::SerializeStructVariant for &'a mut Serializer { type Ok = (); - type Error = Error; + type Error = BipackError; fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<()> where