Accord is a library for validating data according to rules like length, contains, range and either.
Accord is two fold, the first part being a set of validator-functions that
for example tests that a String
has a minimum of 5 characters or that an i32
is either 10 or 20, and the second part being the rules!
macro which allows you
to run a set of validators on a single piece of data, or a whole collection of data
and get back a set of errors which explains exactly what is wrong. The errors can
easily be serialized using Serde and then be used in for example a REST API to
report to the user which of the data the user posted contains illegal values.
See the Rocket example for how to use Accord with Rocket to validate JSON input and return explanations for any occuring error as JSON which then can be parsed by the requesting application and shown to the user to guide them in how to fix their input values according to the applications rules.
Error messages uses numbered placeholders meaning that an error message could
be "Must not be less than %1." with an accompanien list [5]
, which makes
it easy to translate "Must not be less than %1." without having to deal with the
variable value 5.
#[macro_use]
extern crate accord;
extern crate serde;
extern crate serde_json;
use accord::{Accord, Result as AccordResult, Error, MultipleError, MultipleInvalid};
use accord::validators::{length, contains, range};
struct Account {
pub name: String,
pub email: String,
pub age: i8,
}
impl Accord for Account {
fn validate(&self) -> AccordResult {
rules!{
"name" => self.name => [length(1, 64)],
"email" => self.email => [length(5, 64), contains("@"), contains(".")],
"age" => self.age => [range(12, 127)]
}
}
}
fn main() {
let account = Account {
name: "".to_string(),
email: "test".to_string(),
age: 11,
};
// You can use the `rules!` macro on any value.
// This way of using the the `rules!` macro returns a
// `Result<(), Error>`.
let _ = rules!(account.name, [length(1, 64)]);
let _ = rules!(account.email, [length(5, 64), contains("@"), contains(".")]);
let _ = rules!(account.age, [range(12, 127)]);
// You can also use the collection form of the `rules!` macro
// again using any value you'd like.
// This way of using the `rules!` macro returns a
// `Result<(), MultipleError>`. Notice the string slices that has
// been appended to the lines from last example. These string slices
// are called tags and are used to distingues between the sets of errors
// that are returned.
let _ = rules!{
"name" => account.name => [length(1, 64)],
"email" => account.email => [length(5, 64), contains("@"), contains(".")],
"age" => account.age => [range(12, 127)]
};
// And finally, since our `Account` has implemented the
// `Accord` trait, we can simply do the following, which once
// again returns `Result<(), MultipleError>`, which we then
// serialize to JSON using Serde and print:
if let Err(multiple_error) = account.validate() {
println!("Errors as json: {}",
serde_json::to_string(&multiple_error).unwrap());
} else {
println!("No errors occured");
}
}
- Examples: Usage examples are available in the examples/ directory
- API Documentation: Documentation generated from the source code, comments and examples
Building: cargo build
Testing: cargo test
Make sure you have an up-to-date version of rust nightly installed.
Building: cargo build
Testing: cargo test
You can add --features FEATURES TO ENABLE
to both cargo build
and cargo test
to build or test unstable features. The unstable features currently supported are:
inclusive_range
RFC#1192 which enables one to use thelength
andrange
validators with inclusive ranges instead ofa, b
-variables, as in the example above. An example crate using inclusive ranges can be found here.
You can also use make for doing more stuff in a simpler way. The Makefile requires that you are using Rust via rustup.
make
will build and test Accord and all examples on both stable and nightly, on nightly both with and without unstable featuresmake build
will build everything on both stable and nightlymake build-stable
will build everything on stablemake build-unstable
will build everything on nightly with and without unstable featuresmake build-examples
will build examples on both stable and nightlymake build-stable-examples
make build-unstable-examples
make build-stable-example-<NAME-OF-STABLE-EXAMPLE>
make build-unstable-example-<NAME-OF-UNSTABLE-EXAMPLE>
make test
will test everything on both stable and nightly, on nightly with and without unstable featuresmake test-stable
will test everything on stablemake test-unstable
will test everything on nightly with and without unstable featuresmake test-examples
will test examples on both stable and nightlymake test-stable-examples
make test-unstable-examples
make test-stable-example-<NAME-OF-STABLE-EXAMPLE>
make test-unstable-example-<NAME-OF-UNSTABLE-EXAMPLE>
Contributions are absolutely, positively welcome and encouraged! Contributions come in many forms. You could:
- Submit a feature request or bug report as an issue.
- Ask for improved documentation as an issue.
- Contribute code via pull requests.
To keep a high standard of quality, contributed code must be:
- Commented: Public items must be commented.
- Documented: Exposed items must have rustdoc comments with examples, if applicable.
- Styled: Your code should be
rustfmt
'd when possible. - Simple: Your code should accomplish its task as simply and idiomatically as possible.
- Tested: You must add (and pass) convincing tests for any functionality you add.
- Focused: Your code should do what it's supposed to do and nothing more.
All pull requests are code reviewed and tested by the CI. Note that unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in Accord by you shall be MIT License without any additional terms or conditions.
Thanks to Rocket for showing how to form a great contributing-section.
Accord is Copyright (c) 2017 Christoffer Buchholz. It is free software, and may be redistributed under the terms specified in the LICENSE file.