use serde::{Deserialize, Serialize};
/// apply a bool patch or set replacement for a single set update.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(untagged)]
pub(crate) enum SetUpdate {
/// replace the entire set with this list
Set(Vec<String>),
/// patch: true = add, false = remove
Patch(std::collections::HashMap<String, bool>),
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn set_update_json_markers_are_structurally_disjoint() {
for input in [r#"[]"#, r#"["a","b"]"#] {
let update: SetUpdate = serde_json::from_str(input).unwrap();
assert!(matches!(update, SetUpdate::Set(_)), "{input}");
}
for input in [r#"{}"#, r#"{"a":true,"b":false}"#] {
let update: SetUpdate = serde_json::from_str(input).unwrap();
assert!(matches!(update, SetUpdate::Patch(_)), "{input}");
}
for input in [r#""a""#, "null", "true", "1"] {
assert!(serde_json::from_str::<SetUpdate>(input).is_err(), "{input}");
}
}
#[test]
fn set_update_json_roundtrips_both_variants() {
for update in [
SetUpdate::Set(vec!["a".to_owned(), "b".to_owned()]),
SetUpdate::Patch([("a".to_owned(), true), ("b".to_owned(), false)].into()),
] {
let encoded = serde_json::to_vec(&update).unwrap();
let decoded: SetUpdate = serde_json::from_slice(&encoded).unwrap();
assert_eq!(decoded, update);
}
}
}