fluent_validator 0.1.2

Crate renamed & superceded by assayer crate. Please check > https://crates.io/crates/assayer
Documentation

Deprecation notice

The fluent_validator crate has been yanked. It is superceded by the assayer crate, with the same zero-overhead implementation, but with ref, mut ref and move validators as well as full documentation.

Original documentation

fluent_validator was created to allow you to specify a set of validation rules in either an imperative or a fluent (chained-method functional) style, while taking full advantage of Rust's compile-time optimizations.

** Quick Start **

  1. Add fluent_validator to your Cargo.toml [dependencies] section.
    • If you aren't already using cargo edit, you should be. With it installed, just type cargo add fluent_validator from the command line to complete this step.
  2. Add extern crate fluent_validator; to your crate's root file (either lib.rs or main.rs).
  3. Define your validator (see below)
  4. Call you validator for fun and profit! (see below)

*** Simple validator scenario *** Imagine you are writing a command line program which requires a single argument when invoked. You would define your validator to ensure exactly one argument is provided. This means that the number of args must be 2 (under most common envrionments, the OS supplies name of the app itself automatically as the very first argument). Let's assume, for simplicity, that you have collected the command line arguments passed to your application, ensured they are valid UTF-8 and have stored them as a series of elements in a Vec:

use fluent_validator::Error as FluentValidatorError;

impl Validator<bool> for Vec<String> {
    fn validate(value: Vec<String>) -> Result<bool, FluentValidatorError> {
        Ok(value)
        
            //Determine if the vector received contains exactly two elements
            .and_then(|v| match v.len() == 2 {
                true => Ok(v),
                false => Err(FluentValidatorError::InvalidSize),  //Or add your own custom `enum` to `Error` in `src/error.rs`
            })
            
            //value passes validation
            .and_then(|v| Ok(v))

*** Sample 3-stage validator ***

Mutating validators require owning datatypes (eg. String):

impl Validator<String> for Base64ByteString {
    fn validate(value: String) -> Result<String> {
        Ok(value)

            //value contains data?
            .and_then(|v| match !v.is_empty() {
                true => Ok(v),
                false => Err(Error::EmptyValue(VAL_ERR_EMPTY_VALUE.to_string())),
            })

            //ensure value defines whole bytes (contains a multiple-of-three number of base-64 digits)
            .and_then(|v| v += "=="[..v.len() % 3])

            //value contains only valid base-64 characters?
            .and_then(|v| match v.chars()
                                 .all(|c| c.is_hex_char()) {
                true => Ok(v),
                false => Err(Error::IllegalValue((VAL_ERR_ILLEGAL_BASE_64_DIGIT.to_string()))),
            })

            //value passes validation
            .and_then(|v| Ok(v))
    }
}

Non-mutating validators can use any datatypes:

impl<T: AsRef<str>> Validator<T> for HexByteString {
    fn validate(value: T) -> Result<T> {
        Ok(value.as_ref())

            //value contains data?
            .and_then(|v| match !v.is_empty() {
                true => Ok(v),
                false => Err(Error::EmptyValue(VAL_ERR_EMPTY_VALUE.to_string())),
            })

            //value defines whole bytes (contains an even number of hex digits)?
            .and_then(|v| match v.len() % 2 == 0 {
                true => Ok(v),
                false => Err(Error::InvalidSize(VAL_ERR_INVALID_SIZE.to_string())),
            })

            //value contains only valid hexadecimal characters?
            .and_then(|v| match v.chars()
                                 .all(|c| c.is_hex_char()) {
                true => Ok(v),
                false => Err(Error::IllegalValue((VAL_ERR_ILLEGAL_HEX_DIGIT.to_string()))),
            })?;
        Ok(value)
    }
}

Invoke validators as follows:

let hex_value = "123456";
let base_64_value = "123456";

// Method syntax
let hex_result1 = hex_value.validate::<HexByteString>();
let base_64_result1 = base_64_value.validate::<Base64ByteString>();

// Function syntax
let hex_result2 = Validate::<HexByteString>(hex_value);
let base_64_result2 = Validate::<Base64ByteString>(base_64_value);