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())?;