Reputation: 669
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
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()
}
Caution: Whenever you convert to bytes, confirm whether you want little endian/big endian and all the bytes follow the same endianess.
Upvotes: 1