What I need is a function that does this:
Given a Mutable reference of byte slice, interpret the bytes into a struct, return a mutable reference to the struct instead. In the struct, there's a tail field, I want to have the tail field to point to the rest of the byte slice.
cannot borrow `*obj` as mutable more than once at a time
I want to ask for help to get deeper understanding of what part of my code doesn't reflect my memory and lifetime model at the top. Or my model at the top is wrong?
This isn't possible. tail will be a pointer to the data, not the data itself, so if the &A internally just points to the same place as the original data, then you'd be overlapping the (ptr, len) of tail with the rest of the data.
&'a mut Foo<'a> is an antipattern. This means that the Foo has been borrowed mutably for as long as its contents live... Meaning that the reference to Foo must live as long as the reference it contains, however the Foo itself must outlive the reference it contains.
This is unsound, but for more reasons than the ones mentioned above: head.as_mut_ptr() might not necessarily be aligned correctly to what A expects (in this case, align(A) = max(align(u64), align(usize))).
It's not entirely clear what you aim to do with this, but perhaps you meant to declare A as follows:
Someone else is better at explaining this than me, but I think it's interesting that the code compiles if you change obj.set_tail(tail) with simply obj.tail = tail.
(Not that you'd want the code to compile, it's trying to protect you from the UB you've got there)
This is due to the &'a mut A<'a> antipattern. A is already borrowing itself mutably for the duration of its own lifetime according to that type signature, so you can't mutably reborrow it in the creation of &mut self to pass into A::set_tail.
Purpose:
I am building a 'serializer' to convert Rust Struct from and to byte sequence. Also bytes should have the type information (which are the id_bytes) encoded. The code above is when I want the receiver to convert the received bytes into a struct. But because the received bytes can be one of multiple types, so I am using an Enum to do this.
The reason for tail is that I want to support vector-like field in the struct. So I want to have one or multiple attached array at the end.
Example: Suppose the received could receive type A message or type B message.
enum E<'a> {
A(&'a mut A),
B(&'a mut B),
}
...
let buf = [0u8; 1024]; // I will use a struct wrapper to ensure alignment
// Received got bytes via a system call
match E::parse_bytes(buf) {
E::A(a) => handler_a(a),
E::B(b) => handler_b(b),
}
As for the overlapping issue and alignment issue, I will make sure the receive buffer is 64 aligned. And I will use size_of to avoid the overlap. Also I am using macros to generate this function so it should avoid a lot of manual errors.
About the anti pattern, I am curious if you have any fix after hearing my build purpose. Thanks!
I am building this against my own toy embedded OS on raspberry pi written in C. So I am using no_std without heap allocation.
Unless it's for learning purposes (in which case study miri and it's purpose), I would strongly advice you to use a ready-made and battle-tested library like bytemuck - Rust before wrangling with unsafe code yourself.