zenoh_flow_commons/
deserialize.rsuse serde::Deserializer;
use std::{str::FromStr, sync::Arc};
use zenoh_keyexpr::OwnedKeyExpr;
pub fn deserialize_id<'de, D>(deserializer: D) -> std::result::Result<Arc<str>, D::Error>
where
D: Deserializer<'de>,
{
let id: String = serde::de::Deserialize::deserialize(deserializer)?;
if id.contains(['*', '#', '$', '?', '>']) {
return Err(serde::de::Error::custom(format!(
r#"
Identifiers (for nodes or ports) in Zenoh-Flow must *not* contain any of the characters: '*', '#', '$', '?', '>'.
The identifier < {} > does not satisfy that condition.
These characters, except for '>', have a special meaning in Zenoh and they could negatively impact Zenoh-Flow's
behaviour.
The character '>' is used as a separator when flattening a composite operator. Allowing it could also negatively impact
Zenoh-Flow's behaviour.
"#,
id
)));
}
OwnedKeyExpr::autocanonize(id.clone()).map_err(|e| {
serde::de::Error::custom(format!(
r#"
Identifiers (for nodes or ports) in Zenoh-Flow *must* be valid key-expressions in their canonical form.
The identifier < {} > does not satisfy that condition.
Caused by:
{:?}
"#,
id, e
))
})?;
Ok(id.into())
}
pub fn deserialize_size<'de, D>(deserializer: D) -> std::result::Result<usize, D::Error>
where
D: Deserializer<'de>,
{
let size_str: String = serde::de::Deserialize::deserialize(deserializer)?;
let size_u64 = bytesize::ByteSize::from_str(&size_str)
.map_err(|e| {
serde::de::Error::custom(format!(
"Unable to parse value as bytes {size_str}:\n{:?}",
e
))
})?
.as_u64();
usize::try_from(size_u64).map_err(|e| serde::de::Error::custom(format!(
"Unable to convert < {} > into a `usize`. Maybe check the architecture of the target device?\n{:?}",
size_u64, e
)))
}
pub fn deserialize_time<'de, D>(deserializer: D) -> std::result::Result<u64, D::Error>
where
D: Deserializer<'de>,
{
let buf: &str = serde::de::Deserialize::deserialize(deserializer)?;
let time_u128 = buf
.parse::<humantime::Duration>()
.map_err(serde::de::Error::custom)?
.as_micros();
u64::try_from(time_u128).map_err(|e| {
serde::de::Error::custom(format!(
"Unable to convert < {} > into a `u64`. Maybe lower the value?\n{:?}",
time_u128, e
))
})
}
#[cfg(test)]
mod tests {
use serde::Deserialize;
use crate::NodeId;
#[derive(Deserialize, Debug)]
pub struct TestStruct {
pub id: NodeId,
}
#[test]
fn test_deserialize_id() {
let json_str = r#"
{
"id": "my//chunk"
}
"#;
assert!(serde_json::from_str::<TestStruct>(json_str).is_err());
let json_str = r#"
{
"id": "my*chunk"
}
"#;
assert!(serde_json::from_str::<TestStruct>(json_str).is_err());
let json_str = r##"
{
"id": "#chunk"
}
"##;
assert!(serde_json::from_str::<TestStruct>(json_str).is_err());
let json_str = r#"
{
"id": "?chunk"
}
"#;
assert!(serde_json::from_str::<TestStruct>(json_str).is_err());
let json_str = r#"
{
"id": "$chunk"
}
"#;
assert!(serde_json::from_str::<TestStruct>(json_str).is_err());
let json_str = r#"
{
"id": "my>chunk"
}
"#;
assert!(serde_json::from_str::<TestStruct>(json_str).is_err());
let json_str = r#"
{
"id": "my/chunk/is/alright"
}
"#;
assert!(serde_json::from_str::<TestStruct>(json_str).is_ok());
}
}