Nutype 0.4.2 with Arbitrary support!
Serhii Potapov April 10, 2024 #rust #macro #newtype #nutype #arbitrary #fuzzingI'm thrilled to unveil the latest update, Nutype 0.4.2, now available for the community. Dive into the details on GitHub.
About Nutype
Nutype is an innovative Rust crate designed to revolutionize the standard newtype pattern. By incorporating procedural macros, it introduces features such as sanitization and validation, ensuring that values are only instantiated once they satisfy specific, predefined criteria.
Exciting New Feature: Arbitrary
With the release of Nutype 0.4.2, we've introduced the ability to derive the Arbitrary trait, a powerful tool for generating pseudo-random structures of a given type. This functionality is crucial for fuzzing and property-based testing, expanding the utility of Nutype. For an in-depth exploration, check out my previous article, Property-Based Testing in Rust with Arbitrary.
What sets this feature apart is its intelligent derived implementation of Arbitrary, which respects the established validation rules. Here’s how it works:
use nutype::nutype;
use arbtest::arbtest;
use arbitrary::Arbitrary;
#[nutype(
derive(Arbitrary, AsRef),
sanitize(trim),
validate(
not_empty,
len_char_max = 100,
),
)]
pub struct Title(String);
fn main() {
arbtest(|u| {
// Generate an arbitrary valid Title
let title = Title::arbitrary(u)?;
// The inner string is guaranteed to be non-empty
assert!(!title.as_ref().is_empty());
// The inner string is guaranteed not to exceed 100 characters
assert!(title.as_ref().chars().count() <= 100);
Ok(())
});
}
This functionality extends to integer and float-based types as well:
#[nutype(
derive(Arbitrary, AsRef),
validate(
finite,
greater_or_equal = -1.0,
less_or_equal = 1.0,
),
)]
pub struct PearsonCorrelation(f64);
fn main() {
arbtest(|u| {
let correlation = PearsonCorrelation::arbitrary(u)?;
assert!(correlation.as_ref().is_finite());
assert!(*correlation.as_ref() >= -1.0);
assert!(*correlation.as_ref() <= 1.0);
Ok(())
});
}Understanding Limitations
While Nutype 0.4.2 expands possibilities, certain scenarios might limit the derivation of Arbitrary for valid newtypes, resulting in a compilation error. This occurs in cases like custom validation logic defined with the predicate = attribute:
#[nutype(
derive(Arbitrary, AsRef),
validate(
predicate = |x: &i32| x % 2 == 0,
),
)]
pub struct Even(i32);
Error:
error: Cannot derive trait `Arbitrary` for a type with `predicate` validator
--> dummy/src/main.rs:5:1
|
5 | / #[nutype(
6 | | derive(Arbitrary, AsRef),
7 | | validate(
8 | | predicate = |x: &i32| x % 2 == 0,
9 | | ),
10 | | )]
| |__^
|Other changes
For a comprehensive overview of all enhancements and modifications, please refer to the release notes.