use std::fmt;
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct LossyValue {
key: String,
raw_value: String,
}
impl LossyValue {
pub fn new(key: String, raw_value: String) -> Self {
Self { key, raw_value }
}
pub fn key(&self) -> &str {
&self.key
}
pub fn raw_value(&self) -> &str {
&self.raw_value
}
}
#[derive(Debug, Clone, Default, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(transparent))]
pub struct LossyValues(Vec<LossyValue>);
impl LossyValues {
pub fn is_empty(&self) -> bool {
self.0
.is_empty()
}
pub fn iter(&self) -> impl Iterator<Item = &LossyValue> {
self.0
.iter()
}
pub fn push(&mut self, v: LossyValue) {
self.0
.push(v);
}
}
impl fmt::Display for LossyValues {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let keys: Vec<&str> = self
.0
.iter()
.map(|v| v.key())
.collect();
write!(f, "{}", keys.join(", "))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn lossy_values_display_keys_only() {
let mut lossy = LossyValues::default();
lossy.push(LossyValue::new(
"variable_dp_match".to_string(),
"%E9foo".to_string(),
));
lossy.push(LossyValue::new(
"another_key".to_string(),
"%FFbar".to_string(),
));
let display = lossy.to_string();
assert_eq!(display, "variable_dp_match, another_key");
assert!(!display.contains("%E9"));
assert!(!display.contains("foo"));
}
#[test]
fn lossy_values_empty() {
let lossy = LossyValues::default();
assert!(lossy.is_empty());
assert_eq!(
lossy
.iter()
.count(),
0
);
}
#[cfg(feature = "serde")]
#[test]
fn serde_roundtrip() {
let mut lossy = LossyValues::default();
lossy.push(LossyValue::new("key1".to_string(), "%E9value".to_string()));
let json = serde_json::to_string(&lossy).unwrap();
let deserialized: LossyValues = serde_json::from_str(&json).unwrap();
assert_eq!(lossy, deserialized);
assert_eq!(
deserialized
.iter()
.next()
.unwrap()
.key(),
"key1"
);
assert_eq!(
deserialized
.iter()
.next()
.unwrap()
.raw_value(),
"%E9value"
);
}
#[cfg(feature = "serde")]
#[test]
fn serde_old_json_without_field() {
let json = "[]";
let lossy: LossyValues = serde_json::from_str(json).unwrap();
assert!(lossy.is_empty());
}
}