Skip to main content

value

Macro value 

Source
macro_rules! value {
    ($($value:tt)+) => { ... };
}
Available on crate feature recursive only.
Expand description

Construct a Value from a Rust-like constructor expression.

With this macro it is possible to construct values that have the same structure as actual types like structs, enums, tuples, or even primitive types. It is not necessary to declare the types in advance.

§Syntax

The syntax is more or less the same as Rust’s constructor expressions for structs, enums, and tuples. The name of structs can be omitted. Enum variants must be written in the form Foo::Bar (specifying only the variant is not supported, even if the variant is imported).

Literals for bool, char, number, and strings can be written similar to Rust literals with some minor differences: a &str does not have to be converted to a String (this is done automatically), and brackets are used for sequences, not arrays. Each number literal should contain the type, e.g., 42_u64, 1.2_f32, etc. This is necessary because the macro cannot infer the type of number literals.

The following example gives an overview of the syntax, with elements of various types.

use asserting::prelude::*;

let value = value!({                          // a struct
    foo: 2.3_f64,                             // a float literal
    bar: {                                    // an embedded struct
        baz: "alpha",                         // a string literal
        qux: 123_i16,                         // an integer literal
        corge: true,                          // a boolean literal
    },
    grault: Sample::Two("beta", -456_i64),    // a tuple variant
    waldo: (123_u8, 234_u8, 56_u8),           // a tuple
    fred: ["alpha", "beta", "gamma"],         // a sequence
    quux: #{ 'a' => 1, 'b' => 2, 'c' => 3},   // a map
    thud: Named(0.8_f32),                     // a tuple struct
});

Variables in scope can be referenced inside the value!-macro.

use asserting::prelude::*;

let one = 1;
let two = 2;
let three = 3;

let value = value!([one, two, three]);

assert_eq!(format!("{value:?}"), "[1, 2, 3]");

Expressions can be used inside the value!-macro as well:

use asserting::prelude::*;

let value = value!(Sum(13_i16 + 17_i16));

assert_eq!(format!("{value:?}"), "Sum(30)");

§Structs

Structs can be constructed on the fly, without prior declaration of a type. In asserting they are called “anonymous structs”. The name of a struct can be omitted.

let value = value!({
    name: "Silvia",
    age: 25_u8,
});

The name of a struct to be constructed can be specified as by the usual syntax in Rust.

let value = value!(Person {
    name: "Silvia",
    age: 25_u8,
});

Note: The name of a struct is not compared in the field-by-field recursive comparison mode.

§Tuples

A tuple is constructed using parenthesis as in plain Rust.

let value = value!((42_u64, "alpha", true));

§Enums-Variants

Example for constructing a value of unit variant:

let value = value!(Foo::Bar);

Example for constructing a value of tuple variant:

let value = value!(Foo::Bar(-1.3_f32));

Example for constructing a value of struct variant:

let value = value!(Foo::Bar { left: "alpha", right: -123_i16 });

§Sequences

A sequence is constructed by enclosing a list of values inside brackets. In the following example we construct a sequence of chars.

let value = value!(['a', 'b', 'c']);

§Maps

A map starts with #{ and ends with }. An association between a key and a value is separated by =>. Multiple key/value-pairs are separated by ,.

let value = value!(#{
    'a' => 1,
    'b' => 2,
    'c' => 3,
});

§Primitive types

TypeExample
booltrue or false
char'a'
f321.2_f32
f641.2_f64
str"alpha"
String"alpha"
i8-12_i8
i16-12_i16
i32-12_i32
i64-12_i64
i128-12_i128
u812_i8
u1612_i16
u3212_i32
u6412_i64
u12812_i128

Note: isize and usize are not supported by serde. Therefore, isize values are converted to i64 or i128 and usize values are converted to u64 or u128.

§Limitations

§No Field Init Shorthand

When initializing a struct field with the value of a variable, the field init shorthand is not supported. Even if the field has the same name as the variable, the variable must be repeated after the colon.

Instead of using the field init shorthand, which does not compile:

use asserting::prelude::*;

let bar = "alpha";

let value = value!(Foo { bar });

using the normal (verbose) syntax works:

use asserting::prelude::*;

let bar = "alpha";

let value = value!(Foo { bar: bar });

assert_eq!(value, value!(Foo { bar: "alpha" }));

§No Unit Structs

This macro does not support unit structs. Unit structs interfere with identifiers captured from the environment. We decided that capturing variables from the environment of the macro is more valuable than unit structs.