# `Ranges`
[![Docs][docs-badge]][docs-url]
[![Crates.io][crates-badge]][crates-url]
[![License][license-badge]][license-url]
[![Deps.rs][deps-badge]][deps-url]
[![Build Status][build-badge]][build-url]
[![Code Coverage][coverage-badge]][coverage-url]
[![Matrix][matrix-badge]][matrix-url]
[docs-badge]: https://docs.rs/ranges/badge.svg
[docs-url]: https://docs.rs/ranges
[crates-badge]: https://img.shields.io/crates/v/ranges.svg
[crates-url]: https://crates.io/crates/ranges
[license-badge]: https://img.shields.io/crates/l/ranges
[license-url]: LICENSE.md
[deps-badge]: https://deps.rs/repo/gitlab/bit-refined/ranges/status.svg
[deps-url]: https://deps.rs/repo/gitlab/bit-refined/ranges
[build-badge]: https://gitlab.com/bit-refined/ranges/badges/master/pipeline.svg
[build-url]: https://gitlab.com/bit-refined/ranges/commits/master
[coverage-badge]: https://gitlab.com/bit-refined/ranges/badges/master/coverage.svg
[coverage-url]: https://gitlab.com/bit-refined/ranges/commits/master
[matrix-badge]: https://img.shields.io/matrix/ranges:byter.dev.svg?server_fqdn=matrix.byter.dev&label=ranges%3Abyter.dev&logo=matrix&maxAge=3600
[matrix-url]: https://matrix.to/#/!VvXZulziYqsakYDyiN:byter.dev?via=byter.dev
`Ranges` is a generic replacement for the [core]/[std] range types.
[core]: https://doc.rust-lang.org/core/ops/index.html#structs
[std]: https://doc.rust-lang.org/std/ops/index.html#structs
[vector]: https://doc.rust-lang.org/alloc/vec/struct.Vec.html
## Overview
### `GenericRange`
This is the main replacement for [core]/[std] ranges with provided `From` implementations.
The only difference is, that `T` needs to implement `Domain` and consequently [`Ord`].
The `start` needs to be less or equal to `end` to uphold certain guarantees and allow for more optimization.
### `Ranges`
This is a [vector]-backed range/interval set storing generic ranges in a ordered and always disjoint fashion.
### `Domain`
This is the helper trait that defines the properties of a type and the domain it is in.
It is already implemented for all [primitive] integers, [`char`] and [`bool`]. Additionally there are implementations
using feature gates for [`noisy_float`] and [`num-bigint`].
The default implementation of this trait is written in a way, that continuous
types need no further code (except, if applicable, their min- and maximum).
Discrete-only methods panic by default and are never called by the
library if the `DISCRETE` constant is `false` (which it is by default).
[`From`]: https://doc.rust-lang.org/core/convert/trait.From.html
[`Ord`]: https://doc.rust-lang.org/core/cmp/trait.Ord.html
[primitive]: https://doc.rust-lang.org/core/primitive/index.html
[`char`]: https://doc.rust-lang.org/std/primitive.char.html
[`bool`]: https://doc.rust-lang.org/std/primitive.bool.html
[`noisy_float`]: https://crates.io/crates/noisy_float
[`num-bigint`]: https://crates.io/crates/num-bigint
## Examples
<small>More examples can be found in the [documentation][docs-url].</small>
##### GenericRange
- from [core]/[std] ranges:
```
use ranges::GenericRange;
let generic = GenericRange::from(1..5);
assert_eq!(generic.start_bound(), Bound::Included(&1));
assert_eq!(generic.end_bound(), Bound::Excluded(&5));
```
- overlapping union:
```
use ranges::{GenericRange, OperationResult};
let range = GenericRange::from(0..10);
let range2 = 5..=15;
assert_eq!(range | range2, OperationResult::Single((0..=15).into()));
```
##### Ranges
- find contained intersecting ranges:
```
use ranges::Ranges;
let ranges = Ranges::from(vec![0..5, 10..20, 25..30, 45..50]);
assert_eq!(ranges.find_intersecting_ranges(&(7..47).into()), Some((1, 3)));
```
- contains an item:
```
use ranges::Ranges;
let ranges = Ranges::from(vec![0..3, 5..10]);
assert!(ranges.contains(&2));
assert!(ranges.contains(&7));
assert!(!ranges.contains(&4));
```
##### Domain
Example implementation for a `Domain` allowing only values between 0 and 100:
```
use ranges::Domain;
struct LimitedInt(u8);
impl LimitedInt {
const MIN: u8 = 0;
const MAX: u8 = 100;
}
impl Domain for LimitedInt {
fn predecessor(&self) -> Option<Self> {
match self {
Self::MIN => None,
_ => Some(self - 1),
}
}
fn successor(&self) -> Option<Self> {
match self {
Self::MAX => None,
_ => Some(self + 1),
}
}
fn minimum() -> Bound<Self> {
Bound::Included(Self::MIN)
}
fn maximum() -> Bound<Self> {
Bound::Included(Self::MAX)
}
}
#[test]
fn clamp_to_domain() {
let range = GenericRange::<LimitedInt>::from(0..200);
assert!(range, (0..=100).into());
}
```
## Notes
The feature [`arbitrary`] allows creating arbitrary `GenericRange`s and `Range`s
which will always uphold the guarantees described above e.g. for use in fuzzers.
[`arbitrary`]: https://crates.io/crates/arbitrary