From trait - How to implement it from a slice

Viewed 168

Looking at the documentation for the trait std::convert::From, it says:

Used to do value-to-value conversions while consuming the input value.

To me, and looking at the fn from(T) -> Self signature, it sounds like the function takes ownership of the argument.

How can e.g. String implement the From<&str> trait? It cannot take ownership from the shared reference.

I want to implement a "viewer" structure; something that doesn't take ownership: Say a &[u8] represents my binary data; the first byte is my "data id".

struct DataView {
    id: u8,
    data: &[u8],
}

Then I would like to be able to do something like:

impl From<&[u8]> for DataView {
    fn from(buffer: &[u8]) -> DataView {
        DataView {
            id: buffer[0],
            data: &buffer[1..],
        }
    }
}

Is something like this possible? Does such a structure make sense if I am only interested in "viewing"?

1 Answers

Yes you can do that without taking ownership. But first, every stuct that contains a reference needs a lifetime to assert, that it doesn't exist passt the scope of the data it references:

#[derive(Debug)]
struct DataView<'a> {
    id: u8,
    data: &'a [u8],
}

Now we can implement the From trait the following manner:

impl<'a> From<&'a [u8]> for DataView<'a> {
    fn from(arg: &'a [u8]) -> Self {
        let id = arg[0];
        let data = &arg[1..];
        Self { id, data }
    }
}

Note that we are explicitly asserting that the referenced argmument has the same lifetime as the DataView object. Now we can do:

fn main() {
    let arg: &[u8] = &[1, 2, 3, 4, 6];

    let view = DataView::from(arg);
    println!("{:?}", view);
}
Related