#枚举 #类型 # #宏-derive #derive #utility

try_as

提供宏和特性以简化使用仅用于枚举类型集合的枚举的使用

1 个不稳定版本

使用旧的 Rust 2015

0.1.0 2022 年 12 月 22 日

#1272 in Rust 模式

43 每月下载次数

自定义许可

13KB

提供宏和特性以简化使用仅用于枚举类型集合的枚举的使用。

它导出了一组特性,有助于实现这一目的

  • traits::TryAsRef - 类似于 AsRef<T>,但允许失败
  • traits::TryAsMut - 类似于 AsMut<T>,但允许失败
  • traits::TypedContainer - 检查容器的类型

以及一组宏,这些宏从这些和某些标准特性中派生出实现,具体如下

  • macros::From 将类型转换为枚举
  • macros::TryInto 将枚举转换回类型
  • macros::TryAsMut 获取枚举值的引用
  • macros::TryAsRef 获取枚举值的可变引用
  • macros::TypedContainer 检查枚举中的类型

要派生枚举的特性,枚举必须具有以下形状

  • 每个变体必须恰好有一个未命名的参数
  • 每个变体参数类型最多出现一次

文档

文档可以在这里阅读:这里

示例

一个简短的示例,其中使用了所有宏:我们有一个包含 3 种类型之一的枚举值:i64Stringbool

enum Value{
    Number(i64),
    String(String),
    Bool(bool)
}

我们想在这枚举和类型 i64Stringbool 之间进行转换。使用此包的宏,可以轻松实现这一点

#[derive(try_as::From, try_as::TryInto, Debug, PartialEq, Eq)]
enum Value{
    Number(i64),
    String(String),
    Bool(bool)
}

let x = Value::from(0);
assert_eq!(x, Value::Number(0));

let maybe_i64: Result<i64, _> = x.try_into();
assert_eq!(maybe_i64.unwrap(), 0);

更多信息请参阅 文档

待办事项和笔记

API可能尚未稳定。欢迎提出改进建议和PR!


在某些情况下,某些特性使用起来可能较为冗长,例如

#[derive(try_as::From, try_as::TryInto, Debug)]
enum Value{
    Number(i64),
    String(String),
    Bool(bool)
}

let x = Value::from(0);
// This doesn't work; rust can't resolve the type on its own
assert_eq!(x.try_into().unwrap(), 0);
// So etiher we write this
assert_eq!((x as dyn TryInto<i64, _>).try_into().unwrap(), 0);
// Or this
let maybe_i64: Result<i64, _> = x.try_into();
assert_eq!(maybe_i64.unwrap(), 0);

这个问题在实际情况中可能不太常见,待定。

如果确实如此,我们可能可以定义这些特性的辅助方法,允许在方法泛型参数中指定返回类型,

pub trait TryAsMut<T> {
    fn try_as_mut(&mut self) -> Option<&mut T>;

    fn try_as_mut_of<U>(&mut self) -> Option<&mut U>
    where
        Self: TryAsMut<U>,
    {
        self.try_as_mut()
    }
}

/// Now we can get an `Option<&i64>` simply by writing
let maybe_val = x.try_as_mut_of::<i64>();
// Or to unwrap
let val = x.try_as_mut_of::<i64>().unwrap();

对于TryInto,我们可以提供泛型实现,例如

pub trait TryAs {
    fn try_as<T>(self) -> Result<T, Self>
    where
        Self: TryInto<T, Error = Self>,
    {
        self.try_into()
    }
}

impl<U> TryAs for U {}

// Now, if `x` has an implementation of TryInto<u64>, we can write
let maybe_val = x.try_as::<i64>();
// Or to unwrap
let val = x.try_as::<i64>().unwrap();

依赖

~1.5MB
~34K SLoC