&[u8] cannot be indexed by RangeFull?

北城以北 提交于 2021-02-11 14:20:00

问题


I am trying to create a struct which can contain anything that is sliceable to [u8].

use std::ops::{Index, RangeFull};

struct Wrapper<DataT>
where
    DataT: ?Sized + Index<RangeFull, Output = [u8]>, 
{
    data: DataT,
}

impl<DataT> Wrapper<DataT>
where
    DataT: ?Sized + Index<RangeFull, Output = [u8]>, 
{
    
    fn subwrapper(&self) -> Wrapper<Vec<u8>> {
        let mut buffer = Vec::<u8>::new();
        buffer.extend_from_slice(&self.data[..]);
        Wrapper {
            data: buffer,
        }
    }
}

fn main() {
    let data : [u8; 3] = [1, 2, 3];
    let w = Wrapper {data: &data[..]};
    let sub = w.subwrapper();
}

I get the error

error[E0277]: the type `&[u8]` cannot be indexed by `std::ops::RangeFull`
  --> src/main.rs:24:13
   |
3  | / struct Wrapper<DataT>
4  | | where
5  | |     DataT: ?Sized + Index<RangeFull, Output = [u8]>, {
6  | |         data: DataT,
7  | |     }
   | |_____- required by `Wrapper`
...
24 |       let w = Wrapper {data: &data[..]};
   |               ^^^^^^^ `&[u8]` cannot be indexed by `std::ops::RangeFull`
   |
   = help: the trait `std::ops::Index<std::ops::RangeFull>` is not implemented for `&[u8]`

I followed Array cannot be indexed by RangeFull?, but it didn't seem to solve the issue. Is this because &[u8] is a slice? When I try using the SliceIndex trait it seems to break for the Vec. Is there a way to say either trait is acceptable?


回答1:


The problem here is that while a slice [u8] implements Index<RangeFull>, a reference to a slice &[u8] does not. And it is the reference that you're trying to store in Wrapper so DataT is inferred to be &[u8], thus the trait bound DataT: Index<FullRange> is not satisfied.

If your goal is to cover "anything that's sliceable to [u8]", you should likely use other traits, though. A trait like AsRef<[u8]> might be better here, as it indicates "a reference to this type can be converted into a reference of a slice [u8]", which might be a more suitable definition of "sliceable to [u8]". (Other traits like Deref<Target = [u8]> might also be suitable alterantives here.)

Using AsRef, your code would become:

struct Wrapper<DataT>
where
    DataT: AsRef<[u8]>, // <-- new trait bound
{
    data: DataT,
}

impl<DataT> Wrapper<DataT>
where
    DataT: AsRef<[u8]>, // <-- new trait bound
{
    fn subwrapper(&self) -> Wrapper<Vec<u8>> {
        let buffer = self.data.as_ref() // <-- use `.as_ref()` to get `&[u8]`
            .to_vec();                  // <-- more efficient way to get `Vec<u8>`
                                        //       from `&[u8]`
        Wrapper { data: buffer }
    }
}

fn main() {
    let data: [u8; 3] = [1, 2, 3];
    let w = Wrapper { data: &data }; // <-- no need to use `[..]` here, as
                                     //       `[u8; N]` implements `AsRef<[u8]>`
    let sub = w.subwrapper();
}

Playground example



来源:https://stackoverflow.com/questions/64088594/u8-cannot-be-indexed-by-rangefull

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!