From 33a27d0124e947ff1858880ce142dd0f6b55b172 Mon Sep 17 00:00:00 2001 From: sergeych Date: Wed, 11 Oct 2023 22:18:46 +0100 Subject: [PATCH] 0.2.0: improving nameing, started serialization support and convenience macros. --- Cargo.toml | 2 +- README.md | 5 ++- src/bipack.rs | 79 ++++++++++++++++++++++++++++++++++++++++++++ src/bipack_source.rs | 6 ++-- src/lib.rs | 22 ++++++++++-- 5 files changed, 107 insertions(+), 7 deletions(-) create mode 100644 src/bipack.rs diff --git a/Cargo.toml b/Cargo.toml index 253bbe1..184c14a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "bipack_ru" -version = "0.1.0" +version = "0.2.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 0fa4f57..a2441d9 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,8 @@ # bipack_ru +> This is yet an alpha. We are still experimenting with the interface. 0.1.* could +> be backward incompatible! + Bipack format implementation, minimalistic by purpose. At the moment it does not include `serde` module as it is yet unclear how much @@ -9,4 +12,4 @@ The autodoc documentation is good enough already, so we do not repeat it here no # License -For compyance with other modules this work is provided under APACHE 2.0 license a copy of which is included in the file `LICENSE`. \ No newline at end of file +For compliance with other modules this work is provided under APACHE 2.0 license a copy of which is included in the file `LICENSE`. \ No newline at end of file diff --git a/src/bipack.rs b/src/bipack.rs new file mode 100644 index 0000000..9f48d5c --- /dev/null +++ b/src/bipack.rs @@ -0,0 +1,79 @@ +use crate::bipack_sink::{BipackSink, IntoU64}; +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); +} + +/// The trait need by [bipack()] macro and in the serializer to come, packs some +/// type into a generic sink. +pub trait BiUnpackable where Self: Sized { + + fn bi_unpack(source: &mut dyn BipackSource) -> Result; +} + +/// Pack all arguments according to their type, using variable-length +/// encoding for integers and default encoding for binaries and string, +/// and return `Vec` with packed result. +/// +/// It you need more fine-grained packing, use [BipackSink] directly. +#[macro_export] +macro_rules! bipack { + ( $( $e: expr),* ) => {{ + let mut result = Vec::new(); + $( + $e.bi_pack(&mut result); + )* + result + }}; +} + +impl BiPackable for T { + fn bi_pack(self: &Self, sink: &mut impl BipackSink) { + sink.put_unsigned(self.into_u64()) + } +} + +impl BiPackable for &str { + fn bi_pack(self: &Self, sink: &mut impl BipackSink) { + sink.put_str(self) + } +} + +macro_rules! declare_unpack_u { + ($($type:ident),*) => { + $(impl BiUnpackable for $type { + fn bi_unpack(source: &mut dyn BipackSource) -> Result<$type> { + Ok(source.get_unsigned()? as $type) + } + })* + }; +} + +declare_unpack_u!(u16, u32, u64); + +// impl BiUnpackable for String { +// fn bi_unpack(source: &mut impl BipackSource) -> Result { +// source.get_str() +// } +// } + +// impl dyn BiUnpackable { +// +// } + +impl BiUnpackable for u8 { + fn bi_unpack(source: &mut dyn BipackSource) -> Result { + source.get_u8() + } +} + +impl BiUnpackable for String { + fn bi_unpack(source: &mut dyn BipackSource) -> Result { + source.get_str() + } +} + + diff --git a/src/bipack_source.rs b/src/bipack_source.rs index 1001bf5..6a23960 100644 --- a/src/bipack_source.rs +++ b/src/bipack_source.rs @@ -120,7 +120,7 @@ pub trait BipackSource { /// [crate::bipack_sink::BipackSink::put_str]. The size is encoded the same way as does /// [crate::bipack_sink::BipackSink::put_unsigned] and can be manually read by /// [BipackSource::get_unsigned]. - fn var_bytes(self: &mut Self) -> Result> { + fn get_var_bytes(self: &mut Self) -> Result> { let size = self.get_unsigned()? as usize; self.get_fixed_bytes(size) } @@ -128,9 +128,9 @@ pub trait BipackSource { /// REad a variable length string from a source packed with /// [crate::bipack_sink::BipackSink::put_str]. It is a variable sized array fo utf8 encoded /// characters. - fn str(self: &mut Self) -> Result { + fn get_str(self: &mut Self) -> Result { String::from_utf8( - self.var_bytes()? + self.get_var_bytes()? ).or_else(|e| Err(BipackError::BadEncoding(e))) } } diff --git a/src/lib.rs b/src/lib.rs index d95c51b..e7d1e1b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -117,11 +117,15 @@ pub mod bipack_source; pub mod bipack_sink; pub mod tools; +mod bipack; #[cfg(test)] mod tests { use base64::Engine; - use crate::bipack_sink::{BipackSink}; + + use crate::bipack; + use crate::bipack::{BiPackable, BiUnpackable}; + use crate::bipack_sink::BipackSink; use crate::bipack_source::{BipackSource, Result, SliceSource}; use crate::tools::to_dump; @@ -182,7 +186,7 @@ mod tests { data.put_str("Hello, rupack!"); println!("size ${}\n{}",data.len(), to_dump(&data)); let mut src = SliceSource::from(&data); - assert_eq!("Hello, rupack!", src.str().unwrap()); + assert_eq!("Hello, rupack!", src.get_str().unwrap()); } #[test] @@ -201,4 +205,18 @@ mod tests { } } } + + #[test] + fn test_packer() -> Result<()>{ + let a = 177u32; + let b = "hello!"; + let sink = bipack!(a, b); + println!("{}", to_dump(&sink)); + let mut source = SliceSource::from(&sink); + let a1 = u32::bi_unpack(&mut source)?; + let s1 = String::bi_unpack(&mut source)?; + assert_eq!(177u32, a1); + assert_eq!("hello!", s1); + Ok(()) + } } \ No newline at end of file