Link0
Link0

Reputation: 669

How to return chained iterators in rust

I have a simple struct that defines some kind of message to be sent over network.

struct Message {
    message_type: u32,
    user_id: u32,
    message: Vec<u8>,
}

And somewhere else I want to serialize it into a simple sequence of bytes. So I defined iterator for the bytes of the message like this:

impl Message {
    fn iter(&self) -> std::iter::Chain<std::iter::Chain<std::slice::Iter<'_, u8>, std::slice::Iter<'_, u8>>, std::slice::Iter<'_, u8>> {
        self.message_type
            .to_be_bytes()
            .iter()
            .chain(self.user_id.to_be_bytes().iter())
            .chain(self.message.iter())
    }

    fn data(&self) -> Vec<u8> {
        self.iter().cloned().collect()
    }
}

Yes, the type keeps growing with more chained iterators, which is kind of a shame

But I get 2 compiler errors when I try to run it

cannot return value referencing temporary value

returns a value referencing data owned by the current function. rustc(E0515)

Guess I'm not versed enough in the rust's ownership system

Upvotes: 0

Views: 1155

Answers (1)

apatniv
apatniv

Reputation: 1856

The problem why rust borrow checker is complaining is because to_be_bytes() functions return an array which is stored on stack. The code is attempting to create a iterator to a object that is allocated on stack and this iterator is outliving the object.

self.message_type.to_be_bytes()

For example:
This creates an array on stack and .iter() is only valid as long as this object exists.

There are couple of ways fix this. Make the iter and eventual conversion to bytes all in the same function.

fn data(&self) -> Vec<u8> {
    self.message_type
        .to_be_bytes()
        .iter()
        .chain(self.user_id.to_be_bytes().iter())
        .chain(self.message.iter()).map(|x| *x).collect()
}

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=129af6e7da3d1e3a9454fffbb124e170

Caution: Whenever you convert to bytes, confirm whether you want little endian/big endian and all the bytes follow the same endianess.

Upvotes: 1

Related Questions