Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Attributes, Arguments, and Sub-Arguments

As mentioned in the Terminology section, FieldX provides the fxstruct macro to annotate structs and the fieldx attribute to adjust field parameters. Both accept arguments that can take one of the following forms:

  • Flag: A pure boolean keyword where its presence means true and its absence means false.

  • Keyword: Similar to a flag in that it represents a boolean value. However, it can also take a function-like form with a single argument, the off flag, which sets its value to false:

    #[fxstruct(sync(off))]
  • List or Function: A complex argument that accepts a comma-separated list of sub-arguments. The term "list" originates from the definitions of Rust procedural macro entities:

    #[fxstruct(builder(attributes_fn(allow(dead_code), opt_in)))]
  • Helper: A function-like argument bound to a method of the struct implementation. The method can either be generated by the fxstruct macro or defined by the user. Helpers share common arguments, such as a string literal defining the helper's name, its visibility (if applicable), a list of Rust attributes, a doc comment, and the off flag:

    #[fieldx(builder("set_foo", vis(pub(crate)), doc("Sets the foo field.")))]

The full list of provided arguments can be found in the FieldX documentation.

Struct- and Field-Level Arguments

See also: Terminology

Arguments for the struct-level fxstruct macro serve two purposes, depending on their semantics: they either specify the struct's behavior or parameters, or define default values for field-level arguments. In the following example, the field v3 opts out of being lazily initialized and instead uses a static default value:

#[fxstruct(lazy)]
struct MyStruct {
    v1: u32,
    v2: f32,
    #[fieldx(
        lazy(off),
        default("static default".to_string())
    )]
    v3: String,
}

Interestingly, the v3 field also provides an implicit default at the struct level! Normally, FieldX avoids generating unnecessary code, and the Default trait implementation is no exception. However, if a field is given a default, it is as if the default argument were specified at the struct level, as shown in this snippet:

#[fxstruct(lazy, default)]
struct MyStruct {
    v1: u32,
    v2: f32,
    #[fieldx(
        lazy(off),
        default("static default".to_string())
    )]
    v3: String,
}

This example also demonstrates how the same arguments can have different meanings at the struct and field levels. While lazy has a consistent semantics at both levels with the struct-level argument implicitly applied to all fields, the default argument behaves differently. At the struct level, it provides a new trait implementation, while at the field level, it assigns a default value. The syntax also differs: the struct-level default argument is just a keyword.

A more prominent example of the difference between struct-level and field-level is the builder argument. At the struct level, it generates a builder type and the builder() method. At the field level, it generates a builder method for the field. Both use the same syntax but support partially different lists of sub-arguments:

#[fxstruct(builder("MyStructBuilder", opt_in))]
struct MyStruct {
    v1: u32,
    #[fieldx(builder("set_v2", into))]
    v2: f32,
}