0.2.0: improving nameing, started serialization support and convenience macros.

This commit is contained in:
Sergey Chernov 2023-10-11 22:18:46 +01:00
parent c1aaede6f7
commit 33a27d0124
5 changed files with 107 additions and 7 deletions

View File

@ -1,6 +1,6 @@
[package] [package]
name = "bipack_ru" name = "bipack_ru"
version = "0.1.0" version = "0.2.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

@ -1,5 +1,8 @@
# bipack_ru # 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. Bipack format implementation, minimalistic by purpose.
At the moment it does not include `serde` module as it is yet unclear how much 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 # 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`. For compliance with other modules this work is provided under APACHE 2.0 license a copy of which is included in the file `LICENSE`.

79
src/bipack.rs Normal file
View File

@ -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<Self>;
}
/// Pack all arguments according to their type, using variable-length
/// encoding for integers and default encoding for binaries and string,
/// and return `Vec<u8>` 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<T: IntoU64 + Copy> 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<String> BiUnpackable<String> for String {
// fn bi_unpack(source: &mut impl BipackSource) -> Result<Self> {
// source.get_str()
// }
// }
// impl dyn BiUnpackable<u32> {
//
// }
impl BiUnpackable for u8 {
fn bi_unpack(source: &mut dyn BipackSource) -> Result<u8> {
source.get_u8()
}
}
impl BiUnpackable for String {
fn bi_unpack(source: &mut dyn BipackSource) -> Result<String> {
source.get_str()
}
}

View File

@ -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_str]. The size is encoded the same way as does
/// [crate::bipack_sink::BipackSink::put_unsigned] and can be manually read by /// [crate::bipack_sink::BipackSink::put_unsigned] and can be manually read by
/// [BipackSource::get_unsigned]. /// [BipackSource::get_unsigned].
fn var_bytes(self: &mut Self) -> Result<Vec<u8>> { fn get_var_bytes(self: &mut Self) -> Result<Vec<u8>> {
let size = self.get_unsigned()? as usize; let size = self.get_unsigned()? as usize;
self.get_fixed_bytes(size) self.get_fixed_bytes(size)
} }
@ -128,9 +128,9 @@ pub trait BipackSource {
/// REad a variable length string from a source packed with /// 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 /// [crate::bipack_sink::BipackSink::put_str]. It is a variable sized array fo utf8 encoded
/// characters. /// characters.
fn str(self: &mut Self) -> Result<String> { fn get_str(self: &mut Self) -> Result<String> {
String::from_utf8( String::from_utf8(
self.var_bytes()? self.get_var_bytes()?
).or_else(|e| Err(BipackError::BadEncoding(e))) ).or_else(|e| Err(BipackError::BadEncoding(e)))
} }
} }

View File

@ -117,11 +117,15 @@
pub mod bipack_source; pub mod bipack_source;
pub mod bipack_sink; pub mod bipack_sink;
pub mod tools; pub mod tools;
mod bipack;
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use base64::Engine; 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::bipack_source::{BipackSource, Result, SliceSource};
use crate::tools::to_dump; use crate::tools::to_dump;
@ -182,7 +186,7 @@ mod tests {
data.put_str("Hello, rupack!"); data.put_str("Hello, rupack!");
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.str().unwrap()); assert_eq!("Hello, rupack!", src.get_str().unwrap());
} }
#[test] #[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(())
}
} }