to-regex-range 0.1.1

Generate a compact regex that matches an integer range: (1, 99) -> [1-9]|[1-9][0-9]. A faithful port of the to-regex-range npm package. Zero dependencies, no_std.
Documentation
//! Behavioral spec for `to-regex-range`, cross-checked against the npm package.

use to_regex_range::{to_regex_range, to_regex_range_with_options, Options};

#[test]
fn simple_ranges() {
    assert_eq!(to_regex_range(1, 5), "[1-5]");
    assert_eq!(to_regex_range(3, 7), "[3-7]");
    assert_eq!(to_regex_range(0, 9), "[0-9]");
    assert_eq!(to_regex_range(1, 9), "[1-9]");
    assert_eq!(to_regex_range(12, 19), "1[2-9]");
    assert_eq!(to_regex_range(5, 5), "5");
    assert_eq!(to_regex_range(0, 0), "0");
    assert_eq!(to_regex_range(5, 6), "(?:5|6)");
}

#[test]
fn multi_digit_ranges() {
    assert_eq!(to_regex_range(1, 10), "(?:[1-9]|10)");
    assert_eq!(to_regex_range(1, 99), "(?:[1-9]|[1-9][0-9])");
    assert_eq!(to_regex_range(10, 99), "(?:1[0-9]|[2-9][0-9])");
    assert_eq!(to_regex_range(1, 100), "(?:[1-9]|[1-9][0-9]|100)");
    assert_eq!(to_regex_range(100, 199), "(?:10[0-9]|1[1-9][0-9])");
    assert_eq!(to_regex_range(1, 999), "(?:[1-9]|[1-9][0-9]{1,2})");
    assert_eq!(to_regex_range(0, 100), "(?:[0-9]|[1-9][0-9]|100)");
    assert_eq!(
        to_regex_range(1, 1_000_000),
        "(?:[1-9]|[1-9][0-9]{1,5}|1000000)"
    );
}

#[test]
fn real_world_ranges() {
    assert_eq!(
        to_regex_range(1, 255),
        "(?:[1-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])"
    );
    assert_eq!(
        to_regex_range(0, 255),
        "(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])"
    );
    assert_eq!(to_regex_range(1, 12), "(?:[1-9]|1[0-2])");
    assert_eq!(to_regex_range(1, 31), "(?:[1-9]|[12][0-9]|3[01])");
    assert_eq!(
        to_regex_range(1, 365),
        "(?:[1-9]|[1-9][0-9]|[12][0-9]{2}|3[0-5][0-9]|36[0-5])"
    );
}

#[test]
fn negatives() {
    assert_eq!(to_regex_range(-5, 5), "(?:-[1-5]|[0-5])");
    assert_eq!(to_regex_range(-10, -1), "(?:-[1-9]|-10)");
    assert_eq!(to_regex_range(-99, 99), "(?:-[1-9]|-?[1-9][0-9]|[0-9])");
    assert_eq!(to_regex_range(-1, 1), "(?:-1|[01])");
}

#[test]
fn order_is_normalized() {
    assert_eq!(to_regex_range(5, 1), "[1-5]");
}

// Regression: extreme i64 ranges must not overflow/panic.
#[test]
fn extreme_ranges_do_not_panic() {
    let _ = to_regex_range(i64::MIN, i64::MAX);
    let _ = to_regex_range(i64::MIN, 0);
    let _ = to_regex_range(i64::MIN, -1);
    let _ = to_regex_range(0, i64::MAX);
    let _ = to_regex_range(i64::MAX - 1, i64::MAX);
    let _ = to_regex_range(i64::MIN, i64::MIN + 1);
    assert!(!to_regex_range(i64::MIN, i64::MAX).is_empty());
}

#[test]
fn options() {
    assert_eq!(
        to_regex_range_with_options(1, 99, &Options::default().shorthand(true)),
        "(?:[1-9]|[1-9]\\d)"
    );
    assert_eq!(
        to_regex_range_with_options(1, 99, &Options::default().capture(true)),
        "([1-9]|[1-9][0-9])"
    );
    assert_eq!(
        to_regex_range_with_options(1, 99, &Options::default().wrap(false)),
        "[1-9]|[1-9][0-9]"
    );
    assert_eq!(
        to_regex_range_with_options(5, 6, &Options::default().capture(true)),
        "(5|6)"
    );
    assert_eq!(
        to_regex_range_with_options(5, 6, &Options::default().wrap(false)),
        "5|6"
    );
}