Skip to content

Nutype v0.6.0 - const_fn and into_iterator

Choose a tag to compare

@greyblake greyblake released this 02 Feb 17:23
· 39 commits to master since this release
93f4bf5

What is nutype?

Nutype is a proc macro that adds sanitizatio_ and validation to newtypes, ensuring values always pass checks, even with serde deserialization.

Changes in v0.6.0

  • [FEATURE] You can now instantiate types in a const context if they are declared with the const_fn flag.
  • [FEATURE] You can now derive IntoIterator for types wrapping inner types that implement IntoIterator.
  • [FIX] &'a str is now supported as an inner type.
  • [BREAKING] The fallible ::new() constructor has been removed (it was deprecated in 0.4.3).

Const functions

The #[nutype] macro can now accept the const_fn flag, which instructs it to generate const fn new() / const fn try_new() functions. This allows you to create instances in a const context:

use nutype::nutype;

#[nutype(
    const_fn,
    validate(greater_or_equal = -1.0, less_or_equal = 1.0)
)]
struct Correlation(f64);

// Since Result::unwrap() is not yet supported in a const context, we need to handle the result manually:
const ZERO_CORRELATION: Correlation = match Correlation::try_new(0.0) {
    Ok(c) => c,
    Err(_) => panic!("Invalid Correlation value"),
};

Because manually unwrapping in a const context can be tedious, you can use a helper macro like the one below (not part of nutype):

macro_rules! nutype_const {
    ($name:ident, $ty:ty, $value:expr) => {
        const $name: $ty = match <$ty>::try_new($value) {
            Ok(value) => value,
            Err(_) => panic!("Invalid value"),
        };
    };
}

nutype_const!(ZERO_CORRELATION, Correlation, 0.0);

IntoIterator

Types that wrap a collection can now derive IntoIterator. This automatically provides both a consuming iterator (impl IntoIterator for T) and an iterator over references (impl IntoIterator for &T).

Example:

use nutype::nutype;

#[nutype(derive(IntoIterator))]
struct Names(Vec<String>);

fn main() {
    let names = Names::new(vec![
        "Alice".to_string(),
        "Bob".to_string(),
    ]);

    // Iterate over references
    for name in &names {
        println!("{}", name);
    }

    // Iterate over owned values (consuming iterator)
    for name in names {
        println!("{}", name);
    }
}