crate::ix!();
pub fn fuzzy_option_u8<'de, D>(deserializer: D) -> Result<Option<u8>, D::Error>
where
D: Deserializer<'de>,
{
let val: Option<JsonValue> = Option::deserialize(deserializer)?;
match val {
None => {
Ok(None)
}
Some(json_val) => {
match json_val {
JsonValue::Number(num) => {
if let Some(u) = num.as_u64() {
if u <= 255 {
Ok(Some(u as u8))
} else {
warn!("JsonValue {} out of range for u8 => clamping to 255", u);
Ok(Some(255))
}
}
else if let Some(f) = num.as_f64() {
if f < 0.0 {
warn!("Float {} < 0 => clamping to 0", f);
Ok(Some(0))
} else if f > 255.0 {
warn!("Float {} > 255 => clamping to 255", f);
Ok(Some(255))
} else {
let truncated = f.trunc();
if (f - truncated).abs() > f64::EPSILON {
warn!("Truncating float {} => {}", f, truncated);
}
Ok(Some(truncated as u8))
}
} else {
let msg = format!("Number not convertible to u64/f64 => {:?}", num);
Err(de::Error::custom(msg))
}
}
JsonValue::Null => {
Ok(None)
}
other => {
let msg = format!("Expected numeric or null, got {:?}", other);
Err(de::Error::custom(msg))
}
}
}
}
}
pub fn fuzzy_option_u8_from_value(val: &JsonValue) -> Result<Option<u8>, String> {
match val {
JsonValue::Null => Ok(None),
JsonValue::Number(num) => {
if let Some(u) = num.as_u64() {
if u > 255 {
warn!("JsonValue {} out of range => clamp to 255", u);
Ok(Some(255))
} else {
Ok(Some(u as u8))
}
} else if let Some(f) = num.as_f64() {
if f < 0.0 {
warn!("Float {} < 0 => clamp to 0", f);
Ok(Some(0))
} else if f > 255.0 {
warn!("Float {} > 255 => clamp to 255", f);
Ok(Some(255))
} else {
let truncated = f.trunc();
if (f - truncated).abs() > f64::EPSILON {
warn!("Truncating float {} => {}", f, truncated);
}
Ok(Some(truncated as u8))
}
} else {
Err(format!("Number not convertible to f64 or u64 => {:?}", num))
}
}
other => Err(format!("Expected numeric or null for fuzzy_option_u8, got {:?}", other)),
}
}