tier 0.1.17

Rust configuration library for layered TOML, env, and CLI settings
Documentation
use std::cmp::Ordering;

use serde_json::Value;

use crate::number::compare_json_numbers;

pub(crate) fn values_equal(left: &Value, right: &Value) -> bool {
    match (left, right) {
        (Value::Number(left), Value::Number(right)) => {
            compare_json_numbers(left, right).is_some_and(|ordering| ordering == Ordering::Equal)
        }
        (Value::Array(left), Value::Array(right)) => {
            left.len() == right.len()
                && left
                    .iter()
                    .zip(right)
                    .all(|(left, right)| values_equal(left, right))
        }
        (Value::Object(left), Value::Object(right)) => {
            left.len() == right.len()
                && left.iter().all(|(key, left)| {
                    right
                        .get(key)
                        .is_some_and(|right| values_equal(left, right))
                })
        }
        _ => left == right,
    }
}

#[cfg(feature = "schema")]
pub(crate) fn values_contain(values: &[Value], value: &Value) -> bool {
    values.iter().any(|existing| values_equal(existing, value))
}

#[cfg(test)]
mod tests {
    use serde_json::json;

    use super::values_equal;

    #[test]
    fn value_equality_treats_numbers_mathematically() {
        assert!(values_equal(&json!(1), &json!(1.0)));
        assert!(values_equal(
            &json!([1, { "port": 8080 }]),
            &json!([1.0, { "port": 8080.0 }])
        ));
        assert!(!values_equal(&json!(1), &json!(1.5)));
    }
}