So, I guess, you have multiple questions:
-
What I don't understand is why is it important to add the [..]?
-
I'm also having trouble understanding how adding &mut &mut to account.data.borrow_mut()[..] creates a slice of u8. How is this being converted to u8?
Those questions are kinda intertwined, as you can see inthe anwser to question 1.
Question 1
When we look at the documentation about certain cases of indexing, we see, that
account.data.borrow_mut()[..]
is sugar for
*(account.data.borrow_mut().index_mut(..))
Why is that a valid expression?
..
is a shorthand for RangeFull
.
RangeFull
has an implementation for SliceIndex<[u8]>
.
With this blanket implementation we get a IndexMut<RangeFull> for [u8]
, which provides
fn index_mut(&mut [u8], index: RangeFull) -> &mut [u8]
Now the deref coercion and or the auto dereferencing mentioned in other answers and comments kicks in.
account.data.borrow_mut().index_mut(..)
And RefMut<&mut [u8]>
implements DerefMut
which has Deref<Target = &mut [u8]>
as a super trait.
And &mut [u8]
implements DerefMut
with Deref<Target = [u8]>
as super trait.
As mentioned in the reference, the compiler will now take the receiver expression and dereference it repeatedly, so it gets a list of candidate types. It also adds for each type resulting from a dereference the reference type and the mutable reference type to the list of candidate types. From this candidate types it selects one providing the method to call.
RefMut<&mut [u8]>
using account.data.borrow_mut()
&RefMut<&mut [u8]>
&mut RefMut<&mut [u8]>
&mut [u8]
using *account.data.borrow_mut().deref_mut()
&&mut [u8]
&mut &mut [u8]
[u8]
using *(*account.data.borrow_mut().deref_mut())
&[u8]
&mut [u8]
(In 7. we are dereferencing a pointer type &mut [u8]
so no DerefMut
Trait is used.)
The first (and only) type in this list providing an index_mut()
method is &mut [u8]
, via the IndexMut<FullRange>
implementation for [u8]
, so &mut [u8]
is selected as receiver type. The return type of index_mut()
is &mut [u8]
as well.
So now, we hopefully understand, the type of
*(account.data.borrow_mut().index_mut(..))
is [u8]
.
Hence:
Question 2
&mut &mut account.data.borrow_mut()[..]
has type &mut &mut [u8]
.
Addendum
&mut &mut [u8]
is needed as &mut [u8]
has a Write
implementation.
And serialize
pub fn serialize<W: Write>(&self, writer: &mut W) -> Result<()>
needs an argument of type &mut W
, where W
implements Write
.
The reference to a value of type W
implementing Write
needs to mutable, as we want to keep track of the actual writing position in the value of type W
. In the case of &mut [u8]
we simply alter the reference to start at a different position in the underlying slice, so we need a mutable reference to the mutable reference, as we want to alter the mutable reference itself and not only the underlying data.
Addendum 2
Just use
mail_account.serialize(&mut *account.data.borrow_mut())?;