6 个稳定版本
1.3.1 | 2024年5月15日 |
---|---|
1.3.0 | 2023年11月17日 |
1.2.1 | 2023年9月24日 |
1.1.0 | 2023年8月5日 |
#1782 在 开发工具
12,469 每月下载量
在 17 个 Crates 中使用 (通过 indexed_db_futures)
46KB
666 行
为获取器和设置器提供的一个优雅且可配置的推导宏。有关选项的完整列表,请参阅推导宏文档。
示例
基本用法
#[derive(Default, accessory::Accessors)]
struct Structopher {
/// The comment gets copied over
#[access(set, get, get_mut)] // Generate a setter, getter ant mut getter
field: String,
_field2: u8, // Generate nothing
}
let mut data = Structopher::default();
data.set_field("Hello, world!".to_string());
let get: &String = data.field();
assert_eq!(get, "Hello, world!", "get(1)");
let mut get: &mut String = data.field_mut();
*get = "Hello, universe!".to_string();
let mut get = data.field();
assert_eq!(get, "Hello, universe!", "get(2)");
生成输出
impl Structopher {
/// The comment gets copied over
#[inline]
pub fn field(&self) -> &String { &self.field }
/// The comment gets copied over
#[inline]
pub fn field_mut(&mut self) -> &mut String { &mut self.field }
/// The comment gets copied over
#[inline]
pub fn set_field(&mut self, new_value: String) -> &mut Self {
self.field = new_value;
self
}
}
选项继承
选项优先级如下
- 字段属性
- 每个访问器类型 (
get
,get_mut
,set
) - 通配符 (
all
)
- 每个访问器类型 (
- 容器属性 (
defaults
)- 每个访问器类型 (
get
,get_mut
,set
) - 通配符 (
all
)
- 每个访问器类型 (
#[derive(accessory::Accessors, Default, Eq, PartialEq, Debug)]
#[access(
get, set, // derive these for all fields by default
// set defaults for whenever
defaults(
all(
const_fn, // Make it a const fn
owned, // use `self` and not `&self`
cp // Treat it as a copy type. Treats it as a reference if not set & not `owned`
),
get(
owned = false, // overwrite from `all`
vis(pub(crate)) // set visibilty to `pub(crate)`
)
)
)]
struct Structopher {
#[access(
all(const_fn = false), // Disable the container's const_fn for this field
get(const_fn), // But re-enable it for the getter
get_mut // enable with defaults
)]
x: i8,
y: i8,
#[access(get_mut(skip))] // skip only get_mut
z: i8,
#[access(skip)] // skip this field altogether
w: i8,
}
const INST: Structopher = Structopher { x: 0, y: 0, z: 0, w: 0 }
.set_y(-10)
.set_z(10);
let mut inst = Structopher::default();
inst = inst.set_x(10);
*inst.x_mut() += 1;
assert_eq!(INST, Structopher { x: 0, y: -10, z: 10, w: 0 } , "const instance");
assert_eq!(inst, Structopher { x: 11, y: 0, z: 0, w: 0 } , "instance");
生成输出
impl Structopher {
#[inline]
pub(crate) const fn x(&self) -> i8 { self.x }
#[inline]
pub fn x_mut(mut self) -> i8 { self.x }
#[inline]
pub fn set_x(mut self, new_value: i8) -> Self {
self.x = new_value;
self
}
#[inline]
pub(crate) const fn y(&self) -> i8 { self.y }
#[inline]
pub const fn set_y(mut self, new_value: i8) -> Self {
self.y = new_value;
self
}
#[inline]
pub(crate) const fn z(&self) -> i8 { self.z }
#[inline]
pub const fn set_z(mut self, new_value: i8) -> Self {
self.z = new_value;
self
}
}
名称和类型
您可以修改函数的返回类型和名称
#[derive(Default, accessory::Accessors)]
#[access(defaults(get(prefix(get))))]
struct Structopher {
#[access(
get(suffix(right_now), ty(&str)), // set the suffix and type
get_mut(suffix("")) // remove the inherited suffix set by `get_mut`
)]
good: String,
}
let mut inst = Structopher::default();
*inst.good() = "On it, chief".into();
assert_eq!(inst.get_good_right_now(), "On it, chief");
生成输出
impl Structopher {
#[inline]
pub fn get_good_right_now(&self) -> &str { &self.good }
#[inline]
pub fn good(&mut self) -> &mut String { &mut self.good }
}
泛型限制
#[derive(Default, accessory::Accessors)]
#[access(bounds(World: PartialEq))] // applies to the impl block
struct Hello<World> {
#[access(get(cp, bounds(World: Copy)))] // Applies to specific accessor
world: World,
}
let world: u8 = Hello { world: 10u8 }.world();
assert_eq!(world, 10);
生成输出
impl<World> Hello<World> where World: PartialEq {
#[inline]
pub fn world(&self) -> World where World: Copy {
self.world
}
}
取消引用原始指针
该库支持取消引用原始指针,使其对外部代码不可见。让我们看看我们的示例结构体,然后我们将逐字段进行分析。
#[derive(Accessors)]
#[access(get, get_mut, set, defaults(all(ptr_deref())))]
struct NotUnsafeWhatsoever {
direct: *mut String,
#[access(get(ty(&str)), get_mut(ty(&mut str)), set(skip))]
retyped: *mut String,
#[access(get(ptr_deref(mut)), get_mut(skip), set(skip))]
force_mutable: *mut NoImmutablesHere,
#[access(get(cp), get_mut(cp))]
copy_field: *mut usize,
}
// Setting up
let mut direct = String::from("direct");
let mut retyped = String::from("retyped");
let mut force_mutable = NoImmutablesHere::default();
let mut copy_field = 100;
let mut inst = NotUnsafeWhatsoever {
direct: &mut direct,
retyped: &mut retyped,
force_mutable: &mut force_mutable,
copy_field: &mut copy_field,
};
// Check `direct`
inst.direct_mut().push_str("ly opposed to this");
assert_eq!(&*direct, "directly opposed to this");
assert_eq!(inst.direct(), &*direct);
inst.set_direct(String::from("too big for the two of us"));
assert_eq!(&*direct, "too big for the two of us");
assert_eq!(inst.direct(), &*direct);
// Check `retyped`
assert_eq!(inst.retyped(), "retyped");
let (re, _) = inst.retyped_mut().split_at_mut(2);
re.make_ascii_uppercase();
assert_eq!(inst.retyped(), "REtyped");
// Check `force_mutable` - just a type check
let _fmut: &mut NoImmutablesHere = inst.force_mutable();
// Check `copy_field`
*inst.copy_field_mut() += 1;
assert_eq!(inst.copy_field(), 101);
assert_eq!(copy_field, 101);
inst.set_copy_field(777);
assert_eq!(inst.copy_field(), 777);
assert_eq!(copy_field, 777);
direct
字段继承了默认的自动 ptr_deref()
并生成了以下代码:无类型修改
#[inline]
pub fn direct(&self) -> &String {
unsafe { &*self.direct }
}
#[inline]
pub fn direct_mut(&mut self) -> &mut String {
unsafe { &mut *self.direct }
}
#[inline]
pub fn set_direct(&mut self, new_value: String) -> &mut Self {
unsafe {
*self.direct = new_value;
};
self
}
retyped
字段在 get
和 get_mut
中显式设置了类型,该类型被传播到取消引用中
#[inline]
pub fn retyped(&self) -> &str {
unsafe { &*self.retyped }
}
#[inline]
pub fn retyped_mut(&mut self) -> &mut str {
unsafe { &mut *self.retyped }
}
force_mutable
假设我们正在处理一些内部代码,并绕过 Rust 的编译时借用检查,并允许我们从对 NotUnsafeWhatsoever
的不可变引用中取消引用到对 NoImmutablesHere
的可变引用
#[inline]
pub fn force_mutable(&self) -> &mut NoImmutablesHere {
unsafe { &mut *self.force_mutable }
}
最后,copy
字段标记为 cp
,将不会返回带有 get
的引用
#[inline]
pub fn copy_field(&self) -> usize {
unsafe { *self.copy_field }
}
#[inline]
pub fn copy_field_mut(&mut self) -> &mut usize {
unsafe { &mut *self.copy_field }
}
#[inline]
pub fn set_copy_field(&mut self, new_value: usize) -> &mut Self {
unsafe {
*self.copy_field = new_value;
};
self
}
依赖
~335–790KB
~18K SLoC