2 releases
0.1.1 | Apr 24, 2023 |
---|---|
0.1.0 | Apr 23, 2023 |
#776 in Procedural macros
33 downloads per month
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
~34K SLoC