TryFrom 与 TryInto

TryFromTryInfo 这两个 trait, 主要是为了容错, 因为类型之间的转换有可能是 会失败的. 所以这两个 trait 会返回 Result<> 结构.

它们的定义如下, 可以看到, 接口定义跟 From trait 以及 Into trait 很相似:

#![allow(unused)]
fn main() {
pub trait TryFrom<T>: Sized {
    type Error;

    // Required method
    fn try_from(value: T) -> Result<Self, Self::Error>;
}

pub trait TryInto<T>: Sized {
    type Error;

    // Required method
    fn try_into(self) -> Result<T, Self::Error>;
}
}

char 模块实现了将 char 转换成 u8, u16 等数值类型, 下面是代码片段:

#[stable(feature = "u8_from_char", since = "1.59.0")]
impl TryFrom<char> for u8 {
    type Error = TryFromCharError;

    /// Tries to convert a [`char`] into a [`u8`].
    ///
    /// # Examples
    ///
    /// ```
    /// let a = 'ÿ'; // U+00FF
    /// let b = 'Ā'; // U+0100
    /// assert_eq!(u8::try_from(a), Ok(0xFF_u8));
    /// assert!(u8::try_from(b).is_err());
    /// ```
    #[inline]
    fn try_from(c: char) -> Result<u8, Self::Error> {
        u8::try_from(u32::from(c)).map_err(|_| TryFromCharError(()))
    }
}

平时只需要实现 TryFrom trait 即可, 因为 TryInto 已被标准库实现:

// TryFrom implies TryInto
#[stable(feature = "try_from", since = "1.34.0")]
impl<T, U> TryInto<U> for T
where
    U: TryFrom<T>,
{
    type Error = U::Error;

    #[inline]
    fn try_into(self) -> Result<U, U::Error> {
        U::try_from(self)
    }
}

一个示例代码

下面的代码定义了MQTT协议的版本.

#![allow(unused)]

fn main() {
use std::convert::TryFrom;

/// Current version of MQTT protocol can be:
/// * 3.1
/// * 3.1.1
/// * 5.0
#[repr(u8)]
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum ProtocolLevel {
    /// MQTT 3.1
    V3 = 3,

    /// MQTT 3.1.1
    #[default]
    V4 = 4,

    /// MQTT 5.0
    V5 = 5,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DecodeError {
    InvalidProtocolLevel,
}

impl TryFrom<u8> for ProtocolLevel {
    type Error = DecodeError;

    fn try_from(v: u8) -> Result<Self, Self::Error> {
        match v {
            3 => Ok(Self::V3),
            4 => Ok(Self::V4),
            5 => Ok(Self::V5),

            _ => Err(DecodeError::InvalidProtocolLevel),
        }
    }
}
}

其它转换方式