Crate newstr[][src]

Expand description

This crate provides simple macros that generate String based new types. The two primary macros implement the validity rules for the new type by either 1) providing a predicate that is used by the is_valid associated function, or 2) providing a function to parse and return a string which is then called by FromStr::from_str.

Both of these methods produce a new struct, with the following:

  1. An associated predicate function is_valid that returns true if the string provided would be a valid value for the type.
  2. This type derives implementations of Clone, Debug, PartialEq, PartialOrd, Eq, Ord, and Hash.
  3. An implementation of Display for T that simply returns the inner value.
  4. An implementation of From<T> for String.
  5. An implementation of Deref for T with the target type str.
  6. An implementation of FromStr.

Additional user-required traits can also be added to the macro to be derived by the implementation.

Example

The following example constructs a new string type with the macro is_valid_newstring that implements an Identifier value. This value must be ASCII, alphanumeric, the ‘_’ character and must not be empty.

use std::fmt::{Display, Formatter};
use std::str::FromStr;
use std::ops::Deref;

fn is_identifier_value(s: &str) -> bool {
    !s.is_empty() && s.chars().all(|c| c.is_ascii_alphanumeric() || c == '_')
}

is_valid_newstring!(Identifier, is_identifier_value);

assert!(!Identifier::is_valid(""));
assert!(!Identifier::is_valid("hi!"));
assert!(!Identifier::is_valid("hello world"));
assert!(!Identifier::is_valid("9.99"));

assert_eq!(
    Identifier::from_str("hi").unwrap().to_string(),
    String::from("hi")
);
assert_eq!(
    Identifier::from_str("hello_world").unwrap().to_string(),
    String::from("hello_world")
);

Dependencies

In the example above you can see the necessary use-statements for the trait implementations the macros generate. Unless you use regex_is_valid there are no crate dependencies; if you do you will need to add lazy_static and regex dependencies.

If the macros in this crate take on addition dependencies or provide new implementations the set of use statements may change which will break consumer builds. To avoid this another macro, use_required, will add any required use statements the consumer requires.

use_required!();

is_valid_newstring!(NotEmpty, |s: &str| !s.is_empty());

Macros

from_str_newstring

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.

is_valid_newstring

This macro takes a new type identifier and a predicate function to produce a new type. The predicate is called by T::is_valid and is then used in the implementation of FromStr to determine whether to return a new instance or error. As this is simply a boolean value and does not differentiate between reasons for invalidity the error type for FromStr is always ().

regex_is_valid

This macro takes a string that contains a regular expression will construct a new validity predicate that may be used by the is_valid_newstring macro. An optional second parameter provides a name for the new predicate function, overriding the default is_valid.

use_required

This macro expands to the set of use statements required by a consumer of either is_valid_newstring or from_str_newstring macros. This can be valuable over time if the implementationof these macros take on additional dependencies.