# rust-range-check [![range-check on crates.io](http://meritbadge.herokuapp.com/range-check)](https://crates.io/crates/range_check) [![Build status](https://travis-ci.org/ogham/rust-range-check.svg?branch=master)](https://travis-ci.org/ogham/rust-range-check) This is a little library for early returns with range and bounds checking. It works with Rust’s standard `Range` types. ### [View the Rustdoc](https://docs.rs/range_check) # Installation This crate works with [Cargo](https://crates.io). Add the following to your `Cargo.toml` dependencies section: ```toml [dependencies] range_check = "0.2" ``` # Stability This crate requires the `collections_range` feature, which was stabilised in Rust 1.28.0. # Examples ## Range checking in the stdlib Rust’s standard library allows you to test whether a range contains a specified value: ```rust // Range checking with std::ops assert_eq!((0..24).contains(&23), true); assert_eq!((0..24).contains(&24), false); ``` For more information, see the [official Rust documentation for `std::ops::RangeBounds`](https://doc.rust-lang.org/std/ops/trait.RangeBounds.html). ## Range checking with this crate The `range_check` crate provides the `Check` trait that has a function `check_range`, which returns a `Result` instead of a `bool`. If the value exists within the range, it will return the value as an `Ok` variant: ```rust use range_check::Check; assert_eq!(24680.check_range(1..99999), Ok(24680)); ``` If the value does _not_ exist within the range, it will be returned inside an `OutOfRangeError` error variant: ```rust use range_check::Check; assert_eq!(24680.check_range(1..9999).unwrap_err().to_string(), "value (24680) outside of range (1..9999)"); ``` ## Failing early if a value is outside a range When testing multiple values, it can sometimes be helpful to automatically return when one of them is outside a range. In this example, we use the `?` operator to return early: ```rust use range_check::{Check, OutOfRangeError}; struct Clock { hour: i8, minute: i8, } impl Clock { fn new(hour: i8, minute: i8) -> Result> { Ok(Clock { hour: hour.check_range(0..24)?, minute: minute.check_range(0..60)?, }) } } assert!(Clock::new(23, 59).is_ok()); assert!(Clock::new(23, 60).is_err()); assert!(Clock::new(24, 00).is_err()); ``` It becomes a problem when the values being tested are of different types, as there can only be one type as the error `Result` from the function. As long as the types can be converted using the `From` trait, you can convert the error using the `OutOfRangeError::generify` function. In the first call in this example, we convert the error from containing an `i8` to an `i16`: ```rust use range_check::{Check, OutOfRangeError}; struct Clock { second: i8, millisecond: i16, } impl Clock { fn new(second: i8, millisecond: i16) -> Result> { Ok(Clock { second: second.check_range(0..60).map_err(OutOfRangeError::generify)?, millisecond: millisecond.check_range(0..1000)?, }) } } assert!(Clock::new(45, 576).is_ok()); assert!(Clock::new(49, 23456).is_err()); assert!(Clock::new(61, 0).is_err()); ```