jemmy

Crates.iojemmy
lib.rsjemmy
version0.1.6
created_at2025-06-26 18:41:17.07994+00
updated_at2025-07-09 15:20:42.824344+00
descriptionThis package provides a coherent set of manual accessor macros.
homepage
repositoryhttps://github.com/johnstonskj/rust-jemmy.git
max_upload_size
id1727654
size173,154
Simon Johnston (johnstonskj)

documentation

https://docs.rs/jemmy/

README

Package rust-jemmy

This package provides a coherent set of macros that manually generate accessor methods for fields in structures and variants in enums.

Apache-2.0 License MIT License Rust Workflow Security Audit Workflow Coverage Status Stargazer Count

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 initializer, getter and setter methods for the number_on_street and street_1 fields. And generates getter, setter (value) and un-setter (None) methods for the street_2 field.

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.

# 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.
      2. into; will generate a setter method that takes a parameter of type Into<T> rather than the typical T.
      3. 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

Macro field name keywords type generated signature
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

Macro variant name keywords type generated signature
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
Commit count: 0

cargo fmt