37

I am trying to learn Rust, and while doing so I wanted to try converting a struct object to a byte array, but I am running into issues doing so.

So I have this:

struct Node<'a> {
    id: u8,
    name: &'a str,
    data: &'a str,
}
impl<'a> Node<'a> {
    fn new() -> Node<'a> {
        return Node {
            id: 1,
            name: "superName",
            data: "some random desc2",
        };
    }

    fn to_buffer(&mut self) -> &'a [u8] {
        let mut size = mem::size_of::<Node>();
        size = size + self.name.len() * mem::size_of::<char>();
        size = size + self.data.len() * mem::size_of::<char>();
        println!("size {}", size);
        return &[self.id];
    }
}

but I am just getting the error "cannot return reference to temporary value" And I am not 100% sure that I understand the error message to begin with... is it because self.id is only scoped to this function and would be removed from the stack when it is returned?

And is there any way around this?

1
  • 1
    [self.id] creates an array on the stack, &[self.id] refers to this array, but since this array was created inside a function block, it's dropped right when you exit to_buffer function block. Compiler complains that you try to return a reference on the dropped array Commented Sep 12, 2020 at 14:48

2 Answers 2

27

Anything starting with & in Rust is a reference to a value, rather than a value itself. A &[u8] is a reference to a value which needs to exist elsewhere.

Because you create the value it's a reference to within the function, when the function returns, the value the reference points to no longer exists. (id still exists, but the slice containing id does not).

Instead, you can return an owned value, rather than a reference to one:

   fn to_buffer(&mut self) -> Vec<u8> {
        let mut size = mem::size_of::<Node>();
        size = size + self.name.len() * mem::size_of::<char>();
        size = size + self.data.len() * mem::size_of::<char>();
        println!("size {}", size);
        return vec![self.id];
    }

which the caller can then take a reference of if that's what they need.

Sign up to request clarification or add additional context in comments.

Comments

7

Since you originally wanted a reference to self.id but considered as a slice of only one element, I would suggest that instead of creating a new owned value (a vector, with heap allocation...) you just use std::slice::from_ref().

    fn to_buffer(&mut self) -> &[u8] {
        let mut size = mem::size_of::<Node>();
        size = size + self.name.len() * mem::size_of::<char>();
        size = size + self.data.len() * mem::size_of::<char>();
        println!("size {}", size);
        // return &[self.id];
        std::slice::from_ref(&self.id)
    }

1 Comment

"you originally wanted a reference to self.id" — OP's code returned a reference to a temporary array which held a copy of self.id. It's certainly possible (perhaps even likely) that they wanted a reference to it instead, but it's not absolutely certain. Anyway, this is a good answer for others to consider and it has my upvote!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.