“This is the 19th day of my participation in the Gwen Challenge in November. Check out the details: The Last Gwen Challenge in 2021”


Try: TryFrom

We see that conversions From and Into cannot fail. However, sometimes the types we work with don’t exactly map to each other, so we need error-prone versions of these traits.

Fortunately, there are TryFrom and TryInto, which return a Result

. Both traits are present in STD ::convert along with their NB siblings, but their exact details and meanings are still under discussion, meaning they are still marked as unstable. To use them, we can limit ourselves to the nightly version of the compiler, use try_from, or paste their definitions in some file in our library (they’re really short).
,>

Let’s look at the definition of TryFrom (as of Rust 1.10.0):

#[unstable(feature = "try_from", issue = "33417")]
pub trait TryFrom<T>: Sized {
    /// The type returned in the event of a conversion error.
    type Err;

    /// Performs the conversion.
    fn try_from(T) -> Result<Self, Self::Err>;
}
Copy the code

First, we have a stability property, which signals that the property is unstable, and then the property definition itself. We can see that it has an associated type, Err, for conversion failures. As expected, we have a try_from method instead of from, which returns Result<Self, Self::Err> instead of Self.

Continuing with our example:

impl TryFrom<u8> for PacketType {
    type Err = ParseError;
    fn try_from(original: u8) - >Result<Self, Self::Err> {
        match original {
            0= >Ok(PacketType::Data),
            1= >Ok(PacketType::Fin),
            2= >Ok(PacketType::State),
            3= >Ok(PacketType::Reset),
            4= >Ok(PacketType::Syn),
            n => Err(ParseError::InvalidPacketType(n))
        }
    }
}
Copy the code

In this example, we return the corresponding PacketType variable for the values that can be mapped, and an error for the rest. This error type preserves the original value, which is potentially useful for debugging, but can be discarded directly.

AsRef and AsMut

Finally, let’s look at the rest of the traits in the STD ::convert module, not because they’re unimportant. AsRef and AsMut. Like other traits in the Convert module, they are used to convert between types.

However, while other attributes consume values and may perform heavy operations, AsRef and AsMut are used for lightweight, reference-to-reference conversions.

As you might have guessed from their name, AsRef converts a reference to an immutable value to another immutable reference, while AsMut does the same for mutable references.

And since they’re both very similar, let’s look at them at the same time. Let’s start with their definitions:

#[stable(feature = "rust1", since = "1.0.0")]
pub trait AsRef<T: ?Sized> {
    /// Performs the conversion.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn as_ref(&self) -> &T;
}

#[stable(feature = "rust1", since = "1.0.0")]
pub trait AsMut<T: ?Sized> {
    /// Performs the conversion.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn as_mut(&mut self) - > &mut T;
}
Copy the code