diff --git a/Cargo.toml b/Cargo.toml index 99c4aa0..4c76a58 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ name = "df-consul" description = "Deuxfleurs' async Rust bindings for (a subset of) the Consul HTTP API" authors = [ "Alex Auvolat " ] -version = "0.3.4" +version = "0.3.5" edition = "2021" license = "MIT" repository = "https://git.deuxfleurs.fr/Deuxfleurs/df-consul" diff --git a/src/catalog.rs b/src/catalog.rs index fe82c5a..87c7775 100644 --- a/src/catalog.rs +++ b/src/catalog.rs @@ -13,7 +13,7 @@ use futures::future::BoxFuture; use futures::stream::futures_unordered::FuturesUnordered; use futures::{FutureExt, StreamExt, TryFutureExt}; use log::*; -use serde::{Deserialize, Serialize}; +use serde::{Deserialize, Deserializer, Serialize}; use tokio::select; use tokio::sync::watch; @@ -26,6 +26,7 @@ use crate::{Consul, WithIndex}; pub struct Node { pub node: String, pub address: String, + #[serde(default, deserialize_with = "deserialize_null_default")] pub meta: HashMap, } @@ -37,6 +38,8 @@ pub struct Service { pub address: String, pub port: u16, pub tags: Vec, + #[serde(default, deserialize_with = "deserialize_null_default")] + pub meta: HashMap, } /// Full node info, as specified in response to "retrieve map of services for a node" API call in @@ -45,6 +48,7 @@ pub struct Service { #[serde(rename_all = "PascalCase")] pub struct CatalogNode { pub node: Node, + #[serde(default, deserialize_with = "deserialize_null_default")] pub services: HashMap, } @@ -59,11 +63,14 @@ pub type ServiceList = HashMap>; pub struct ServiceNode { pub node: String, pub address: String, + #[serde(default, deserialize_with = "deserialize_null_default")] pub node_meta: HashMap, pub service_name: String, pub service_tags: Vec, pub service_address: String, pub service_port: u16, + #[serde(default, deserialize_with = "deserialize_null_default")] + pub service_meta: HashMap, } /// Node serving a service with health info, @@ -273,3 +280,11 @@ fn retry_to_time(retries: usize, max_time: Duration) -> Duration { Duration::from_secs_f64(2.0f64 * 1.5f64.powf(retries as f64)), ) } + +fn deserialize_null_default<'de, D, T>(deserializer: D) -> Result +where + T: Default + Deserialize<'de>, + D: Deserializer<'de>, +{ + Option::deserialize(deserializer).map(Option::unwrap_or_default) +}