Skip to main content

format

Attribute Macro format 

Source
#[format]
Expand description

Derive Printable and Parsable for Rust types. Use this for types other than Op, Type and Attributes.

A format string can be specified as an argument to the macro, to customize the syntax. Without a format string, the default syntax is used. For enums, no format string is allowed on the enum itself, but it is allowed on its variants.

Primarily, the following two are used to refer to fields in a struct or tuple:

  1. A named variable $name specifies a named struct field.
  2. An unnamed variable $i specifies the i’th field of a tuple struct.

Struct (or tuple) fields that are either Option or Vec (or an array) must to be specified using the opt and vec directives respectively (i.e., a format string is mandatory).

The opt directive takes one mandatory argument, a variable specifying the field name with type Option. It also supports optional label and delimiters directives:

  1. label($name): uses name : as a prefix for the optional value.
  2. delimiters(open, close): wraps the optional value with the given delimiters.

The vec directive takes two arguments, the first is a variable specifying the field name with type Vec (or array) and the second is another directive to specify a ListSeparator.

The following directives are supported:

  1. NewLine: takes no argument, and specifies a newline to be used as list separator.
  2. CharNewline(`c`): takes a single character argument that will be followed by a newline.
  3. Char(`c`): takes a single character argument that will be used as separator.
  4. CharSpace(`c`): takes a single character argument that will be followed by a space.

Generic structs and enums are supported. The macro preserves generic parameters on the generated Printable and Parsable impls, but it does not synthesize trait bounds. Any generic field that is parsed or printed through the format must therefore carry explicit bounds on the type itself. In practice, this usually means a bound like T: Printable + Parsable<Arg = (), Parsed = T>.

Examples:

  1. Derive for a struct, with no format string (default format): (Note that the field u64 has both Printable and Parsable implemented).
use pliron::derive::format;
#[format]
struct IntWrapper {
   inner: u64,
}
  1. An example with a custom format string:
use pliron::derive::format;
#[format("`BubbleWrap` `[` $inner `]`")]
struct IntWrapperCustom {
  inner: u64,
}
  1. An example for an enum (custom format strings are allowed for the variants only).
use pliron::derive::format;
use pliron::{builtin::types::IntegerType, r#type::TypedHandle};
#[format]
enum Enum {
    A(TypedHandle<IntegerType>),
    B {
        one: TypedHandle<IntegerType>,
        two: u64,
    },
    C,
    #[format("`<` $upper `/` $lower `>`")]
    Op {
        upper: u64,
        lower: u64,
    },
}
  1. An example with Option and Vec fields
use pliron::derive::format;
#[format("`<` opt($a) `;` vec($b, Char(`,`)) `>`")]
struct OptAndVec {
   a: Option<u64>,
   b: Vec<u64>,
}
  1. An example with a generic field and explicit bounds:
use pliron::derive::format;
use pliron::{parsable::Parsable, printable::Printable};

#[format]
struct Wrapper<T>
where
    T: Printable + Parsable<Arg = (), Parsed = T>,
{
    value: T,
}
  1. An example with an optional field using label and delimiters in opt:
use pliron::derive::format;
#[format("`<` opt($a, label($value), delimiters(`(`, `)`)) `>`")]
struct OptionalField {
   a: Option<u64>,
}