Crate jemmy

Crate jemmy 

Source
Expand description

This package provides a coherent set of manual accessor macros.

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>.

In general most users will use the combination macros such as with_get_and_set or get_set_and_unset; however, as these are directly built upon the individual accessor macros get, set, unset, with, and so forth it becomes easy to customize the set of methods a type provides.

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 accessors for the fields of a structure. This will provide initializers, getters and setters for the number_on_street and street_1 fields. A getter, setter (value) and unsetter (None) will be provided 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);
}

Typically here’s the constructor rules of thumb:

  1. If an instance can be generated by default (actually Default) it should.
  2. If not, or for explicit construction, anything required for construction should be a parameter to a new or new_ associated function that either returns Self or Result<Self, Error>.
  3. Optional things that initialize an instance before use but after construction should have a with_ method.
  4. Anything else should have a getter and setter (and maybe un-setter) method.

One way to combine a builder-like pattern into a type rather than have a separate type (if doing so adds no significant value) is to separate the notion of construction and initialization as the list above does. Thus, construction is the process of creating an instance, initialization ensures that instance is in a valid state and ready to use. For example, in the following the construction process does not raise errors because all it does is verifies the existence of a vehicle. The initialization process on the other hand may result in errors.

let car: Car = Default::default()
    .with_vin(MY_CAR_VEHICLE_ID_NUMBER),
    .with_fuel(Capacity::Full),
    .initialize()?;

assert_eq!(car.vin(), MY_CAR_VEHICLE_ID_NUMBER);
assert_eq!(car.make(), "Subaru");

§Example 2 - Enums

The following shows the basics of the macros for generating accessors for the variants of an enum. For each variant an is_variant predicate and as_variant cast methods are provided.

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 [, function_name] => [ field_name, ] [ keywords ] [ Type ])
  2. (viz Variant [, function_name] [ => Type ])

The elements of these forms are described below.

  1. viz; the vizibility specifier for the generated method.
  2. for field macros:
    1. Name; the public name of the field, this will be the core name of the method with any prefix/suffix required.
    2. function_name; (optional) where the method name needs to be overridden on a per-method basis this allows for the specification of the core name of the method.
    3. field name; (optional) when the visible name of the field is different from its field name you may specify both.
    4. 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.
    5. 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. Variant; the variant’s identifier within the enum.
    2. function_name; (optional) where the method name needs to be overridden on a per-method basis this allows for the specification of the core name of the method.
    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. value; TBD (const).
    4. Type; (optional) the type of any value of the variant.

Modules§

field
Macros for struct field access.
variant
Macros for enum variant access.

Macros§

as_variant
Generate a safe cast method for variant-associated data.
get
Generate a getter method for a field within a structure.
get_and_set
Generate get and set for a struct field.
get_mut
Generate a mutable getter method for a struct field.
get_set_and_unset
Generate get, set, and unset for an optional struct field.
impl_from_for_variant
Generate an implementation of the standard From trait to construct a new enum with the provided variant value.
is_as_variant
Generate both is_variant and as_variant for an enumeration variant.
is_variant
Generate a predicate function that returns true if the instance of the corresponding enumeration is of the given variant.
set
Generate a setter method for a field within a structure.
unset
Generate an un-setter method for an optional struct field.
with
Generate a builder style initializer method for a struct field.
with_get_and_set
Generate with, get and set for a struct field.
with_get_set_and_unset
Generate with, get, set, and unset for an optional struct field.