diff --git a/torn-api/Cargo.toml b/torn-api/Cargo.toml index 539328e..be77d71 100644 --- a/torn-api/Cargo.toml +++ b/torn-api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "torn-api" -version = "0.5.13" +version = "0.5.14" edition = "2021" authors = ["Pyrit [2111649]"] license = "MIT" diff --git a/torn-api/src/de_util.rs b/torn-api/src/de_util.rs index 3f3983b..3e10aa4 100644 --- a/torn-api/src/de_util.rs +++ b/torn-api/src/de_util.rs @@ -135,6 +135,53 @@ where deserializer.deserialize_map(MapVisitor) } +pub(crate) fn empty_dict_is_empty_array<'de, D, T>(deserializer: D) -> Result, D::Error> +where + D: Deserializer<'de>, + T: Deserialize<'de>, +{ + struct ArrayVisitor(std::marker::PhantomData); + + impl<'de, T> Visitor<'de> for ArrayVisitor + where + T: Deserialize<'de>, + { + type Value = Vec; + + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(formatter, "vec or empty object") + } + + fn visit_map(self, map: A) -> Result + where + A: serde::de::MapAccess<'de>, + { + match map.size_hint() { + Some(0) | None => Ok(Vec::default()), + Some(len) => Err(A::Error::invalid_length(len, &"empty dict")), + } + } + + fn visit_seq(self, mut seq: A) -> Result + where + A: serde::de::SeqAccess<'de>, + { + let mut result = match seq.size_hint() { + Some(len) => Vec::with_capacity(len), + None => Vec::default(), + }; + + while let Some(element) = seq.next_element()? { + result.push(element); + } + + Ok(result) + } + } + + deserializer.deserialize_any(ArrayVisitor(std::marker::PhantomData)) +} + #[cfg(feature = "decimal")] pub(crate) fn string_or_decimal<'de, D>(deserializer: D) -> Result where diff --git a/torn-api/src/faction.rs b/torn-api/src/faction.rs index 9ae8b47..8d11f6a 100644 --- a/torn-api/src/faction.rs +++ b/torn-api/src/faction.rs @@ -68,7 +68,7 @@ pub struct Basic<'a> { #[serde(deserialize_with = "de_util::datetime_map")] pub peace: BTreeMap>, - #[serde(borrow)] + #[serde(borrow, deserialize_with = "de_util::empty_dict_is_empty_array")] pub territory_wars: Vec>, }