我正在使用Vec<u8>
缓冲区将二进制文件读入Rust程序.流中的两个字节代表一个big-endian u16
.
到目前为止,我已经想出如何转换为原语的唯一方法是先将u16
两个元素转换为String
s,看起来很糟糕.
码:
let vector: Vec<u8> = [1, 16].to_vec();
let vector0: String = format!("{:02x}", vector[0]);
let vector1: String = format!("{:02x}", vector[1]);
let mut vector_combined = String::new();
vector_combined = vector_combined + &vector0.clone();
vector_combined = vector_combined + &vector1.clone();
let number: u16 = u16::from_str_radix(&vector_combined.to_string(), 16).unwrap();
println!("vector[0]: 0x{:02x}", vector[0]);
println!("vector[1]: 0x{:02x}", vector[1]);
println!("number: 0x{:04x}", number);
Run Code Online (Sandbox Code Playgroud)
输出:
vector[0]: 0x01
vector[1]: 0x10
number: 0x0110
Run Code Online (Sandbox Code Playgroud)
She*_*ter 16
如果你实际上有两个不同的u8
s,传统的解决方案涉及按位操作,特别是移位和按位OR.这需要零堆分配并且非常有效:
let number = ((vector[0] as u16) << 8) | vector[1] as u16;
Run Code Online (Sandbox Code Playgroud)
并有图解说明:
A0 B0
+--------+ +--------+
|XXXXXXXX| |YYYYYYYY|
+-------++ +-------++
| |
A1 = A0 as u16 | B1 = B0 as u16 |
+---------------v+ +---------------v+
|00000000XXXXXXXX| |00000000YYYYYYYY|
+---------------++ +---------------++
| |
A2 = A1 << 8 | |
+---------------v+ |
|XXXXXXXX00000000| |
+---------------++ |
| +--+ |
+-------------->OR<--+
+-++
|
V = A2 | B1 |
+----------+----v+
|XXXXXXXXYYYYYYYY|
+----------------+
Run Code Online (Sandbox Code Playgroud)
但是,你真的在狭隘地看待你的问题.你没有两个u8
,你有一个&[u8]
.
在这种情况下,使用byteorder crate:
extern crate byteorder;
use byteorder::{ByteOrder, LittleEndian};
fn main() {
let data = [1, 16];
let v = LittleEndian::read_u16(&data);
println!("{}", v);
}
Run Code Online (Sandbox Code Playgroud)
当您想要通过缓冲区处理读取时,这显示了它的强大功能:
extern crate byteorder;
use byteorder::{BigEndian, LittleEndian, ReadBytesExt};
fn main() {
let data = [1, 16, 1, 2];
let mut current = &data[..];
let v1 = current.read_u16::<LittleEndian>();
let v2 = current.read_u16::<BigEndian>();
println!("{:?}, {:?}", v1, v2); // Ok(4097), Ok(258)
}
Run Code Online (Sandbox Code Playgroud)
如您所见,您需要意识到输入数据的字节顺序.
也可以看看:
您原始帖子的免费代码审核:
没有必要在to_vec
这里使用,vec!
而是使用.
没有必要指定绝大多数类型.
let vector = [1u8, 16].to_vec();
let vector0 = format!("{:02x}", vector[0]);
let vector1 = format!("{:02x}", vector[1]);
let mut vector_combined = String::new();
vector_combined = vector_combined + &vector0.clone();
vector_combined = vector_combined + &vector1.clone();
let number = u16::from_str_radix(&vector_combined.to_string(), 16).unwrap();
Run Code Online (Sandbox Code Playgroud)
String
到另一个... String
在from_str_radix
.let vector0 = format!("{:02x}", vector[0]);
let vector1 = format!("{:02x}", vector[1]);
let mut vector_combined = String::new();
vector_combined = vector_combined + &vector0;
vector_combined = vector_combined + &vector1;
let number = u16::from_str_radix(&vector_combined, 16).unwrap();
Run Code Online (Sandbox Code Playgroud)
String
来追加,只需使用vector0
let vector0 = format!("{:02x}", vector[0]);
let vector1 = format!("{:02x}", vector[1]);
let vector_combined = vector0 + &vector1;
let number = u16::from_str_radix(&vector_combined, 16).unwrap();
Run Code Online (Sandbox Code Playgroud)
let vector_combined = format!("{:02x}{:02x}", vector[0], vector[1]);
let number = u16::from_str_radix(&vector_combined, 16).unwrap();
Run Code Online (Sandbox Code Playgroud)
当然,这仍然不是正确的解决方案,但它更好.
您可以将第一个元素相乘以将其移动到更高的字节,然后添加第二个元素。它只需要额外的铸造:
let a: u8 = 1;
let b: u8 = 2;
let c: u16 = (a as u16 * 256) + b as u16;
println!("c: {}", c); // c: 258
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1906 次 |
最近记录: |