diff --git a/TODO.md b/TODO.md index 5d608fa..a2f1020 100644 --- a/TODO.md +++ b/TODO.md @@ -16,7 +16,7 @@ * move stuff to common crate with ws: what about Request/InMessage etc? * info hashes, peer ids: check that whole deserialization and url decoding works as it should. There are suspicously many `\u{fffd}` -* AnnounceRequest.compact: parse int to bool +* AnnounceRequest.compact: handle that it is optional ## aquatic_ws * tests diff --git a/aquatic_http/src/lib/protocol/mod.rs b/aquatic_http/src/lib/protocol/mod.rs index 6b50c87..f9321b8 100644 --- a/aquatic_http/src/lib/protocol/mod.rs +++ b/aquatic_http/src/lib/protocol/mod.rs @@ -74,8 +74,11 @@ pub struct AnnounceRequest { pub bytes_left: usize, #[serde(default)] pub event: AnnounceEvent, - /// FIXME: number: 0 or 1 to bool - pub compact: u8, + /// FIXME: is optional, so should default to something, maybe `true` + #[serde( + deserialize_with = "deserialize_bool_from_number" + )] + pub compact: bool, /// Requested number of peers to return pub numwant: usize, } diff --git a/aquatic_http/src/lib/protocol/serde_helpers.rs b/aquatic_http/src/lib/protocol/serde_helpers.rs index 956119c..29ff9b4 100644 --- a/aquatic_http/src/lib/protocol/serde_helpers.rs +++ b/aquatic_http/src/lib/protocol/serde_helpers.rs @@ -5,6 +5,40 @@ use serde::{Serializer, Deserializer, de::{Visitor, SeqAccess}}; use super::{InfoHash, ResponsePeer}; +struct BoolFromNumberVisitor; + +impl<'de> Visitor<'de> for BoolFromNumberVisitor { + type Value = bool; + + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + formatter.write_str("1 for true, 0 for false") + } + + #[inline] + fn visit_str(self, value: &str) -> Result + where E: ::serde::de::Error, + { + if value == "0" { + Ok(false) + } else if value == "1" { + Ok(true) + } else { + Err(E::custom(format!("not 0 or 1: {}", value))) + } + } +} + + +#[inline] +pub fn deserialize_bool_from_number<'de, D>( + deserializer: D +) -> Result + where D: Deserializer<'de> +{ + deserializer.deserialize_any(BoolFromNumberVisitor) +} + + struct TwentyCharStringVisitor; impl<'de> Visitor<'de> for TwentyCharStringVisitor {