{{#include ../links.md}} # Handling Data In Rust, it is common to name things `as_*`, `to_*`, and `into_*`. These three methods perform three different, but related, functions, and it's important to choose the correct name when writing methods. These methods take data that are stored inside of the struct, and return them in some manner. For example, let's look at the `Mnemonic` struct: ```rust pub struct Mnemonic { entropy: Vec, // fields omitted } ``` We're going to define the three methods `as_bytes()`, `to_bytes()`, and `into_bytes()`, explaining what the details of each are. To start with: ### `Mnemonic::as_bytes()` This method will return a `&[u8]`, a reference to a slice of bytes, without allocating anything. The `Mnemonic` type is not consumed by this process. ```rust impl Mnemonic { /// Return a slice of bytes represented by the mnemonic. pub fn as_bytes(&self) -> &[u8] { &self.entropy } } ``` ### `Mnemonic::to_bytes()` This method will return a `Vec`, an allocated type containing the bytes, without consuming the `Mnemonic` type. This is useful if you may need the `Mnemonic` type in the future. ```rust impl Mnemonic { /// Return a `Vec` of bytes represented by the mnemonic. pub fn to_bytes(&self) -> Vec { self.entropy.to_vec() } } ``` ### `Mnemonic::into_bytes()` This method will return the internal representation of bytes. No allocation is performed, but the `Mnemonic` value is no longer accessible. ```rust impl Mnemonic { /// Return a Vec of bytes represented by the mnemonic. pub fn into_bytes(self) -> Vec { self.entropy } } ``` ## Creating Data: `Mnemonic::seed()` Sometimes you may have an operation (such as creating a seed from a mnemonic) which can't possibly happen without allocating some kind of data. In that case, it is not reasonable - or even possible - to have three methods for that case. In that case, it is reasonable to have a method with a "bare" name, such as `Mnemonic::seed()`. Additionally, unless it makes sense to make the type unusable after such an operation (using the type system to your advantage), it makes sense to borrow from self while returning the allocated value. ```rust impl Mnemonic { /// Create a seed from the mnemonic's data. pub fn seed(&self) -> Result, Error> { let result = perform_secret_operation(self.entropy)?; Ok(result) } } ``` ## Complex Example: `Mnemonic::into_parts()` Let's add a `Wordlist` to our `Mnemonic` type, so we can format it as a string. ```rust pub struct Mnemonic { entropy: Vec, wordlist: Wordlist, } ``` Because we now have two expensive-to-allocate variables in our type, we need to change how we deconstruct it into parts: ```rust impl Mnemonic { /// Split the Mnemonic into its interior parts. pub fn into_parts(self) -> (Vec, Wordlist) { let Mnemonic { entropy, wordlist } = self; (entropy, wordlist) } /// Return a Vec of bytes represented by the mnemonic. pub fn into_bytes(self) -> Vec { self.into_parts().0 } /// Return the Wordlist used by the mnemonic. pub fn into_wordlist(self) -> Wordlist { self.into_parts().1 } } ``` In practical use, `Mnemonic` stores `wordlist` as an `Arc` to allow reusing the same wordlist (parsing it is expensive!), but we'll ignore that for demonstration purposes.