fuzzy-from-json-value 0.1.0

todo: write a description here
Documentation
// ---------------- [ File: fuzzy-from-json-value/src/fuzzy_vec_u8.rs ]
crate::ix!();

/// A fuzzy deserialization helper for `Vec<u8>`.
///
/// - If the JSON is `null` or missing and you have `#[serde(default)]`, you'll get an empty `Vec`.
/// - If the JSON is an array, each element is parsed fuzzily as `u8`:
///   - Floats get truncated and clamped to 0..255, logging any issues.
///   - Integers that exceed 255 or < 0 => clamp, logging it.
///   - Non-numeric => error out.
pub fn fuzzy_vec_u8<'de, D>(deserializer: D) -> Result<Vec<u8>, D::Error>
where
    D: Deserializer<'de>,
{
    // First parse the raw JSON into a `JsonValue`.
    let val: JsonValue = Deserialize::deserialize(deserializer)?;

    match val {
        // (1) If it's null => we can interpret that as an empty vec
        JsonValue::Null => {
            debug!("Received null for fuzzy_vec_u8 => returning empty Vec<u8>.");
            Ok(Vec::new())
        }

        // (2) If it's an array => parse each element fuzzily
        JsonValue::Array(arr) => {
            let mut result = Vec::with_capacity(arr.len());
            for elem in arr {
                let fuzzed = match elem {
                    JsonValue::Number(num) => {
                        // integer?
                        if let Some(u) = num.as_u64() {
                            if u <= 255 {
                                u as u8
                            } else {
                                warn!("JsonValue {} out of u8 range => clamping to 255", u);
                                255
                            }
                        }
                        // float?
                        else if let Some(f) = num.as_f64() {
                            if f < 0.0 {
                                warn!("Float {} < 0 => clamping to 0", f);
                                0
                            } else if f > 255.0 {
                                warn!("Float {} > 255 => clamping to 255", f);
                                255
                            } else {
                                let truncated = f.trunc();
                                if (f - truncated).abs() > f64::EPSILON {
                                    warn!("Truncating float {} => {}", f, truncated);
                                }
                                truncated as u8
                            }
                        } else {
                            let msg = format!("Number not convertible to u64/f64 => {:?}", num);
                            return Err(de::Error::custom(msg));
                        }
                    }
                    // (3) If it's not a number => error
                    other => {
                        let msg = format!("Expected numeric in array, got {:?}", other);
                        return Err(de::Error::custom(msg));
                    }
                };
                result.push(fuzzed);
            }
            Ok(result)
        }

        // (4) If JSON is anything else => error
        other => {
            let msg = format!("Expected array or null for fuzzy_vec_u8, got {:?}", other);
            Err(de::Error::custom(msg))
        }
    }
}