1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
//! This is a little library that helps with range and bounds checking. It works //! with Rust’s standard `Range` types. //! //! //! Range checking in the stdlib //! ---------------------------- //! //! Rust’s standard library allows you to test whether a range contains //! a specified value: //! //! ``` //! // 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.Check.html) trait that has a function //! `check_range`, which returns a [`Result`](type.Result.html) instead of a `bool`. //! //! If the value exists within the range, it will return the value as an //! `Ok` variant: //! //! ``` //! 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`](struct.OutOfRangeError.html) error variant: //! //! ``` //! 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: //! //! ``` //! use range_check::{Check, OutOfRangeError}; //! //! struct Clock { //! hour: i8, //! minute: i8, //! } //! //! impl Clock { //! fn new(hour: i8, minute: i8) -> Result<Clock, OutOfRangeError<i8>> { //! 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`](https://doc.rust-lang.org/std/convert/trait.From.html) //! trait, you can convert the error using the //! [`OutOfRangeError::generify`](struct.OutOfRangeError.html#method.generify) //! function. In the first call in this example, we convert the error from //! containing an `i8` to an `i16`: //! //! ``` //! use range_check::{Check, OutOfRangeError}; //! //! struct Clock { //! second: i8, //! millisecond: i16, //! } //! //! impl Clock { //! fn new(second: i8, millisecond: i16) -> Result<Clock, OutOfRangeError<i16>> { //! 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()); //! ``` #![crate_name = "range_check"] #![crate_type = "rlib"] #![crate_type = "dylib"] #![warn(missing_copy_implementations)] #![warn(missing_debug_implementations)] #![warn(missing_docs)] #![warn(trivial_casts, trivial_numeric_casts)] #![warn(unused_qualifications)] #![warn(unused_results)] mod check; pub use check::{Check, OutOfRangeError}; mod bounds;