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