2 releases
0.1.1 | Apr 24, 2023 |
---|---|
0.1.0 | Apr 23, 2023 |
#790 in Procedural macros
15KB
232 lines
On Your Marks.. Get Set.. Rust!
Things might break and error handling is primitive. Use at your own risk
This library provides a single macro GetSet
, which allows you to write rudimentary getters and setters for your struct.
I wrote this because I was tired of manually writing them. In most cases, you would not need getters and setters which are this primitive but I needed them (and also "muh proc-macros" ¯\_(ツ)_/¯
).
If you find a bug or have a feature which seems like a good fit, feel free to contribute.
Basic Usage
You can use the macro in the following manner:
#[derive(GetSet)]
struct Foo {
#[get(clone)]
bar: String,
#[get(copy)]
pub baz: f32,
#[get(im_ref(&Path), mut_ref(&mut Path))]
qux: PathBuf
#[set]
pub quux: Option<u64>,
}
These should effectively translate to:
impl Foo {
pub fn get_bar(&self) -> String {
self.bar.clone()
}
pub fn get_baz(&self) -> String {
self.baz.clone()
}
pub fn get_qux_ref(&self) -> &Path {
self.qux.as_ref()
}
pub fn get_qux_ref_mut(&self) -> &mut Path {
self.qux.as_mut()
}
pub fn set_quux(&mut self, value: Option<u64>) {
self.quux = value
}
}
Remarks
-
Each field can only have atmost one
#[get(..)]
attribute and atmost one#[set]
attibute.So, This is fine
... #[get(clone, im_ref(&i32), mut_ref(&mut i32))] corge: i32 ...
This is not!
... #[get(clone)] #[get(im_ref(&i32))] #[get(mut_ref(&mut i32))] corge: i32 ...
-
Arguments
copy
,clone
,im_ref
andmut_ref
can only be present at most once, inside an attribute. -
Arguments
copy
andclone
can be used inside the same attribute. -
Arguments
im_ref
andmut_ref
also require a rust type, which is the return type of the getter. -
Argument
im_ref
simply calls theAsRef
impl of that type. Similarilymut_ref
calls theAsMut
impl. -
If the Argument is either
copy
orclone
, the name of the getter will simply beget_<field_name>
, where<field_name>
is replaced by the name of the field on which the attribute is present. (See the above example) -
Similarly Argument is
im_ref
, the name of the getter will beget_<field_name>_ref
, andget_<field_name>_ref_mut
in case ofmut_ref
-
Attribute
#[set]
does not take any arguments and the name of the setter generated isset_<field_name>
. -
All the methods generated have
pub
visibility.
Funky
There also exist a special getter argument - funky
, which allows you to do funky stuff (duh).
This allows you to use any rust expression to manipulate the value, which you are getting.
...
#[get(funky(grault_opt :: grault.ok() => Option<i32>))]
grault: Result<i32>
#[get(funky(garply_mut_opt :: mut garply.as_mut() => Option<&mut i32>))]
garply: Option<f32>
...
These effectively translate to:
...
pub fn get_grault_opt(&self) -> Option<i32> {
self.grault.ok()
}
pub fn get_garply_mut_opt(&mut self) -> Option<&mut i32> {
self.garply.as_mut()
}
...
You must be careful while using this, because technically you can do things like:
...
#[get(funky(waldo_funk :: mut {
let foo = *waldo;
let bar = (foo * 420) as f32;
*waldo = (bar - 1.69) as i32;
bar
} => f32))]
pub waldo: i32
...
This will translate to something like
...
pub fn get_waldo_funk(&mut self) -> f32 {
let foo = *self.waldo;
let bar = (foo * 420) as f32;
self.waldo = (bar - 1.69) as i32;
bar
}
...
Remarks
- This is the only argument which can occur more than once.
funky
takes :- identifier which will be used to create the name of the getter,
- then, the
::
symbol - then, an optional
mut
keyword which specifies if the reciever is&mut self
or&self
- then, the
=>
symbol - then, the return type of the getter
- I only added this, because i find myself often needing getters which call a single method on a field and return that value (See the example)
- Probably do not use if you need to do more than one line of processing on the field value (or use it if you are lazy like me :D)
Dependencies
~1.5MB
~37K SLoC