「Rust 中方便和習慣性的轉換」TryFrom和錯誤

語言: CN / TW / HK

theme: cyanosis

「這是我參與11月更文挑戰的第 19 天,活動詳情檢視:2021最後一次更文挑戰


嘗試:TryFrom

我們看到,由From和Into進行的轉換不能失敗。然而,有時我們處理的型別並不完全相互對映,所以我們需要這些trait的易錯版本。

幸運的是,有 TryFromTryInto,它們返回一個 Result<TargetType, ErrorType>。這兩個trait和它們NB的兄弟姐妹一起存在於std::convert中,但它們的確切細節和含義仍在討論中,這意味著它們仍被標記為不穩定。為了使用它們,我們可以將自己限制在編譯器的nightly版本中,使用 try_from,或者將它們的定義貼上在我們的庫中的某個檔案中(它們真的很短)。

讓我們來看看TryFrom的定義(截至Rust 1.10.0):

```rust

[unstable(feature = "try_from", issue = "33417")]

pub trait TryFrom: 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。

繼續我們的例子:

rust 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對可變的引用做同樣的轉換。

由於它們都非常相似,我們同時看看它們。讓我們從它們的定義開始:

```rust

[stable(feature = "rust1", since = "1.0.0")]

pub trait AsRef { /// 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 { /// Performs the conversion. #[stable(feature = "rust1", since = "1.0.0")] fn as_mut(&mut self) -> &mut T; } ```