Rust字节序操作byteorder
字节序操作——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::().unwrap()); assert_eq!(768, rdr.read_u16::().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::(&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" "); 自己实现序列化和反序列化struct#[derive(Debug)] pub struct Person { features:HashMap>, 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> { 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::(self.feature_size); buf.write_u64::(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::()?; self.channel_bit = rdr.read_u64::()?; for _ in 0..length{ let key = rdr.read_u8()?; let mut feature = vec![0.0;self.feature_size as usize]; rdr.read_f32_into::(&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()) }