「Rust 中方便和习惯性的转换」TryFrom和错误
「这是我参与11月更文挑战的第 19 天,活动详情查看:2021最后一次更文挑战」
尝试:TryFrom
我们看到,由From和Into进行的转换不能失败。然而,有时我们处理的类型并不完全相互映射,所以我们需要这些trait的易错版本。
幸运的是,有 TryFrom
和 TryInto
,它们返回一个 Result<TargetType, ErrorType>
。这两个trait和它们NB的兄弟姐妹一起存在于std::convert中,但它们的确切细节和含义仍在讨论中,这意味着它们仍被标记为不稳定。为了使用它们,我们可以将自己限制在编译器的nightly版本中,使用 try_from,或者将它们的定义粘贴在我们的库中的某个文件中(它们真的很短)。
让我们来看看TryFrom的定义(截至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>;
}
首先,我们有一个稳定性属性,标志着该特性是不稳定的,然后是特性定义本身。我们可以看到它有一个相关的类型,Err,用于转换失败的情况。正如预期的那样,我们有一个try_from方法而不是from,它返回Result<Self, Self::Err>而不是Self。
继续我们的例子:
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))
}
}
}
在这个例子中,对于可以映射的值,我们返回相应的 PacketType 变量,对于其余的值,我们返回一个错误。这个错误类型保留了原始值,这对调试有潜在的帮助,但其实我们可以直接丢弃它。
AsRef
and AsMut
最后我们看看std::convert模块中剩下的trait,放到最后并非是它们不重要。AsRef和AsMut。像convert模块中的其他trait一样,它们被用来实现类型间的转换。
然而,其他特质会消耗数值,并可能执行重的操作,而 AsRef 和 AsMut 是用来实现轻便的,引用到引用的转换。
你可能已经从它们的名字中猜到了,AsRef将一个不可变的值的引用转换为另一个不可变的引用,而AsMut对可变的引用做同样的转换。
由于它们都非常相似,我们同时看看它们。让我们从它们的定义开始:
#[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;
}
转载自:https://juejin.cn/post/7034862561367425032