0

I have a struct Message as follows:

struct Message<'a> {
    message_type: String,
    data: &'a [u8],
}

The socketcan library has the CANFrame::data method that returns a &[u8].

I would not like to copy this into a vector, as I'd like it to all remain in the Message object on the stack, but I want to move the data from one to another.

match socket.read_frame() {
    Ok(frame) => {
        let message = Message {
            message_type: format!("{}", frame.id()),
            data: frame.data().clone(),
        };

However, the result frame.data() does not live long enough as the frame's scope is (and should be) fairly short:

error[E0597]: `frame` does not live long enough
  --> src/main.rs:27:31
   |
27 |                         data: frame.data().clone(),
   |                               ^^^^^ borrowed value does not live long enough
...
39 |             }
   |             - borrowed value only lives until here
   |
   = note: borrowed value must be valid for the static lifetime...

I know that the slice is only going to be at most 8 elements, as that's the limitation of the CAN protocol. What I really want is a struct that holds a [u8] as well as a usize (or u8 would also be valid) and thus can be converted to a slice with the correct size.

I'm just trying to figure out the idiomatic way to move (in the English "move" sense, as I may not want to use move semantics here -- not sure) the data from the CANFrame to the Message.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
River Tam
  • 3,096
  • 4
  • 31
  • 51
  • *Why* are you worried about copying **8 bytes** of data? – Shepmaster Jul 17 '18 at 19:35
  • @Shepmaster 1. To be clear, I don't even know how to copy the 8 bytes of data 2. I'm trying to learn – River Tam Jul 17 '18 at 19:37
  • Or [How can I create a stack-allocated vector-like container?](https://stackoverflow.com/q/29239586/155423). – Shepmaster Jul 17 '18 at 19:43
  • I guess that answers it, but is there really nothing like that in the standard library already? Seems like a surprising oversight... I'd rather not have to include this very general code in my codebase. (edit: I see now it's a crate, but it still seems surprising to me it's not in the standard library) – River Tam Jul 17 '18 at 19:45
  • It looks like more common than arrayvec is Servo's [smallvec](https://github.com/servo/rust-smallvec). It seems I'm really not going to get it through the standard library, so I guess I'll go with that – River Tam Jul 17 '18 at 19:48
  • If you don't like crates, Rust is **not** going to be a language that you enjoy. Rust doesn't even have *random number generation* in the standard library! Everyone always seems to think that *their* specific needs are the needs of the vast majority of programmers and that it's absurd that the standard library doesn't have what *they* want. Instead Rust spent time and effort to make reusing code easy to do via Cargo and crates.io. Additionally, the standard library already has "very general code" that you are using and only the code you use ends up in the compiled output. – Shepmaster Jul 17 '18 at 19:49
  • @Shepmaster coming from JS, I tend to agree with you wholeheartedly, and Cargo/npm are some of my favorite parts of programming. The reason I would argue small vecs should be in the standard library are essentially just that Vectors, Arrays, and Slices are part of the standard library. Slices, as far as I'm concerned, are about as general as small vecs. I recognize that that's entirely opinion oriented, however. – River Tam Jul 17 '18 at 19:53
  • Note that you *had a choice* in the implementation in the first place because there isn't something in the standard library. Anyway, if you feel that strongly about it, propose to merge the crate into the standard library. Things can always be added, but they can **never** be removed due to backwards compatibility guarantees. – Shepmaster Jul 17 '18 at 19:55

0 Answers0