我想在编译时检查实现中使用的切片是否From具有特定大小。
(游乐场)
#[derive(Debug)]
struct Pixel {
r: u8,
g: u8,
b: u8,
}
impl From<&[u8]> for Pixel {
fn from(arr: &[u8]) -> Pixel {
Pixel {
r: arr[0],
g: arr[1],
b: arr[2],
}
}
}
fn main() {
println!("Hello, world!");
let arr: [u8; 9] = [1, 2, 3, 4, 5, 6, 7, 8, 9];
let pixels: Vec<Pixel> = arr.chunks_exact(3).map(Pixel::from).collect();
println!("{:.?}", pixels);
}
Run Code Online (Sandbox Code Playgroud)
这并不像我想要的那么具体。我想尽可能清楚地检查arr传递给is 3 个元素(在编译时)。Pixel::from<&[u8]>()
想到了assert!(arr.len()==3),但这在运行时检查。
所以我想也许我可以通过( Playground )进行转换:
impl From<[u8; 3]> for Pixel {
fn from(arr: [u8; 3]) -> Pixel {
Pixel {
r: arr[0],
g: arr[1],
b: arr[2],
}
}
}
Run Code Online (Sandbox Code Playgroud)
但这会导致:
error[E0277]: the trait bound `Pixel: From<&[u8]>` is not satisfied
--> src/main.rs:22:30
|
22 | let pixels: Vec<Pixel> = arr.chunks_exact(3).map(Pixel::from).collect();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `From<&[u8]>` is not implemented for `Pixel`
|
= help: the following implementations were found:
<Pixel as From<[u8; 3]>>
error[E0277]: the trait bound `Pixel: From<&[u8]>` is not satisfied
--> src/main.rs:22:54
|
22 | let pixels: Vec<Pixel> = arr.chunks_exact(3).map(Pixel::from).collect();
| ^^^^^^^^^^^ the trait `From<&[u8]>` is not implemented for `Pixel`
|
= help: the following implementations were found:
<Pixel as From<[u8; 3]>>
= note: required by `from`
error[E0277]: the trait bound `Pixel: From<&[u8]>` is not satisfied
--> src/main.rs:22:30
|
22 | let pixels: Vec<Pixel> = arr.chunks_exact(3).map(Pixel::from).collect();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `From<&[u8]>` is not implemented for `Pixel`
|
= help: the following implementations were found:
<Pixel as From<[u8; 3]>>
Run Code Online (Sandbox Code Playgroud)
同样我尝试过From<&[u8; 3]>但结果相同。
有没有办法实现特定大小的切片?
这不是如何将切片转换为数组引用?由于这个问题具体涉及在编译时检查而不影响运行时性能,因此它不会强制转换&[u8]为&[u8; 3]简单地在编译时检查&[u8]是否有 3 个元素(可以通过 using 来完成&[u8; 3])。上述问题的所有答案都会产生运行时影响,除了我相信这个答案中的这种方法(像这样应用),但这根本不检查切片是否具有适当的长度。这个问题并不是专门关于能够使用,Pixel::from<[u8;3]>而是关于在编译时一般检查长度,这些答案都没有提供或与之相关。
您不能在编译时执行此操作,因为切片长度在编译时未知。这是切片存在的一个重要原因。当编译时长度已知时,那就是一个数组。
也可以看看:
相反,我会写出易错和绝对正确的转换:
use std::array::TryFromSliceError;
use std::convert::TryFrom;
#[derive(Debug)]
struct Pixel {
r: u8,
g: u8,
b: u8,
}
impl TryFrom<&[u8]> for Pixel {
type Error = TryFromSliceError;
fn try_from(arr: &[u8]) -> Result<Self, Self::Error> {
<&[u8; 3]>::try_from(arr).map(Self::from)
}
}
impl From<&[u8; 3]> for Pixel {
fn from(arr: &[u8; 3]) -> Self {
Self::from(*arr)
}
}
impl From<[u8; 3]> for Pixel {
fn from(arr: [u8; 3]) -> Self {
Pixel {
r: arr[0],
g: arr[1],
b: arr[2],
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后,您可以从数组进行转换,允许出现编译时错误,或者当您有一个切片并且在编译时不知道长度时,您可以尝试转换并出现运行时错误。
将来,您可以使用诸如slice::array_chunks将切片转换为数组迭代器之类的方法。然而,仍然存在切片长度不正确(太长或太短)的情况,您必须以某种方式处理。
| 归档时间: |
|
| 查看次数: |
690 次 |
| 最近记录: |