61 个版本 (稳定版)

4.0.1 2024 年 8 月 1 日
4.0.0 2023 年 10 月 9 日
4.0.0-alpha.62023 年 2 月 7 日
4.0.0-alpha.22022 年 12 月 8 日
0.1.2 2020 年 7 月 3 日

#14#patterns

Download history 4461/week @ 2024-05-04 2750/week @ 2024-05-11 3170/week @ 2024-05-18 2833/week @ 2024-05-25 3092/week @ 2024-06-01 2685/week @ 2024-06-08 3976/week @ 2024-06-15 4657/week @ 2024-06-22 3748/week @ 2024-06-29 3312/week @ 2024-07-06 4347/week @ 2024-07-13 3730/week @ 2024-07-20 5849/week @ 2024-07-27 5912/week @ 2024-08-03 5798/week @ 2024-08-10 5728/week @ 2024-08-17

23,694 每月下载量
用于 90 个 crate (15 直接使用)

Apache-2.0

255KB
5K SLoC

Rust Amplify 库:派生宏

Build Tests Lints codecov

Docs unsafe forbidden Apache-2 licensed

增强 Rust 语言功能:多个泛型特质的实现,类型包装,派生宏。

这是 Rust 语言增强库的一部分,提供所需的派生宏。

最低支持的 Rust 编译器版本 (MSRV):1.60.0。Rust 版本 2021。

概述

显示派生

  1. 使用其他格式化特质生成 Display 描述
     #[derive(Display, Debug)]
     #[display(Debug)]
     struct Some { /* ... */ }
    
  2. 使用现有函数显示描述
     #[derive(Display)]
     #[display(Int::print)]
     union Int { uint: u32, int: i32 };
    
     impl Int {
         pub fn print(&self) -> String {
             s!("Integer representation")
         }
     }
    
    格式化函数必须返回 String 并接受单个 self 参数(如果您需要带有流式输出的格式化,请使用第 1 部分中所示的一个现有格式化特质)。
  3. 自定义格式字符串
     #[derive(Display)]
     #[display("({x}, {y})")]
     struct Point { x: u32, y: u32 }
    
  4. 使用文档注释来表示描述。在这种情况下,文档注释也可能包含类似于情况 3 的格式化
     #[macro_use] extern crate amplify;
    
     #[derive(Display)]
     #[display(doc_comments)]
     enum Variants {
         /// Letter A
         A,
    
         /// Letter B
         B,
    
         /// This comment is ignored
         #[display("Letter C")]
         C,
    
         /// Letter {_0}
         Letter(String)
     };
    
     assert_eq!(format!("{}", Variants::C), "Letter C");
     assert_eq!(format!("{}", Variants::Letter(s!("K"))), " Letter K");
    
    您还可以在此模式下与其他特定选项上的显示标签混合;在这种情况下,文档注释将被忽略

示例

高级使用枚举

#[derive(Debug, Display)]
#[display(Debug)]
enum Test {
    Some,

    #[display = "OtherName"]
    Other,

    Named {
        x: u8,
    },

    #[display = "Custom{x}"]
    NamedCustom {
        x: u8,
    },

    Unnamed(u16),

    // NB: Use `_`-prefixed indexes for tuple values
    #[display = "Custom{_0}"]
    UnnamedCustom(String),
}

错误派生

错误推导宏仅在与其他错误推导宏一起使用时才能完全工作。使用 #[derive(Display)][display(doc_comments)] 时,它使用文档注释来生成错误描述;使用 #[derive(From)] 时,它可以自动实现来自其他错误类型的转换。

#[derive(Debug, Display, Error)]
#[display(doc_comments)]
enum Error {
    /// I/O operation error
    Io,
    /// Math overflow
    Overflow,
    /// Zero division with {_0}
    ZeroDivision(u16),
}

来自 derive

实现了整个实体及其单独字段的对 From 特质的实现。与 #[derive(Error)] 一起工作良好,并且在许多情况下可能需要 Default 的实现(详细信息,请参见下面的示例)

示例

#[derive(From, Default)]
#[from(::std::io::Error)]
// Structure may contain no parameters
pub struct IoErrorUnit;

#[derive(From, Default)]
#[from(::std::io::Error)] // When no explicit binding is given, structure must implement `Default`
pub struct IoError {
    details: String,

    #[from]
    kind: IoErrorUnit,
}

#[derive(From)]
pub enum Error {
    // You can specify multiple conversions with separate attributes
    #[from(::std::io::Error)]
    #[from(IoError)]
    Io,

    #[from]
    Format(::std::fmt::Error),

    #[from]
    WithFields { details: ::std::str::Utf8Error },

    MultipleFields {
        // ...and you can also covert error type
        #[from(IoErrorUnit)]
        // rest of parameters must implement `Default`
        io: IoError,
        details: String,
    },
}

#[derive(From)]
pub struct Wrapper(u32, i16);

包装推导

创建一个包装现有类型的 rust 新类型。可用于包含多个命名或未命名字段的结构体中;在这种情况下,您希望包装的字段应该用 #[wrap] 属性标记;否则假定第一个字段是包装的字段。

使用多个字段需要您在主结构体上实现 FromDefault 的推导。

支持自动实现以下特质

  • 放大::包装器
  • AsRef
  • AsMut
  • 借用
  • 借用Mut
  • Deref
  • DerefMut

只有在使用带有 trivial_bounds 特性门和 nightly 特性集的夜间 rust 编译器的夜间 rust 编译器时,才能完整使用此推导宏。这将为额外的特质提供自动实现,如果它们为包装类型实现

  • 显示
  • LowerHex
  • UpperHex
  • LowerExp
  • UpperExp
  • 八进制
  • 索引
  • 索引Mut
  • 加分配
  • 减分配
  • 乘分配
  • 除分配

其他特质,如 PartialEqEqPartialOrdOrdHash 可以通过在相同的 #[derive] 属性中实现,与 DefaultDebugFrom 以相同的方式实现

示例

use std::marker::PhantomData;
use amplify::Wrapper;

#[derive(Clone, Wrapper, Default, From, Debug)]
struct Wrapped<T, U>(
    #[wrap]
    #[from]
    HashMap<usize, Vec<U>>,
    PhantomData<T>,
)
where
    U: Sized + Clone;

let w = Wrapped::<(), u8>::default();
assert_eq!(w.into_inner(), HashMap::<usize, Vec<u8>>::default());

获取器推导

为结构体内的所有字段(包括公共和私有字段)创建与字段名称匹配的获取器方法。获取器返回引用类型。

示例

#[derive(Getters, Default)]
struct One {
    a: Vec<u8>,
    pub b: bool,
    pub(self) c: u8,
}

let one = One::default();
assert_eq!(one.a(), &Vec::<u8>::default());
assert_eq!(one.b(), &bool::default());
assert_eq!(one.c(), &u8::default());

AsAny derive

特性 amplify::AsAny 允许将任何类型简单地转换为通用的“胖”指针 &dyn Any(参见 ::core::any::Any),之后可以将它转换回原始类型,对于所有其他转换将以优雅的方式失败。`AsAny` derive 宏允许在任意类型上轻松实现此特性。

示例

# #[macro_use] extern crate amplify_derive;
extern crate amplify;
use amplify::AsAny;

#[derive(AsAny, Copy, Clone, PartialEq, Eq, Debug)]
struct Point {
    pub x: u64,
    pub y: u64,
}

#[derive(AsAny, PartialEq, Debug)]
struct Circle {
    pub radius: f64,
    pub center: Point,
}

let mut point = Point { x: 1, y: 2 };
let point_ptr = point.as_any();

let mut circle = Circle {
    radius: 18.,
    center: point,
};
let circle_ptr = circle.as_any();

assert_eq!(point_ptr.downcast_ref(), Some(&point));
assert_eq!(circle_ptr.downcast_ref(), Some(&circle));
assert_eq!(circle_ptr.downcast_ref::<Point>(), None);

let p = point_ptr.downcast_ref::<Point>().unwrap();
assert_eq!(p.x, 1)

依赖项

~1.5MB
~36K SLoC