字节序操作——byteorder
字节数组操作是一个高频的操作,rust生态中有bytes和byteorder两个第三方库来处理。两个库的操作方法基本类似,我们选择byteorder 来做介绍。
在byteorder中定义了BigEndian和LittleEndian两个枚举类,这两个枚举类分别实现了byteorder::ByteOrder个trait。
byteorder::ByteOrder提供发了丰富的接口来实现常用类型转成字节数组。
pub trait ByteOrder: Clone + Copy + Debug + Default + Eq + Hash + Ord + PartialEq + PartialOrd + Sealed {
fn read_u16(buf: &[u8]) -> u16;
fn read_u32(buf: &[u8]) -> u32;
fn read_u64(buf: &[u8]) -> u64;
fn read_u128(buf: &[u8]) -> u128;
fn read_uint(buf: &[u8], nbytes: usize) -> u64;
fn read_uint128(buf: &[u8], nbytes: usize) -> u128;
fn write_u16(buf: &mut [u8], n: u16);
fn write_u32(buf: &mut [u8], n: u32);
fn write_u64(buf: &mut [u8], n: u64);
fn write_u128(buf: &mut [u8], n: u128);
fn write_uint(buf: &mut [u8], n: u64, nbytes: usize);
fn write_uint128(buf: &mut [u8], n: u128, nbytes: usize);
fn read_u16_into(src: &[u8], dst: &mut [u16]);
fn read_u32_into(src: &[u8], dst: &mut [u32]);
fn read_u64_into(src: &[u8], dst: &mut [u64]);
fn read_u128_into(src: &[u8], dst: &mut [u128]);
fn write_u16_into(src: &[u16], dst: &mut [u8]);
fn write_u32_into(src: &[u32], dst: &mut [u8]);
fn write_u64_into(src: &[u64], dst: &mut [u8]);
fn write_u128_into(src: &[u128], dst: &mut [u8]);
fn from_slice_u16(numbers: &mut [u16]);
fn from_slice_u32(numbers: &mut [u32]);
fn from_slice_u64(numbers: &mut [u64]);
fn from_slice_u128(numbers: &mut [u128]);
fn from_slice_f32(numbers: &mut [f32]);
fn from_slice_f64(numbers: &mut [f64]);
fn read_u24(buf: &[u8]) -> u32 { ... }
fn read_u48(buf: &[u8]) -> u64 { ... }
fn write_u24(buf: &mut [u8], n: u32) { ... }
fn write_u48(buf: &mut [u8], n: u64) { ... }
fn read_i16(buf: &[u8]) -> i16 { ... }
fn read_i24(buf: &[u8]) -> i32 { ... }
fn read_i32(buf: &[u8]) -> i32 { ... }
fn read_i48(buf: &[u8]) -> i64 { ... }
fn read_i64(buf: &[u8]) -> i64 { ... }
fn read_i128(buf: &[u8]) -> i128 { ... }
fn read_int(buf: &[u8], nbytes: usize) -> i64 { ... }
fn read_int128(buf: &[u8], nbytes: usize) -> i128 { ... }
fn read_f32(buf: &[u8]) -> f32 { ... }
fn read_f64(buf: &[u8]) -> f64 { ... }
fn write_i16(buf: &mut [u8], n: i16) { ... }
fn write_i24(buf: &mut [u8], n: i32) { ... }
fn write_i32(buf: &mut [u8], n: i32) { ... }
fn write_i48(buf: &mut [u8], n: i64) { ... }
fn write_i64(buf: &mut [u8], n: i64) { ... }
fn write_i128(buf: &mut [u8], n: i128) { ... }
fn write_int(buf: &mut [u8], n: i64, nbytes: usize) { ... }
fn write_int128(buf: &mut [u8], n: i128, nbytes: usize) { ... }
fn write_f32(buf: &mut [u8], n: f32) { ... }
fn write_f64(buf: &mut [u8], n: f64) { ... }
fn read_i16_into(src: &[u8], dst: &mut [i16]) { ... }
fn read_i32_into(src: &[u8], dst: &mut [i32]) { ... }
fn read_i64_into(src: &[u8], dst: &mut [i64]) { ... }
fn read_i128_into(src: &[u8], dst: &mut [i128]) { ... }
fn read_f32_into(src: &[u8], dst: &mut [f32]) { ... }
fn read_f32_into_unchecked(src: &[u8], dst: &mut [f32]) { ... }
fn read_f64_into(src: &[u8], dst: &mut [f64]) { ... }
fn read_f64_into_unchecked(src: &[u8], dst: &mut [f64]) { ... }
fn write_i8_into(src: &[i8], dst: &mut [u8]) { ... }
fn write_i16_into(src: &[i16], dst: &mut [u8]) { ... }
fn write_i32_into(src: &[i32], dst: &mut [u8]) { ... }
fn write_i64_into(src: &[i64], dst: &mut [u8]) { ... }
fn write_i128_into(src: &[i128], dst: &mut [u8]) { ... }
fn write_f32_into(src: &[f32], dst: &mut [u8]) { ... }
fn write_f64_into(src: &[f64], dst: &mut [u8]) { ... }
fn from_slice_i16(src: &mut [i16]) { ... }
fn from_slice_i32(src: &mut [i32]) { ... }
fn from_slice_i64(src: &mut [i64]) { ... }
fn from_slice_i128(src: &mut [i128]) { ... }
}
use byteorder::{ByteOrder, LittleEndian};
let mut buf = [0; 4];
LittleEndian::write_u32(&mut buf, 1_000_000);
assert_eq!(1_000_000, LittleEndian::read_u32(&buf));
use byteorder::{ByteOrder, BigEndian};
let mut buf = [0; 2];
BigEndian::write_i16(&mut buf, -5_000);
assert_eq!(-5_000, BigEndian::read_i16(&buf));
use byteorder::{ByteOrder, BigEndian};
let mut numbers = [5, 65000];
BigEndian::from_slice_i64(&mut numbers);
assert_eq!(numbers, [5i64.to_be(), 65000i64.to_be()]);
选择byteorder的另一个重要原因是,byteorder定义了另外两个ReadBytesExt和WriteBytesExttrait,
ReadBytesExt继承了std::io::Readtrait,然后所有实现std::io::Read的类,将免费获取ReadBytesExt。 WriteBytesExt继承了std::io::Writetrait,然后所有实现std::io::Write的类,将免费获取WriteBytesExt。
use std::io::Cursor;
use byteorder::{BigEndian, ReadBytesExt};
let mut rdr = Cursor::new(vec![2, 5, 3, 0]); //Cursor<[u8]>实现了std::io::Read 所有免费实现了ReadBytesExt
assert_eq!(517, rdr.read_u16::<BigEndian>().unwrap());
assert_eq!(768, rdr.read_u16::<BigEndian>().unwrap());
use std::f32;
use std::io::Cursor;
use byteorder::{BigEndian, ReadBytesExt};
let mut rdr = Cursor::new(vec![
0x40, 0x49, 0x0f, 0xdb,
0x3f, 0x80, 0x00, 0x00,
]);
let mut dst = [0.0; 2];
rdr.read_f32_into::<BigEndian>(&mut dst).unwrap(); //读取 float32 数组
assert_eq!([f32::consts::PI, 1.0], dst);
use byteorder::WriteBytesExt;
let mut wtr = Vec::new(); //Vec<[u8]>实现了std::io::Write 免费实现了WriteBytesExt
wtr.write_u8(2).unwrap();
wtr.write_u8(5).unwrap();
assert_eq!(wtr, b"\x02\x05");
自己实现序列化和反序列化struct
#[derive(Debug)]
pub struct Person {
features:HashMap<i8,Vec<f32>>,
feature_size :u16,
channel_bit:u64,
}
impl Person {
fn size(&self)->usize {
let length = self.features.len();
if length < 1 {
return 7
}
1 + 2 + 8 + (1+self.feature_size as usize *4)*length
}
pub fn marshal(&self) ->Option<Vec<u8>> {
if self.size() < 11 {
return None
}
let mut buf = Vec::with_capacity(self.size());
buf.write_u8(self.features.len() as u8);
buf.write_u16::<LittleEndian>(self.feature_size);
buf.write_u64::<LittleEndian>(self.channel_bit);
for (k,v) in & self.features {
buf.write_u8(*k as u8);
unsafe {
let b = std::slice::from_raw_parts(v.as_ptr() as *const u8, v.len() * 4);
buf.write_all(b); //write_all 方法来着 std::io::Write trait
}
}
Some(buf)
}
pub fn unmarshal(&mut self,b :&[u8])->std::result::Result<(),std::io::Error> {
if b.len() < 11 {
return Err(std::io::Error::new(std::io::ErrorKind::Other,"to short"))
}
let mut rdr = Cursor::new(b);
let length = rdr.read_u8()?;
self.feature_size = rdr.read_u16::<LittleEndian>()?;
self.channel_bit = rdr.read_u64::<LittleEndian>()?;
for _ in 0..length{
let key = rdr.read_u8()?;
let mut feature = vec![0.0;self.feature_size as usize];
rdr.read_f32_into::<LittleEndian>(&mut feature)?;
self.features.insert(key as i8,feature);
}
Ok(())
}
}
fn main() {
let mut features = HashMap::new();
features.insert(1i8, Vec::from([2.9;2048]));
features.insert(2i8, Vec::from([2.9;2048]));
let person = Person {
features,
feature_size:2048,
channel_bit:0
};
let bytes = person.marshal().unwrap();
let mut personb = Person {
features:HashMap::new(),
feature_size:2048,
channel_bit:0
};
personb.unmarshal(& bytes).unwrap();
println!("{:?}",person);
println!("{:?}",personb);
assert_eq!(person.features.get(&1).unwrap(), personb.features.get(&1).unwrap())
}