#getter-setter #getters #setters #getter #setter #proc-macro #macro

macro getset

Getset,我们准备好了!一个用于生成字段上最基本获取器和设置器的过程宏。

12个版本

0.1.2 2021年11月28日
0.1.1 2020年5月13日
0.1.0 2020年2月13日
0.0.9 2019年10月21日
0.0.5 2017年6月2日

#58 in 过程宏

Download history 79162/week @ 2024-03-26 79360/week @ 2024-04-02 86388/week @ 2024-04-09 90107/week @ 2024-04-16 90761/week @ 2024-04-23 68522/week @ 2024-04-30 85214/week @ 2024-05-07 77964/week @ 2024-05-14 73058/week @ 2024-05-21 71308/week @ 2024-05-28 69595/week @ 2024-06-04 72476/week @ 2024-06-11 77701/week @ 2024-06-18 84883/week @ 2024-06-25 67135/week @ 2024-07-02 67439/week @ 2024-07-09

310,193 每月下载量
用于 676 个crate(198 个直接使用)

MIT 许可证

22KB
298

getset

Download License Docs Coverage Status

Getset,我们准备好了!

一个用于生成字段上最基本获取器和设置器的过程宏。

获取器生成如下 fn field(&self) -> &type,而设置器生成如下 fn field(&mut self, val: type)

这些宏不适用于需要在设置器和获取器内部执行自定义逻辑的字段。在这种情况下,请自己编写!

use getset::{CopyGetters, Getters, MutGetters, Setters};

#[derive(Getters, Setters, MutGetters, CopyGetters, Default)]
pub struct Foo<T>
where
    T: Copy + Clone + Default,
{
    /// Doc comments are supported!
    /// Multiline, even.
    #[getset(get, set, get_mut)]
    private: T,

    /// Doc comments are supported!
    /// Multiline, even.
    #[getset(get_copy = "pub", set = "pub", get_mut = "pub")]
    public: T,
}

fn main() {
    let mut foo = Foo::default();
    foo.set_private(1);
    (*foo.private_mut()) += 1;
    assert_eq!(*foo.private(), 2);
}

您可以使用 cargo-expand 生成输出。以下是上述代码生成的函数(使用 cargo expand --example simple 进行复制)

use getset::{Getters, MutGetters, CopyGetters, Setters};
pub struct Foo<T>
where
    T: Copy + Clone + Default,
{
    /// Doc comments are supported!
    /// Multiline, even.
    #[getset(get, get, get_mut)]
    private: T,
    /// Doc comments are supported!
    /// Multiline, even.
    #[getset(get_copy = "pub", set = "pub", get_mut = "pub")]
    public: T,
}
impl<T> Foo<T>
where
    T: Copy + Clone + Default,
{
    /// Doc comments are supported!
    /// Multiline, even.
    #[inline(always)]
    fn private(&self) -> &T {
        &self.private
    }
}
impl<T> Foo<T>
where
    T: Copy + Clone + Default,
{
    /// Doc comments are supported!
    /// Multiline, even.
    #[inline(always)]
    pub fn set_public(&mut self, val: T) -> &mut Self {
        self.public = val;
        self
    }
}
impl<T> Foo<T>
where
    T: Copy + Clone + Default,
{
    /// Doc comments are supported!
    /// Multiline, even.
    #[inline(always)]
    fn private_mut(&mut self) -> &mut T {
        &mut self.private
    }
    /// Doc comments are supported!
    /// Multiline, even.
    #[inline(always)]
    pub fn public_mut(&mut self) -> &mut T {
        &mut self.public
    }
}
impl<T> Foo<T>
where
    T: Copy + Clone + Default,
{
    /// Doc comments are supported!
    /// Multiline, even.
    #[inline(always)]
    pub fn public(&self) -> T {
        self.public
    }
}

可以在结构体级别为结构体中的所有字段设置属性。字段级属性具有优先级。

#[macro_use]
extern crate getset;

mod submodule {
    #[derive(Getters, CopyGetters, Default)]
    #[get_copy = "pub"] // By default add a pub getting for all fields.
    pub struct Foo {
        public: i32,
        #[get_copy] // Override as private
        private: i32,
    }
    fn demo() {
        let mut foo = Foo::default();
        foo.private();
    }
}
fn main() {
    let mut foo = submodule::Foo::default();
    foo.public();
}

出于某些目的,在获取器上使用 get_ 前缀是有用的,这可能是为了兼容性或历史原因。这可以通过 with_prefix 实现。

#[macro_use]
extern crate getset;

#[derive(Getters, Default)]
pub struct Foo {
    #[get = "pub with_prefix"]
    field: bool,
}

fn main() {
    let mut foo = Foo::default();
    let val = foo.get_field();
}

当使用结构级别属性时,可以跳过字段的设置器和获取器生成,方法是在代码中添加以下标记:#[getset(skip)]

use getset::{CopyGetters, Setters};

#[derive(CopyGetters, Setters)]
#[getset(get_copy, set)]
pub struct Foo {
    // If the field was not skipped, the compiler would complain about moving
    // a non-copyable type in copy getter.
    #[getset(skip)]
    skipped: String,

    field1: usize,
    field2: usize,
}

impl Foo {
    // It is possible to write getters and setters manually,
    // possibly with a custom logic.
    fn skipped(&self) -> &str {
        &self.skipped
    }

    fn set_skipped(&mut self, val: &str) -> &mut Self {
        self.skipped = val.to_string();
        self
    }
}

依赖项

~1.5MB
~36K SLoC