+variable-length signed support
This commit is contained in:
1 parent
588446cd42
commit
e0ac1b1094
5 files changed
+90
-15
No files matched your search
+21
-11
@@ -54,12 +54,12 @@ pub trait BipackSink {
|
||||
for b in data { self.put_u8(*b); }
|
||||
}
|
||||
|
||||
fn put_var_bytes(self: &mut Self,data: &[u8]) {
|
||||
fn put_var_bytes(self: &mut Self, data: &[u8]) {
|
||||
self.put_unsigned(data.len());
|
||||
self.put_fixed_bytes(data);
|
||||
}
|
||||
|
||||
fn put_str(self: &mut Self,str: &str) {
|
||||
fn put_str(self: &mut Self, str: &str) {
|
||||
self.put_var_bytes(str.as_bytes());
|
||||
}
|
||||
|
||||
@@ -118,20 +118,30 @@ pub trait BipackSink {
|
||||
};
|
||||
|
||||
if value < V0LIMIT {
|
||||
encode_seq(0, &[value]);
|
||||
}
|
||||
else if value < V1LIMIT {
|
||||
encode_seq( 1, &[value & 0x3F, value >> 6]);
|
||||
}
|
||||
else if value < V2LIMIT {
|
||||
encode_seq( 2, &[value & 0x3f, value >> 6, value >> 14]);
|
||||
}
|
||||
else {
|
||||
encode_seq(0, &[value]);
|
||||
} else if value < V1LIMIT {
|
||||
encode_seq(1, &[value & 0x3F, value >> 6]);
|
||||
} else if value < V2LIMIT {
|
||||
encode_seq(2, &[value & 0x3f, value >> 6, value >> 14]);
|
||||
} else {
|
||||
encode_seq(3, &[value & 0x3f, value >> 6, value >> 14]);
|
||||
self.put_var_unsigned(value >> 22);
|
||||
}
|
||||
}
|
||||
|
||||
/// Put variable-length encoded integer value. it is packed just like variable-length
|
||||
/// unsigned value except that LSB (bit 0) is used as negative number flag (when set,
|
||||
/// the encoded number is negative).
|
||||
///
|
||||
/// Note that because of this the range of supported integers is one bit smaller than
|
||||
/// i64, only 30 bits for value and one for a sign. This will probably be fixed later
|
||||
/// but please note that it is impractical to store really big numbers in variable-length
|
||||
/// format, consider using [put_i64] instead which has no such limitation.
|
||||
fn put_signed(self: &mut Self, val: i64) {
|
||||
let (neg, val) = if val < 0 { (1, -val) } else { (0, val) };
|
||||
self.put_unsigned( (neg as u64) | ((val as u64) << 1) );
|
||||
}
|
||||
|
||||
fn put_var_unsigned(self: &mut Self, value: u64) {
|
||||
let mut rest = value;
|
||||
loop {
|
||||
|
||||
@@ -97,6 +97,14 @@ pub trait BipackSource {
|
||||
Ok(result | (self.get_varint_unsigned()? << 22))
|
||||
}
|
||||
|
||||
/// Unpack variable-length signed value, packed with
|
||||
/// [crate::bipack_sink::BipackSink::put_signed], see it for the packing details.
|
||||
fn get_signed(self: &mut Self) -> Result<i64> {
|
||||
let value = self.get_unsigned()?;
|
||||
let result = (value >> 1) as i64;
|
||||
Ok(if value & 1 != 0 { -result } else { result } )
|
||||
}
|
||||
|
||||
/// read 8-bytes varint-packed unsigned value from the source. We dont' recommend
|
||||
/// using it directly; use [BipackSource::get_unsigned] instead.
|
||||
fn get_varint_unsigned(self: &mut Self) -> Result<u64> {
|
||||
|
||||
+27
@@ -245,6 +245,33 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_varsigned() -> Result<()> {
|
||||
fn test(value: i64) -> Result<()> {
|
||||
let mut x = Vec::new();
|
||||
x.put_signed(value);
|
||||
assert_eq!(value, SliceSource::from(&x).get_signed()?);
|
||||
Ok(())
|
||||
}
|
||||
fn test2(value: i64) -> Result<()> {
|
||||
test(value)?;
|
||||
test(-value)?;
|
||||
Ok(())
|
||||
}
|
||||
test(0)?;
|
||||
test2(1)?;
|
||||
test2(2)?;
|
||||
test2(64)?;
|
||||
test2(65)?;
|
||||
test2(127)?;
|
||||
test2(128)?;
|
||||
test2(255)?;
|
||||
test2(256)?;
|
||||
test2(2147483647)?;
|
||||
test2(2222147483647)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_packer() -> Result<()>{
|
||||
let a = 177u32;
|
||||
let b = "hello!";
|
||||
|
||||
Reference in new issue
Block a user