macro_rules! from_str_newstring {
    ($new_name:ident, $closure:expr) => { ... };
    ($new_name:ident, $closure:expr; $( $other:ident ),*) => { ... };
    ($new_name:ident, $closure:expr, $error:ty) => { ... };
    ($new_name:ident, $closure:expr, $error:ty; $( $other:ident ),*) => { ... };
}
Expand description

This macro takes a new type identifier and a parse function to produce a new type. The parse function must take the form fn(&str) -> Result<String, Err>, this is called from within the FromStr::from_str function to actually parse the string, and in doing so potentially returning an altered form if necessary.

In this macro the implementation of T::is_valid calls FromStr::from_str to perform the validity check.

An optional parameter for this macro allows the implementation to override the default error type, (), used in the implementation of FromStr allowing more detail to be provided on the validation failure.

Examples

This creates a new string type which only allows for uppercase characters.

fn parse_uppercase_only(s: &str) -> Result<String, ()> {
    if s.chars().all(|c|c.is_uppercase()) {
        Ok(s.to_string())
    } else {
        Err(())
    }
}

from_str_newstring!(OnlyUpperCase, parse_uppercase_only);

assert!(!OnlyUpperCase::is_valid("hello"));
assert!(OnlyUpperCase::from_str("hello").is_err());

assert!(OnlyUpperCase::is_valid("HELLO"));
assert!(OnlyUpperCase::from_str("HELLO").is_ok());
assert_eq!(OnlyUpperCase::from_str("HELLO").unwrap().to_string(), String::from("HELLO"));

In the following our new string type also derives serde attributes for serialization.

use serde::{Deserialize, Serialize};

fn parse_uppercase_only(s: &str) -> Result<String, ()> {
    if s.chars().all(|c|c.is_uppercase()) {
        Ok(s.to_string())
    } else {
        Err(())
    }
}

from_str_newstring!(OnlyUpperCase, parse_uppercase_only; Deserialize, Serialize);