tier 0.1.17

Rust configuration library for layered TOML, env, and CLI settings
Documentation
use serde_json::{Map, Value};

pub(crate) fn keyword_u64(object: &Map<String, Value>, key: &str) -> Option<u64> {
    object.get(key).and_then(Value::as_u64)
}

pub(crate) fn usize_saturating(value: u64) -> usize {
    usize::try_from(value).unwrap_or(usize::MAX)
}

pub(crate) fn usize_to_u64_saturating(value: usize) -> u64 {
    u64::try_from(value).unwrap_or(u64::MAX)
}

pub(crate) fn len_at_least(len: usize, min: u64) -> bool {
    match u64::try_from(len) {
        Ok(len) => len >= min,
        Err(_) => true,
    }
}

pub(crate) fn len_at_most(len: usize, max: u64) -> bool {
    match u64::try_from(len) {
        Ok(len) => len <= max,
        Err(_) => false,
    }
}

pub(crate) fn len_less_than(len: usize, max: u64) -> bool {
    match u64::try_from(len) {
        Ok(len) => len < max,
        Err(_) => false,
    }
}

pub(crate) fn remaining_required(min: u64, existing: usize) -> usize {
    usize_saturating(min.saturating_sub(usize_to_u64_saturating(existing)))
}

pub(crate) fn available_slots(max: Option<u64>, existing: usize) -> usize {
    max.map_or(usize::MAX, usize_saturating)
        .saturating_sub(existing)
}

#[cfg(test)]
mod tests {
    use super::{
        available_slots, len_at_least, len_at_most, len_less_than, remaining_required,
        usize_saturating,
    };

    #[test]
    fn large_json_schema_counts_are_saturated_explicitly() {
        assert_eq!(usize_saturating(u64::MAX), usize::MAX);
        assert_eq!(remaining_required(u64::MAX, 0), usize::MAX);
        assert_eq!(available_slots(Some(u64::MAX), 0), usize::MAX);
    }

    #[test]
    fn length_comparisons_do_not_depend_on_lossy_casts() {
        assert!(len_at_least(usize::MAX, 0));
        assert!(len_at_most(0, u64::MAX));
        assert!(!len_at_most(usize::MAX, 0));
        assert!(!len_less_than(0, 0));
    }
}