diff --git a/zenoh-plugin-ros2dds/src/config.rs b/zenoh-plugin-ros2dds/src/config.rs index 77adb47..11ad31e 100644 --- a/zenoh-plugin-ros2dds/src/config.rs +++ b/zenoh-plugin-ros2dds/src/config.rs @@ -59,10 +59,9 @@ pub struct Config { pub queries_timeout: Option, #[serde(default = "default_reliable_routes_blocking")] pub reliable_routes_blocking: bool, - #[serde(default)] - __required__: bool, - #[serde(default, deserialize_with = "deserialize_paths")] - __path__: Vec, + __required__: Option, + #[serde(default, deserialize_with = "deserialize_path")] + __path__: Option>, } impl Config { @@ -350,38 +349,67 @@ fn default_domain() -> u32 { } } -fn deserialize_paths<'de, D>(deserializer: D) -> Result, D::Error> +fn deserialize_path<'de, D>(deserializer: D) -> Result>, D::Error> where D: Deserializer<'de>, { - struct V; - impl<'de> serde::de::Visitor<'de> for V { - type Value = Vec; - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(formatter, "a string or vector of strings") - } - fn visit_str(self, v: &str) -> Result - where - E: de::Error, - { - Ok(vec![v.into()]) - } - fn visit_seq(self, mut seq: A) -> Result - where - A: de::SeqAccess<'de>, - { - let mut v = if let Some(l) = seq.size_hint() { - Vec::with_capacity(l) - } else { - Vec::new() - }; - while let Some(s) = seq.next_element()? { - v.push(s); - } - Ok(v) + deserializer.deserialize_option(OptPathVisitor) +} + +struct OptPathVisitor; + +impl<'de> serde::de::Visitor<'de> for OptPathVisitor { + type Value = Option>; + + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(formatter, "none or a string or an array of strings") + } + + fn visit_none(self) -> Result + where + E: de::Error, + { + Ok(None) + } + + fn visit_some(self, deserializer: D) -> Result + where + D: Deserializer<'de>, + { + deserializer.deserialize_any(PathVisitor).map(Some) + } +} + +struct PathVisitor; + +impl<'de> serde::de::Visitor<'de> for PathVisitor { + type Value = Vec; + + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(formatter, "a string or an array of strings") + } + + fn visit_str(self, v: &str) -> Result + where + E: de::Error, + { + Ok(vec![v.into()]) + } + + fn visit_seq(self, mut seq: A) -> Result + where + A: de::SeqAccess<'de>, + { + let mut v = if let Some(l) = seq.size_hint() { + Vec::with_capacity(l) + } else { + Vec::new() + }; + while let Some(s) = seq.next_element()? { + v.push(s); } + Ok(v) } - deserializer.deserialize_any(V) } fn default_reliable_routes_blocking() -> bool { @@ -508,7 +536,9 @@ where serializer.serialize_f32(d.as_secs_f32()) } +#[cfg(test)] mod tests { + use super::Config; #[test] fn test_allowance() { @@ -657,4 +687,69 @@ mod tests { ); assert!(invalid.is_err()); } + + #[test] + fn test_path_field() { + // See: https://github.com/eclipse-zenoh/zenoh-plugin-webserver/issues/19 + let config = serde_json::from_str::(r#"{"__path__": "/example/path"}"#); + + assert!(config.is_ok()); + let Config { + __required__, + __path__, + .. + } = config.unwrap(); + + assert_eq!(__path__, Some(vec![String::from("/example/path")])); + assert_eq!(__required__, None); + } + + #[test] + fn test_required_field() { + // See: https://github.com/eclipse-zenoh/zenoh-plugin-webserver/issues/19 + let config = serde_json::from_str::(r#"{"__required__": true}"#); + assert!(config.is_ok()); + let Config { + __required__, + __path__, + .. + } = config.unwrap(); + + assert_eq!(__path__, None); + assert_eq!(__required__, Some(true)); + } + + #[test] + fn test_path_field_and_required_field() { + // See: https://github.com/eclipse-zenoh/zenoh-plugin-webserver/issues/19 + let config = serde_json::from_str::( + r#"{"__path__": "/example/path", "__required__": true}"#, + ); + + assert!(config.is_ok()); + let Config { + __required__, + __path__, + .. + } = config.unwrap(); + + assert_eq!(__path__, Some(vec![String::from("/example/path")])); + assert_eq!(__required__, Some(true)); + } + + #[test] + fn test_no_path_field_and_no_required_field() { + // See: https://github.com/eclipse-zenoh/zenoh-plugin-webserver/issues/19 + let config = serde_json::from_str::("{}"); + + assert!(config.is_ok()); + let Config { + __required__, + __path__, + .. + } = config.unwrap(); + + assert_eq!(__path__, None); + assert_eq!(__required__, None); + } }