#newtype #conversion #convert

无 std shrinkwraprs

自动派生 Rust 转换特性 -- 使处理 newtypes 变得轻松

9 个版本

使用旧的 Rust 2015

0.3.0 2019 年 12 月 12 日
0.2.3 2019 年 11 月 19 日
0.2.1 2019 年 1 月 25 日
0.2.0 2018 年 2 月 11 日
0.0.2 2018 年 2 月 4 日

2221Rust 模式

Download history 4195/week @ 2024-04-28 4108/week @ 2024-05-05 3557/week @ 2024-05-12 4422/week @ 2024-05-19 3929/week @ 2024-05-26 4563/week @ 2024-06-02 4937/week @ 2024-06-09 4225/week @ 2024-06-16 4606/week @ 2024-06-23 3279/week @ 2024-06-30 4072/week @ 2024-07-07 5010/week @ 2024-07-14 3899/week @ 2024-07-21 4293/week @ 2024-07-28 4291/week @ 2024-08-04 3695/week @ 2024-08-11

16,447 每月下载量
用于 169 个包 (54 个直接使用)

BSD-3-Clause

32KB
568

shrinkwraprs 流水线状态

latest version api documentation license

创建包装类型可以使我们给出关于代码正确性的更多编译时保证

// Now we can't mix up widths and heights; the compiler will yell at us!
struct Width(u64);
struct Height(u64);

但是...它们有点难用。如果你需要获取包装的 u64,你需要不断进行模式匹配来包装和解包值。

shrinkwraprs 通过允许你通过派生 Shrinkwrap 来派生各种转换特性的实现来减轻这种痛苦。

实现的功能

目前,使用 #[derive(Shrinkwrap)] 将为所有结构体派生以下特性

  • AsRef<InnerType>
  • Borrow<InnerType>
  • Deref<Target=InnerType>

此外,使用 #[shrinkwrap(mutable)] 还将派生以下特性

  • AsMut<InnerType>
  • BorrowMut<InnerType>
  • DerefMut<Target=InnerType>

最后,还有一个选项是 #[shrinkwrap(transformers)],这将派生一些有用的固有函数来转换包装数据

  • fn transform<F>(&mut self, mut f:F) -> &mut Self whereF:FnMut(&mutInnerType)
  • fn siphon<F, T>(self, mut f:F) ->TwhereF:FnMut(InnerType)-> T

...其中 transform 使链式更新内部值变得容易,而 siphon 允许你轻松地将内部值移出以产生不同类型的值。

transform 将具有与内部字段相同的可见性,这确保了 transform 不会泄露改变内部值(可能以违反不变性的方式)的可能性。 siphon 的可见性与结构体本身相同,因为它 提供调用者直接破坏您数据的方法。

酷,我该如何使用它?

首先,在您的 Cargo.toml 中将 shrinkwraprs 添加为依赖项

[dependencies]

shrinkwraprs = "0.3.0"

然后,只需在您想方便化的任何结构体上贴上 #[derive(Shrinkwrap)]

#[macro_use] extern crate shrinkwraprs;

#[derive(Shrinkwrap)]
struct Email(String);

fn main() {
    let email = Email("[email protected]".into());

    let is_discriminated_email =
        email.contains("+");  // Woohoo, we can use the email like a string!

    /* ... */
}

如果您有多个字段,但只有一个字段您想能够解引用/借用,则使用 #[shrinkwrap(main_field)] 标记

#[derive(Shrinkwrap)]
struct Email {
    spamminess: f64,
    #[shrinkwrap(main_field)] addr: String
}

#[derive(Shrinkwrap)]
struct CodeSpan(u32, u32, #[shrinkwrap(main_field)] Token);

如果您还希望能够直接修改包装的值,还可以添加属性 #[shrinkwrap(mutable)]

#[derive(Shrinkwrap)]
#[shrinkwrap(mutable)]
struct InputBuffer {
    buffer: String
}

...
let mut input_buffer = /* ... */;
input_buffer.push_str("some values");
...

依赖项

~2MB
~47K SLoC