macro_rules! extend {
    {
        $(#[$meta:meta])*
        $vis:vis $wrapper:ident: $inner:ty;
        $(adjust $adjust:expr;)?
        $(ensure $ensure:expr;)?
        $(validate($err:ty) $validate:expr;)?
        $(plugins: [$($plugin:path),+ $(,)?];)?

    } => { ... };
    {
        $inner:ty;
        $(adjust $adjust:expr;)?
    } => { ... };
    {
        $inner:ty;
        $(adjust $adjust:expr;)?
        ensure $ensure:expr;
    } => { ... };
    {
        $inner:ty;
        $(adjust $adjust:expr;)?
        validate($err:ty) $validate:expr;
    } => { ... };
}
Expand description

Convenience macro that creates a Newtype wrapper struct that implements Wrapper and extends another Wrapper.

The usage of the macro is identical to the define!, so check out it’s documentation to learn more. The only difference is the fact that the inner type specified in the type signature must implement Wrapper.

The created struct will inherit the inner type of that another wrapper, and also will run that another wrapper’s adjustment and validation closures before it’s own adjustment and validation closures. For example:

use prae::Wrapper;

prae::define! {
    pub Text: String;
    adjust |text| *text = text.trim().to_owned();
    ensure |text| !text.is_empty();
}

prae::extend! {
    #[derive(Debug)]
    pub Sentence: Text;
    ensure |sentence: &String| {
        // Note that `sentence` is a `&String`, not `&Text`!
        // It's value is already trimmed and checked for emptiness.
        // Now we only need to check conditions that are important
        // for the new type
        sentence.ends_with(&['.', '!', '?'][..])
    };
}

// It works
let sentence = Sentence::new("   My sentence! ").unwrap();
assert_eq!(sentence.get(), "My sentence!");

// Doesn't pass the validation of `Text`
assert!(Sentence::new("   ").is_err());

// Doesn't pass the validation of `Sentence`
assert!(Sentence::new("Without punctuation").is_err());