# Deprecation notice The `fluent_validator` crate has been yanked. It is superceded by the [assayer](https://crates.io/crates/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](https://github.com/killercup/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: ```rust use fluent_validator::Error as FluentValidatorError; impl Validator for Vec { fn validate(value: Vec) -> Result { 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): ```rust impl Validator for Base64ByteString { fn validate(value: String) -> Result { 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: ```rust impl> Validator for HexByteString { fn validate(value: T) -> Result { 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: ```rust let hex_value = "123456"; let base_64_value = "123456"; // Method syntax let hex_result1 = hex_value.validate::(); let base_64_result1 = base_64_value.validate::(); // Function syntax let hex_result2 = Validate::(hex_value); let base_64_result2 = Validate::(base_64_value); ```