I would write this as:
impl Serialize for Filter {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut s = String::new();
if let Some(ref namespace_id) = self.namespace_id {
s.push_str("namespace_id:");
s.push_str(&namespace_id.to_string());
}
if let Some(ref object_id) = self.object_id {
if !s.is_empty() {
s.push_str(" AND ");
}
s.push_str("object_id:");
s.push_str(&object_id);
}
s.serialize(serializer)
}
}
impl<'de> Deserialize<'de> for Filter {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let mut filter = Filter {
namespace_id: None,
object_id: None,
};
let s = String::deserialize(deserializer)?;
for part in s.split(" AND ") {
let mut kv = part.splitn(2, ":");
match (kv.next(), kv.next()) {
(Some("namespace_id"), Some(v)) => {
let uuid = Uuid::parse_str(v).map_err(de::Error::custom)?;
filter.namespace_id = Some(uuid);
}
(Some("object_id"), Some(v)) => {
filter.object_id = Some(v.to_owned());
}
_ => { /* report error if you want */ }
}
}
Ok(filter)
}
}