The issue is that in to_bytes we allocate a Vec<u8> on the heap and then want to return a pointer to the underlying byte-array. But the Vec goes out of scope when to_bytes ends. This cleans up the Vec and the pointer would be invalid if would be allowed to use it after the method returns.
Save but sad.
One option would be to build a wrapper around the User that contains an inner: User and an extra field bytes, that contains a Vec of u8.
Or, which is what I will show here, we could store the Vec directly on the User. While the field is excluded from serialization. Like so:
Then there can be an extra method that initializes the bytes:
impl User {
fn calc_bytes(&mut self) {
let serde_vec = serde_json::to_vec_pretty(self)
.expect("json serialization failed");
self.bytes = Some(serde_vec);
}
}
Which means, that as long as we initialize the bytes field before we call to_bytes the compiler allows us to return a pointer to the underlying bytes-array. Because the compiler knows that this pointer is valid as long as the Vec is valid, which in turn will not be dropped until the User instance goes our of scope.
The impl of ToBytes could look like this:
impl ToBytes for User {
fn to_bytes(&self) -> &[u8] {
match self.bytes {
Some(ref bytes) => bytes,
None => &[],
}
}
}
An idea about the
impl ToBytes for Userproblem:The issue is that in
to_byteswe allocate aVec<u8>on the heap and then want to return a pointer to the underlying byte-array. But theVecgoes out of scope whento_bytesends. This cleans up theVecand the pointer would be invalid if would be allowed to use it after the method returns.Save but sad.
One option would be to build a wrapper around the
Userthat contains aninner: Userand an extra fieldbytes, that contains aVecof u8.Or, which is what I will show here, we could store the
Vecdirectly on the User. While the field is excluded from serialization. Like so:Then there can be an extra method that initializes the bytes:
Which means, that as long as we initialize the bytes field before we call
to_bytesthe compiler allows us to return a pointer to the underlying bytes-array. Because the compiler knows that this pointer is valid as long as theVecis valid, which in turn will not be dropped until theUserinstance goes our of scope.The
implofToBytescould look like this:The full example can be seen at this playground-link:
play.rust-lang.org/?version=stable...