Initial commit
This commit is contained in:
commit
b3b41faf33
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
/target
|
||||
/Cargo.lock
|
14
Cargo.toml
Normal file
14
Cargo.toml
Normal 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
64
src/bipack_sink.rs
Normal 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
77
src/bipack_source.rs
Normal 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
55
src/lib.rs
Normal 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));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user