[英]Why do I get the error “trait bounds were not satisfied” when using ReadBytesExt to read an integer from a slice of bytes?
The following Rust code doesn't compile. 以下Rust代码无法编译。
extern create byteorder;
use byetorder::{LittleEndian, ReadBytesExt};
fn main() {
let buf: [u8; 12] = [
0x00, 0x42, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x30,
];
let id = &buf[0..1].read_u16::<LittleEndian>(); }
The message from the compiler: 来自编译器的消息:
error[E0599]: no method named `read_u16` found for type `[u8]` in the current scope
--> src/main.rs:18:25
|
18 | let id = &buf[0..1].read_u16::<LittleEndian>();
| ^^^^^^^^
|
= note: the method `read_u16` exists but the following trait bounds were not satisfied:
`[u8] : byteorder::ReadBytesExt`
There are very similar questions on Stack Overflow, which I have reviewed, but mine is subtly different from those because I'm trying to read a u16
from a slice. 我已经检查了关于Stack Overflow的非常相似的问题,但是我的问题与这些问题有细微的不同,因为我试图从切片中读取u16
。 In practice, I'm not sure why my example is substantively different, I'm sure I'm missing something obvious. 在实践中,我不确定为什么我的示例有本质上的不同,我确定我缺少明显的东西。
Specifically, it's not clear to me how what I've got is meaningfully different from what's in the accepted answer here: 具体来说,我不清楚我所获得的内容与此处接受的答案有何显着不同:
How can I convert a buffer of a slice of bytes (&[u8]) to an integer? 如何将一个字节片(&[u8])的缓冲区转换为整数?
Don't I also have &[u8]
when I say &buf[0..1]
? 我说&buf[0..1]
时也没有&[u8]
&buf[0..1]
吗?
Your code calls read_u16()
on an array rather than a slice . 您的代码在数组而不是slice上调用read_u16()
。 You probably intend to call the method on &buf[0..1]
, but due to operator precedence you actually call it on buf[0..1]
. 您可能打算在&buf[0..1]
上调用该方法,但是由于运算符的优先级,您实际上在buf[0..1]
上调用了该方法。 This can be fixed by simply adding a pair of parentheses: 只需添加一对括号即可解决此问题:
let id = (&buf[0..1]).read_u16::<LittleEndian>();
Your original code is interpreted as &(buf[0..1].read_u16::<LittleEndian>())
, which is why the compiler complains that the ReadBytesExt
trait is not implemented for [u8]
. 您的原始代码被解释为&(buf[0..1].read_u16::<LittleEndian>())
,这就是为什么编译器会抱怨[u8]
未实现ReadBytesExt
特性。
Because the trait bounds were not satisfied. 因为特质界限不被满足。
read_u16
needs the receiver to be a mutable reference : read_u16
需要接收者是可变的引用 :
pub trait ReadBytesExt: Read {
fn read_u16<T: ByteOrder>(&mut self) -> Result<u16> { ... }
}
This is because it will call Read
, which requires the same: 这是因为它将调用Read
,它要求相同:
impl<'a> Read for &'a [u8] {
fn read(&mut self, buf: &mut [u8]) -> Result<usize>
}
Note that Read
is implemented for &[u8]
, but takes &mut self
. 请注意, Read
是为&[u8]
,但采用&mut self
。 That means that self
is a &mut &[u8]
, a mutable reference to a slice. 这意味着self
是&mut &[u8]
,这是对切片的可变引用。
Introducing parenthesis, as suggested by Sven Marnach , creates a slice ( &[u8]
) as a temporary value and temporary values can be treated as implicitly mutable. 如Sven Marnach所建议,引入括号会创建一个切片( &[u8]
)作为临时值,并且可以将临时值视为隐式可变的。
In the linked question, the starting variable is a slice that is mutable. 在链接的问题中,起始变量是可变的切片。 Calling read_u16
can take a mutable reference to buf
: 调用read_u16
可以对buf
进行可变引用:
let mut buf: &[u8] = &[0x00, 0x42];
In your case, you have an array. 就您而言,您有一个数组。 While this dereferences to a slice, Rust's automatic (de)referencing rules will never add two levels of reference. 虽然这取消了对切片的引用,但Rust的自动(取消)引用规则将永远不会添加两个级别的引用。 Method lookup fails. 方法查找失败。
See also: 也可以看看:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.