# Package rust-jemmy
This package provides a coherent set of macros that *manually* generate accessor
methods for fields in structures and variants in enums.
[](https://opensource.org/licenses/Apache-2.0)
[](https://opensource.org/license/mit)
[](https://github.com/johnstonskj/rust-jemmy/actions/workflows/rust.yml)
[](https://github.com/johnstonskj/rust-jemmy/actions/workflows/security-audit.yml)
[](https://codecov.io/gh/johnstonskj/rust-jemmy)
[](https://github.com/johnstonskj/rust-jemmy/stargazers)
While a number of packages exist to simplify the addition of accessors to Rust
structures and enumerations these are often derive macros that come with a
trade-off between flexibility and control. Jemmy takes a different and more
flexible approach. It provides a set of very simple leaf macros and then
aggregate macros that build common patterns from these building blocks. For
example, you can add `get_and_set` methods for a simple field, or `with_get_and_set`
to include an initializer as well. You can use the `get_set_and_unset` for
optional fields which produces `foo() -> Option<&T>`, `set_foo(T)`, and `unset_foo()`
methods rather than a setter that takes an `Option<T>`.
The name Jemmy was chosen for this crate as the common name for a small pry-bar
or crowbar used in burglary, a very direct form of *manual access*.
## Example 1 - Structures
The following shows the basics of the macros for generating accessor methods for
the fields of a structure. This generates *init*ializer, *get*ter and *set*ter methods
for the `number_on_street` and `street_1` fields. And generates *get*ter, *set*ter
(value) and *un-set*ter (`None`) methods for the `street_2` field.
```rust
use jemmy::*;
#[derive(Default)]
pub struct Address {
number_on_street: u32,
street_1: String,
street_2: Option<String>,
// ...
}
impl Address {
with!(pub number_on_street => u32);
get!(pub number_on_street => copy u32);
set!(pub number_on_street => u32);
with_get_and_set!(pub street_1 => into String);
get_set_and_unset!(pub street_2 => String);
}
```
## Example 2 - Enums
The following shows the basics of the macros for generating accessor methods
for the variants of an enum. For each variant an `is_variant` predicate and
`as_variant` cast methods are provided.
```rust
# pub struct Address(String);
use jemmy::*;
pub enum TypedAddress {
Home(Address),
Work(Address),
Other(Address),
}
impl TypedAddress {
is_variant!(Home => Address);
as_variant!(Home => Address);
is_as_variant!(Work => Address);
is_as_variant!(Other => Address);
}
```
## Standard Forms
The following are the primary forms supported by the macros in the crate; the
first is the form of all field macros, the second is the form of all variant
macros.
1. `(viz name => [field_name,] [keywords] [type])`
2. `(viz enum, variant [=> type])`
The elements of these forms are described below.
1. **viz**; the vizibility specifier for the generated method.
2. for field macros:
1. **name**;
2. **field name**; (optional) when the visible name of the field is different
from its field name you may specify both.
3. **keywords** (optional):
1. **copy**; denotes that the field type implements `Copy` and the generatted
method will return a value rather than a reference.
1. **into**; will generate a setter method that takes a parameter of type
`Into<T>` rather than the typical `T`.
2. **optional**; denotes that the field is an `Option<T>` not `T` which affects
all getters and setters.
4. **type**; (optional) the type of the field, specifically `T`, *do not* specify
`Option<T>` or `Into<T>` if using the corresponding keywords.
3. for enum macros:
1. **enum**; the enum type's identifier.
2. **variant**; the variant's identifier within the enum.
3. **type**; (optional) the type of any value of the variant.
### Structure Fields Macro Summary
| `with!` | number_on_street | | u32 | `fn with_number_on_street(mut self, number_on_street: u32) -> Self` |
| `with!` | street_1 | into | String | `fn with_street_1<T: Into<String>(mut self, street_1: T) -> Self` |
| `with!` | street_2 | optional | String | `fn with_street_2(mut self, street_2: String) -> Self` |
| `get!` | number_on_street | copy | u32 | `const fn number_on_street(&self) -> u32` |
| `get!` | street_1 | | String | `const fn street_1(&self) -> &String` |
| `get!` | street_2 | optional | String | `const fn street_2(&self) -> Option<&String>` |
| `set!` | number_on_street | | u32 | `fn set_number_on_street(&mut self, number_on_street: u32)` |
| `set!` | street_1 | into | String | `fn set_street_1<T: Into<String>(&mut self, street_1: T)` |
| `set!` | street_2 | optional | String | `fn set_street_2(&mut self, street_1: String)` |
| `unset!` | street_2 | | String | `fn unset_street_2(&mut self)` |
### Enum Variants Macro Summary
| `impl_from_for_variant` | Home | | Address | `impl From<Address> for TypedAddress {}` |
| `impl_from_for_variant` | Home | into | Address | `impl<T: Into<Address>> From<T> for TypedAddress {}` |
| `is_variant!` | Home | | Address | `const fn is_home(&self) -> bool` |
| `is_variant!` | Unparsed | | () | `const fn is_unparsed(&self) -> bool` |
| `is_variant!` | Unknown | | () | `const fn is_unknown(&self) -> bool` |
| `as_variant!` | Home | | Address | `const fn as_address(&self) -> Option<&Address>` |
| `as_variant!` | UnParsed | | String | `const fn as_unparsed(&self) -> Option<&String>` |
| `as_variant!` | UnParsed | value | String | `const fn as_unparsed(&self) -> Option<String>` |
| `as_variant!` | Unknown | | () | `const fn as_unknown(&self) -> Option<()>` |
## Changes
### Version 0.1.6
* Fix: converted action workflow to use a config file for tarpaulin.
* Refactor: broke apart the monolithic `lib.rs` into a hierarchy of modules.
* Refactor: followed the same for test modules.
### Version 0.1.5
* Fix: macro implementations:
* Correct comment for `set!` macro case 4
* Fix `with_get_and_set!` implementation for copy types
* Reorder `as_variant!` cases to prioritize empty variant handling
* Documentation: in `as_variant!` macro
* Test: add comprehensive tests for various macro use cases
### Version 0.1.4
* Feature: added `optional copy` and `optional into` for core macros.
* Documentation: most of the docs for the above are also added.
* Test: test_shorts is now the more useful version of the doc tests.
### Version 0.1.3
* Feature: added `#[doc]` to all generated methods.
* Feature: added new options to `with_get_and_set!`.
* Feature: added new macro `with_get_set_and_unset!`.
### Version 0.1.2
Minor improvements and completed documentation.
* Feature: added new `impl_from_for_variant!` macro.
* Feature: made all methods generated by `get!` and `get_mut!` marked `const`.
* Feature: made all methods generated by `unset!` marked as `#[inline(always)]`.
* Documentation: completed all macro and module docs.
* Chore: renamed files; 'LICENSE-*.txt' => 'LICENSE-*'
### Version 0.1.1
Provided addition *helper* or *combinator* macros, and provided module
documentation as well as documentation for more than half of the present
set of macros.
* Structure field macros
* `get_and_set!`
* `with_get_and_set!`
* `get_set_and_unset!`
* Enum field macros
* `is_as_variant!`
### Version 0.1.0
Provided an initial set of macros.
* Structure field macros
* initializers -- `with!` ⟹ `with_fname(mut self, fname: T) -> Self`
* getters -- `get!` ⟹ `fname(&self) -> &T | T | Option<&T>`
* setters -- `set!` ⟹ `set_fname(&mut self, T | Into<T>)`
* un-setters -- `unset!` ⟹ `unset_fname(&mut self)`
* Enum field macros
* predicates -- `is_variant!` ⟹ `is_vname(&self) -> bool`
* getters -- `as_variant!` ⟹ `as_vname(&self) -> &T`