assert_none.rs
Overview
This file defines a Rust struct named StripAssertNoneStruct that leverages the derive_setters crate to automatically generate setter methods with special behaviors. The struct contains optional and non-optional fields, where setters enforce an invariant: attempting to set a field more than once triggers a runtime panic. This is achieved through the assert_none attribute combined with strip_option behavior.
The file also includes three unit tests that verify the correct behavior of the setters, specifically testing the enforcement of the "set only once" rule.
Struct: StripAssertNoneStruct
Purpose
StripAssertNoneStruct is designed to demonstrate and test the interaction of two derive_setters attributes:
strip_option: automatically unwrapsOption<T>values in setters, allowing the user to pass aTdirectly instead ofOption<T>.assert_none: panics if the setter is invoked on a field that is already set (i.e., notNone).
Definition
#[derive(Default, Setters, Debug, PartialEq, Eq)]
#[setters(strip_option, assert_none)]
struct StripAssertNoneStruct {
a: Option<u32>,
#[setters(strip_option = false)]
c: std::option::Option<u32>,
d: u32,
}
Derives:
Default: provides a default constructor where all fields are initialized toNoneor zero (d).Setters: generates setter methods with the specified behaviors.Debug,PartialEq,Eq: standard traits for formatting and comparison.
Struct fields:
a: Option<u32>— an optionalu32field withstrip_optionenabled.c: Option<u32>— optionalu32, but explicitly disablesstrip_optionon its setter.d: u32— a non-optionalu32field.
Attributes and Effects
#[setters(strip_option, assert_none)]on the struct applies to all fields unless overridden.Field
cdisablesstrip_option, so its setter expects anOption<u32>instead ofu32.The
assert_noneattribute on setters causes a panic if the field is already set (i.e., notNone), enforcing single assignment.
Generated Setter Methods
a(&self, value: u32) -> Self
Setter accepts au32(due tostrip_option) and setsatoSome(value). Panics ifawas previously set.c(&self, value: Option<u32>) -> Self
Setter accepts anOption<u32>(nostrip_option). Panics ifcwas previously set.d(&self, value: u32) -> Self
Setter accepts au32. Sincedis not anOption,assert_noneis not applicable here.
Usage Example
let s = StripAssertNoneStruct::default()
.a(3) // sets a = Some(3)
.c(Some(42)) // sets c = Some(42)
.d(7); // sets d = 7
Attempting to call .a(3) or .c(Some(3)) again on the same instance will panic, enforcing the "set once" rule.
Unit Tests
assert_none_must_not_panic_for_the_first_set
Purpose: Verify that the first call to setters with
assert_nonedoes not panic.Test: Construct a default instance and set fields
a,c, anddonce.Assertion: The resulting struct matches the expected values.
assert_none_panic_if_value_was_set
Purpose: Confirm that calling a setter twice on the same field (
c) panics.Test: Set
conce, then call.c(Some(3))again.Expected: Panic triggered on the second call.
assert_none_panic_if_value_was_set_for_stripped_option
Purpose: Confirm that calling a setter twice on the stripped option field (
a) panics.Test: Set
aonce with.a(1), then call.a(1)again.Expected: Panic triggered on the second call.
Interaction with Other Parts of the System
Uses the external crate
derive_settersto generate setters with advanced behaviors.Demonstrates integration of two features from this crate:
strip_option(derive_setters - Strip Option Feature)assert_none(derive_setters - Assert None Feature)
The struct and its generated methods can be used wherever enforcing single assignment semantics is desired, particularly useful in builder patterns or configuration structs.
Implementation Details
The
strip_optionfeature strips theOptionwrapper from the setter argument, simplifying calls by allowing directTvalues instead ofOption<T>.The
assert_nonefeature injects runtime checks into setters to panic if the field is already set, helping prevent unintended overwrites.The field-level override
#[setters(strip_option = false)]disables the strip behavior for fieldc, showing fine-grained control.
Mermaid Diagram
flowchart TD
A[StripAssertNoneStruct]
A -->|has| a[Option<u32> a]
A -->|has| c[Option<u32> c]
A -->|has| d[u32 d]
subgraph Setters
Sa["a(value: u32)"]
Sc["c(value: Option<u32>)"]
Sd["d(value: u32)"]
end
A --> Setters
Sa -->|assert_none + strip_option| A.a
Sc -->|assert_none only| A.c
Sd -->|no assert_none| A.d
subgraph Tests
T1[assert_none_must_not_panic_for_the_first_set]
T2[assert_none_panic_if_value_was_set]
T3[assert_none_panic_if_value_was_set_for_stripped_option]
end
Tests -->|test| Sa
Tests -->|test| Sc
This diagram illustrates the struct's fields and their corresponding setters, highlighting the application of assert_none and strip_option attributes, as well as the unit tests exercising these behaviors.