1 个不稳定版本
0.1.0 | 2023年10月2日 |
---|
#1411 in 编码
62KB
770 行
Leb128fmt
Leb128fmt是一个用于解码和编码LEB128格式数字的库。LEB128是一种可变长度的整数压缩格式。
该库不分配内存,可以用于no_std
和no_std::no_alloc
环境。
提供各种函数,用于按函数名称中的位数编码和解码有符号和无符号整数。还提供了通用的函数,用于读取和写入编码值的切片。
名称中包含单词fixed
的编码函数将使用给定位数可能的最大字节数写入值。例如,使用encode_fixed_u32
将始终使用5个字节来写入值。虽然始终使用最大字节数会消除压缩的优势,但在某些情况下,具有固定编码大小可能是有益的。
最后,还提供了宏,您可以使用它们为像有符号33位值这样的不寻常变体构建自己的编码和解码函数。
安装
cargo add leb128fmt
示例
使用数组的函数
// Encode an unsigned 32 bit number:
let (output, written_len) = leb128fmt::encode_u32(43110).unwrap();
// The number of bytes written in the output array
assert_eq!(written_len, 3);
assert_eq!(&output[..written_len], &[0xE6, 0xD0, 0x02]);
// The entire output array. Note you should only use &output[..written_len] to copy
// into your output buffer
assert_eq!(output, [0xE6, 0xD0, 0x02, 0x00, 0x00]);
// Decode an unsigned 32 bit number:
let input = [0xE6, 0xD0, 0x02, 0x00, 0x00];
let (result, read_len) = leb128fmt::decode_u32(input).unwrap();
assert_eq!(result, 43110);
assert_eq!(read_len, 3);
辅助函数
如果您正在从输入缓冲区读取,可以使用is_last
和max_len
来确定要复制到数组中的字节数。
let buffer = vec![0xFE, 0xFE, 0xE6, 0xD0, 0x02, 0xFE, 0xFE, 0xFE];
let pos = 2;
let end = buffer.iter().skip(pos).copied().position(leb128fmt::is_last).map(|p| pos + p);
if let Some(end) = end {
if end <= pos + leb128fmt::max_len::<32>() {
let mut input = [0u8; leb128fmt::max_len::<32>()];
input[..=end - pos].copy_from_slice(&buffer[pos..=end]);
let (result, read_len) = leb128fmt::decode_u32(input).unwrap();
assert_eq!(result, 43110);
assert_eq!(read_len, 3);
} else {
// invalid LEB128 encoding
panic!();
}
} else {
if buffer.len() - pos < leb128fmt::max_len::<32>() {
// Need more bytes in the buffer
panic!();
} else {
// invalid LEB128 encoding
panic!();
}
}
使用切片的函数
let mut buffer = vec![0xFE; 10];
let mut pos = 1;
// Encode an unsigned 64 bit number with a mutable slice:
let result = leb128fmt::encode_uint_slice::<u64, 64>(43110u64, &mut buffer, &mut pos);
// The number of bytes written in the output array
assert_eq!(result, Some(3));
assert_eq!(pos, 4);
assert_eq!(buffer, [0xFE, 0xE6, 0xD0, 0x02, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE]);
// Decode an unsigned 64 bit number with a slice:
pos = 1;
let result = leb128fmt::decode_uint_slice::<u64, 64>(&buffer, &mut pos);
assert_eq!(result, Ok(43110));
assert_eq!(pos, 4);
使用固定大小编码的函数
编码一个值可能有几种不同的方法。例如,0
可以编码为32位无符号整数
let mut pos = 0;
assert_eq!(leb128fmt::decode_uint_slice::<u32, 32>(&[0x00], &mut pos), Ok(0));
pos = 0;
assert_eq!(leb128fmt::decode_uint_slice::<u32, 32>(&[0x80, 0x00], &mut pos), Ok(0));
pos = 0;
assert_eq!(leb128fmt::decode_uint_slice::<u32, 32>(&[0x80, 0x80, 0x00], &mut pos), Ok(0));
pos = 0;
assert_eq!(leb128fmt::decode_uint_slice::<u32, 32>(&[0x80, 0x80, 0x80, 0x00], &mut pos), Ok(0));
pos = 0;
assert_eq!(leb128fmt::decode_uint_slice::<u32, 32>(&[0x80, 0x80, 0x80, 0x80, 0x00], &mut pos), Ok(0));
提供了函数,用于使用给定位大小的可能的最大字节数编码值。使用最大字节数会消除压缩的优势,但在某些情况下可能很有用。
例如,如果一个二进制格式需要在数据大小未知之前存储某些数据的大小或偏移量,那么先写入一个固定大小的占位符值(0)可能是有益的。然后,一旦知道了真实值,就可以在不移动其他字节的情况下覆盖掉这个占位符。真实值也将使用固定的最大字节数写入。
// Encode an unsigned 32 bit number with all 5 bytes:
let output = leb128fmt::encode_fixed_u32(43110).unwrap();
assert_eq!(output, [0xE6, 0xD0, 0x82, 0x80, 0x00]);
// Decode an unsigned 32 bit number:
let input = output;
let (result, read_len) = leb128fmt::decode_u32(input).unwrap();
assert_eq!(result, 43110);
// Note that all 5 bytes are read
assert_eq!(read_len, 5);
许可证
根据您的选择,在Apache许可证,版本2.0或MIT许可证下授权。
贡献
除非您明确声明,否则任何有意提交并由您包括在作品中的贡献,根据Apache-2.0许可证定义,将以上双授权,没有任何额外的条款或条件。