From ebb74fdd61c1656cad7543e4e62b373293014814 Mon Sep 17 00:00:00 2001 From: sergeych Date: Sun, 15 Oct 2023 18:11:12 +0100 Subject: [PATCH] started serde support: serializer & errors --- Cargo.toml | 3 +- src/error.rs | 35 +++++ src/lib.rs | 2 + src/ser.rs | 384 +++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 423 insertions(+), 1 deletion(-) create mode 100644 src/error.rs create mode 100644 src/ser.rs diff --git a/Cargo.toml b/Cargo.toml index 849f937..35d8452 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "bipack_ru" -version = "0.2.2" +version = "0.3.0" edition = "2021" license = "Apache-2.0" description = "binary size-effective format used in Divan smart contracts, wasm bindings, network protocols, etc." @@ -10,6 +10,7 @@ readme = "README.md" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +serde = { version = "1.0.189", features = ["derive"] } [dev-dependencies] base64 = "0.21.4" diff --git a/src/error.rs b/src/error.rs new file mode 100644 index 0000000..bc40077 --- /dev/null +++ b/src/error.rs @@ -0,0 +1,35 @@ +use std; +use std::fmt::{self, Display}; +use serde::{de, ser}; + +pub type Result = std::result::Result; + +#[derive(Debug)] +pub enum Error { + Message(String), + Eof, + BadEncoding, +} + +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(msg: T) -> Self { + Error::Message(msg.to_string()) + } +} + +impl de::Error for Error { + fn custom(msg: T) -> Self { + Error::Message(msg.to_string()) + } +} diff --git a/src/lib.rs b/src/lib.rs index f01264b..b039f83 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -118,6 +118,8 @@ pub mod bipack_source; pub mod bipack_sink; pub mod tools; pub mod bipack; +mod error; +mod ser; #[cfg(test)] mod tests { diff --git a/src/ser.rs b/src/ser.rs new file mode 100644 index 0000000..c386262 --- /dev/null +++ b/src/ser.rs @@ -0,0 +1,384 @@ +use serde::{ser, Serialize}; +use crate::bipack_sink::{BipackSink, IntoU64}; + +use crate::error::{Error, Result}; +use crate::tools::to_dump; + +pub struct Serializer { + // This string starts empty and JSON is appended as values are serialized. + output: Vec, +} + +pub fn to_bytes(value: &T) -> Result> +where T: Serialize, +{ + let mut serializer = Serializer { output: Vec::new() }; + value.serialize(& mut serializer)?; + Ok(serializer.output) +} + +impl<'a> ser::Serializer for &'a mut Serializer { + 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<()> { + self.output.put_u8(if v { 1 } else { 0 } ); + Ok(()) + } + + fn serialize_i8(self, v: i8) -> Result<()> { + self.output.put_i8(v); + Ok(()) + } + + fn serialize_i16(self, v: i16) -> Result<()> { + self.serialize_i64(i64::from(v)) + } + + fn serialize_i32(self, v: i32) -> Result<()> { + self.serialize_i64(i64::from(v)) + } + + fn serialize_i64(self, v: i64) -> Result<()> { + self.output.put_signed(v); + Ok(()) + } + + fn serialize_u8(self, v: u8) -> Result<()> { + self.output.put_u8(v); + Ok(()) + } + fn serialize_u16(self, v: u16) -> Result<()> { + self.output.put_u64(v.into()); + Ok(()) + } + fn serialize_u32(self, v: u32) -> Result<()> { + self.output.put_u64(v.into_u64()); + Ok(()) + } + fn serialize_u64(self, v: u64) -> Result<()> { + self.output.put_unsigned(v); + Ok(()) + } + + fn serialize_f32(self, v: f32) -> Result<()> { + Err(ser::Error::custom("not implemented")) + } + + fn serialize_f64(self, v: f64) -> Result<()> { + Err(ser::Error::custom("not implemented")) + } + + /// Serialize a char as a single-character string, because this is a UTF8-encoded + /// char, e.g. variable length: + fn serialize_char(self, v: char) -> Result<()> { + self.serialize_str(&v.to_string()) + } + + fn serialize_str(self, v: &str) -> Result<()> { + self.output.put_str(v); + Ok(()) + } + + fn serialize_bytes(self, v: &[u8]) -> Result<()> { + self.output.put_var_bytes(v); + Ok(()) + } + + fn serialize_none(self) -> Result<()> { + self.serialize_u8(0); + Ok(()) + } + + fn serialize_some(self, value: &T) -> Result<()> + where + T: ?Sized + Serialize, + { + self.serialize_u8(1); + value.serialize(self) + } + + fn serialize_unit(self) -> Result<()> { + self.output.put_u8(0); + Ok(()) + } + + fn serialize_unit_struct(self, _name: &'static str) -> Result<()> { + self.serialize_unit() + } + + fn serialize_unit_variant( + self, + _name: &'static str, + _variant_index: u32, + variant: &'static str, + ) -> Result<()> { + self.serialize_u32(_variant_index) + } + + fn serialize_newtype_struct( + self, + _name: &'static str, + value: &T, + ) -> Result<()> + where + T: ?Sized + Serialize, + { + value.serialize(self) + } + + fn serialize_newtype_variant( + self, + _name: &'static str, + _variant_index: u32, + variant: &'static str, + value: &T, + ) -> Result<()> + where + T: ?Sized + Serialize, + { + self.serialize_str(_name); + self.serialize_u32(_variant_index) + } + + fn serialize_seq(self, _len: Option) -> Result { + self.output.put_unsigned(_len.unwrap_or(0)); + Ok(self) + } + + fn serialize_tuple(self, len: usize) -> Result { + self.serialize_seq(Some(len)) + } + + fn serialize_tuple_struct( + self, + _name: &'static str, + len: usize, + ) -> Result { + self.serialize_seq(Some(len)) + } + + fn serialize_tuple_variant( + self, + _name: &'static str, + _variant_index: u32, + variant: &'static str, + _len: usize, + ) -> Result { + variant.serialize(&mut *self)?; + Ok(self) + } + + fn serialize_map(self, _len: Option) -> Result { + self.output.put_unsigned(_len.unwrap_or(0)); + Ok(self) + } + + fn serialize_struct( + self, + _name: &'static str, + len: usize, + ) -> Result { + self.serialize_map(Some(len)) + } +fn serialize_struct_variant( + self, + _name: &'static str, + _variant_index: u32, + variant: &'static str, + _len: usize, + ) -> Result { + variant.serialize(&mut *self)?; + Ok(self) + } +} + +impl<'a> 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; + + // Serialize a single element of the sequence. + fn serialize_element(&mut self, value: &T) -> Result<()> + where + T: ?Sized + Serialize, + { + value.serialize(&mut **self) + } + + // Close the sequence. + fn end(self) -> Result<()> { + Ok(()) + } +} + +impl<'a> ser::SerializeTuple for &'a mut Serializer { + type Ok = (); + type Error = Error; + + fn serialize_element(&mut self, value: &T) -> Result<()> + where + T: ?Sized + Serialize, + { + value.serialize(&mut **self) + } + + fn end(self) -> Result<()> { + Ok(()) + } +} + +impl<'a> ser::SerializeTupleStruct for &'a mut Serializer { + type Ok = (); + type Error = Error; + + fn serialize_field(&mut self, value: &T) -> Result<()> + where + T: ?Sized + Serialize, + { + value.serialize(&mut **self) + } + + fn end(self) -> Result<()> { + Ok(()) + } +} + +impl<'a> ser::SerializeTupleVariant for &'a mut Serializer { + type Ok = (); + type Error = Error; + + fn serialize_field(&mut self, value: &T) -> Result<()> + where + T: ?Sized + Serialize, + { + value.serialize(&mut **self) + } + + fn end(self) -> Result<()> { + Ok(()) + } +} + +impl<'a> ser::SerializeMap for &'a mut Serializer { + type Ok = (); + type Error = Error; + + // The Serde data model allows map keys to be any serializable type. JSON + // only allows string keys so the implementation below will produce invalid + // JSON if the key serializes as something other than a string. + // + // A real JSON serializer would need to validate that map keys are strings. + // This can be done by using a different Serializer to serialize the key + // (instead of `&mut **self`) and having that other serializer only + // implement `serialize_str` and return an error on any other data type. + fn serialize_key(&mut self, key: &T) -> Result<()> + where + T: ?Sized + Serialize, + { + key.serialize(&mut **self) + } + + // It doesn't make a difference whether the colon is printed at the end of + // `serialize_key` or at the beginning of `serialize_value`. In this case + // the code is a bit simpler having it here. + fn serialize_value(&mut self, value: &T) -> Result<()> + where + T: ?Sized + Serialize, + { + value.serialize(&mut **self) + } + + fn end(self) -> Result<()> { + Ok(()) + } +} + +// Structs are like maps in which the keys are constrained to be compile-time +// constant strings. +impl<'a> ser::SerializeStruct for &'a mut Serializer { + type Ok = (); + type Error = Error; + + fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<()> + where + T: ?Sized + Serialize, + { + key.serialize(&mut **self)?; + value.serialize(&mut **self) + } + + fn end(self) -> Result<()> { + Ok(()) + } +} + +impl<'a> ser::SerializeStructVariant for &'a mut Serializer { + type Ok = (); + type Error = Error; + + fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<()> + where + T: ?Sized + Serialize, + { + key.serialize(&mut **self)?; + value.serialize(&mut **self) + } + + fn end(self) -> Result<()> { + Ok(()) + } +} + +#[test] +fn test_struct() { + #[derive(Serialize)] + struct Test { + int: u32, + seq: Vec<&'static str>, + } + + let test = Test { + int: 1, + seq: vec!["a", "b"], + }; + // let expected = r#"{"int":1,"seq":["a","b"]}"#; + // assert_eq!(to_string(&test).unwrap(), expected); + let x = to_bytes(&test).unwrap(); + println!("!:\n{}", to_dump(&x)); +} + +// #[test] +// fn test_enum() { +// #[derive(Serialize)] +// enum E { +// Unit, +// Newtype(u32), +// Tuple(u32, u32), +// Struct { a: u32 }, +// } +// +// let u = E::Unit; +// let expected = r#""Unit""#; +// assert_eq!(to_string(&u).unwrap(), expected); +// +// let n = E::Newtype(1); +// let expected = r#"{"Newtype":1}"#; +// assert_eq!(to_string(&n).unwrap(), expected); +// +// let t = E::Tuple(1, 2); +// let expected = r#"{"Tuple":[1,2]}"#; +// assert_eq!(to_string(&t).unwrap(), expected); +// +// let s = E::Struct { a: 1 }; +// let expected = r#"{"Struct":{"a":1}}"#; +// assert_eq!(to_string(&s).unwrap(), expected); +// } \ No newline at end of file