Initial commit

This commit is contained in:
Sergey Chernov 2023-10-07 01:44:29 +01:00
commit b3b41faf33
5 changed files with 212 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/target
/Cargo.lock

14
Cargo.toml Normal file
View File

@ -0,0 +1,14 @@
[package]
name = "bipack_ru"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
anyhow = "1.0"
lazy_static = "1.4.0"
[dev-dependencies]
base64 = "0.21.4"
hex = "0.4.3"

64
src/bipack_sink.rs Normal file
View File

@ -0,0 +1,64 @@
use std::iter::Iterator;
pub trait DataSink {
fn put_u8(self: &mut Self, data: u8) -> &Self;
fn put_fixed_bytes(self: &mut Self, data: &[u8]) -> &Self {
for b in data { self.put_u8(*b); }
return self
}
fn put_u16(self: &mut Self, mut value: u16) -> &Self {
let mut result = [0u8; 2];
for i in (0..result.len()).rev() {
result[i] = value as u8;
println!(":: {} / {}", value, value as u8);
value = value >> 8;
}
self.put_fixed_bytes(&result)
}
fn put_u32(self: &mut Self, mut value: u32) -> &Self {
let mut result = [0u8; 4];
for i in (0..result.len()).rev() {
result[i] = value as u8;
println!(":: {} / {}", value, value as u8);
value = value >> 8;
}
self.put_fixed_bytes(&result)
}
fn put_u64(self: &mut Self, mut value: u64) -> &Self {
let mut result = [0u8; 8];
for i in (0..result.len()).rev() {
result[i] = value as u8;
println!(":: {} / {}", value, value as u8);
value = value >> 8;
}
self.put_fixed_bytes(&result)
}
}
const V0LIMIT: u64 = 1u64 << 6;
const V1LIMIT: u64 = 1u64 << 14;
const V2LIMIT: u64 = 1u64 << 22;
impl DataSink for Vec<u8> {
fn put_u8(self: &mut Self, data: u8) -> &Self {
self.push(data);
self
}
}
const HEX_DIGS: [char; 16] = [
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
];
pub fn to_hex(src: &[u8]) -> Box<String> {
let mut result = Vec::new();
for i in src {
result.push( HEX_DIGS[(i>>4) as usize]);
result.push( HEX_DIGS[(i&15) as usize]);
}
Box::new(String::from_iter(result))
}

77
src/bipack_source.rs Normal file
View File

@ -0,0 +1,77 @@
/// Data source compatible with mp_bintools serialization. It supports
/// fixed-size integers in rihgt order and varint ans smartint encodings
/// separately.
pub trait BipackSource {
fn u8(self: &mut Self) -> u8;
fn u16(self: &mut Self) -> u16 {
((self.u8() as u16) << 8) + (self.u8() as u16)
}
fn u32(self: &mut Self) -> u32 {
((self.u16() as u32) << 16) + (self.u16() as u32)
}
fn u64(self: &mut Self) -> u64 {
((self.u32() as u64) << 32) | (self.u32() as u64)
}
fn smart_u64(self: &mut Self) -> u64 {
let mut get = || -> u64 { self.u8() as u64 };
let first = get();
let mut ty = first & 3;
let mut result = first >> 2;
if ty == 0 { return result; }
ty -= 1;
result = result + (get() << 6);
if ty == 0 { return result; }
ty -= 1;
result = result + (get() << 14);
if ty == 0 { return result; }
result | (self.var_u64() << 22)
}
fn var_u64(self: &mut Self) -> u64 {
let mut result = 0u64;
let mut count = 0;
loop {
let x = self.u8() as u64;
result = result | ((x & 0x7F) << count);
if (x & 0x80) == 0 { return result; }
count += 7
}
}
fn smart_u16(self: &mut Self) -> u16 {
self.smart_u64() as u16
}
fn smart_u32(self: &mut Self) -> u32 { self.smart_u64() as u32 }
}
pub struct SliceSource<'a> {
data: &'a [u8],
position: usize,
}
impl<'a> SliceSource<'a> {
pub fn new(src: &'a [u8]) -> SliceSource {
SliceSource { data: src, position: 0 }
}
}
impl<'x> BipackSource for SliceSource<'x> {
fn u8(self: &mut Self) -> u8 {
let result = self.data[self.position];
self.position += 1;
result
}
}
pub fn bipack_source<'b>(v: &'b [u8]) -> SliceSource<'b> {
SliceSource::new(v)
}

55
src/lib.rs Normal file
View File

@ -0,0 +1,55 @@
#![allow(dead_code)]
#![allow(unused_variables)]
mod bipack_source;
mod bipack_sink;
pub fn add(left: usize, right: usize) -> usize {
left + right
}
#[cfg(test)]
mod tests {
use base64::Engine;
use crate::bipack_sink::{BipackSink};
use crate::bipack_source::{bipack_source, BipackSource, SliceSource};
#[test]
fn fixed_unpack() {
let mut src = Vec::new();
base64::engine::general_purpose::STANDARD_NO_PAD
.decode_vec("B/oAAAEB0AAAANjLgKAv", &mut src)
.expect("decoded vector");
println!(": {}", hex::encode(&src));
let mut ss = SliceSource::new(&src);
assert_eq!(7, ss.u8());
assert_eq!(64000, ss.u16());
assert_eq!(66000, ss.u32());
assert_eq!(931127140399, ss.u64());
}
#[test]
fn smartint_unpack() {
let mut src = Vec::new();
base64::engine::general_purpose::STANDARD_NO_PAD
.decode_vec("BwLoA0IHBL+AAq7GDQ", &mut src)
.expect("decoded vector");
let mut ss = bipack_source(&src);
assert_eq!(7, ss.u8());
assert_eq!(64000, ss.smart_u16());
assert_eq!(66000, ss.smart_u32());
assert_eq!(931127140399, ss.smart_u64());
}
#[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);
// println!("-- {:?}", data.iter().map(|x| format!("{:0x}", x)).collect::<Vec<_>>());
assert_eq!("07fa00000101d0000000d8cb80a02f", hex::encode(&data).as_str());
// println!("data = {}", to_hex(&data));
}
}