From 52a29fc14a991a0112f110b0df4cacd0fab58f5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Fri, 3 Jul 2020 13:17:02 +0200 Subject: [PATCH] aquatic_http: store info_hash and peer_id in [u8; 20] --- aquatic_http/src/lib/protocol/mod.rs | 10 ++-- .../src/lib/protocol/serde_helpers.rs | 46 +++++++++++++------ 2 files changed, 37 insertions(+), 19 deletions(-) diff --git a/aquatic_http/src/lib/protocol/mod.rs b/aquatic_http/src/lib/protocol/mod.rs index 933a9a9..653c800 100644 --- a/aquatic_http/src/lib/protocol/mod.rs +++ b/aquatic_http/src/lib/protocol/mod.rs @@ -13,9 +13,9 @@ use serde_helpers::*; #[serde(transparent)] pub struct PeerId( #[serde( - deserialize_with = "deserialize_20_char_string", + deserialize_with = "deserialize_20_bytes", )] - pub String + pub [u8; 20] ); @@ -23,9 +23,9 @@ pub struct PeerId( #[serde(transparent)] pub struct InfoHash( #[serde( - deserialize_with = "deserialize_20_char_string", + deserialize_with = "deserialize_20_bytes", )] - pub String + pub [u8; 20] ); @@ -180,8 +180,6 @@ impl Request { let mut processed = String::new(); for (i, part) in query_string.split('%').enumerate(){ - println!("{}", part); - if i == 0 { processed.push_str(part); } else if part.len() >= 2 { diff --git a/aquatic_http/src/lib/protocol/serde_helpers.rs b/aquatic_http/src/lib/protocol/serde_helpers.rs index 29ff9b4..94b39bf 100644 --- a/aquatic_http/src/lib/protocol/serde_helpers.rs +++ b/aquatic_http/src/lib/protocol/serde_helpers.rs @@ -39,35 +39,55 @@ pub fn deserialize_bool_from_number<'de, D>( } -struct TwentyCharStringVisitor; -impl<'de> Visitor<'de> for TwentyCharStringVisitor { - type Value = String; +/// Decode string of 20 byte-size chars to a [u8; 20] +struct TwentyByteVisitor; + +impl<'de> Visitor<'de> for TwentyByteVisitor { + type Value = [u8; 20]; fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("string consisting of 20 chars") + formatter.write_str("string consisting of 20 bytes") } #[inline] fn visit_str(self, value: &str) -> Result where E: ::serde::de::Error, { - if value.chars().count() == 20 { - Ok(value.to_string()) + let mut arr = [0u8; 20]; + let mut char_iter = value.chars(); + + for a in arr.iter_mut(){ + if let Some(c) = char_iter.next(){ + if c as u32 > 255 { + return Err(E::custom(format!( + "character not in single byte range: {:#?}", + c + ))); + } + + *a = c as u8; + } else { + return Err(E::custom(format!("less than 20 bytes: {:#?}", value))); + } + } + + if char_iter.next().is_some(){ + Err(E::custom(format!("more than 20 bytes: {:#?}", value))) } else { - Err(E::custom(format!("not 20 chars: {:#?}", value))) + Ok(arr) } } } #[inline] -pub fn deserialize_20_char_string<'de, D>( +pub fn deserialize_20_bytes<'de, D>( deserializer: D -) -> Result +) -> Result<[u8; 20], D::Error> where D: Deserializer<'de> { - deserializer.deserialize_any(TwentyCharStringVisitor) + deserializer.deserialize_any(TwentyByteVisitor) } @@ -85,7 +105,7 @@ impl<'de> Visitor<'de> for InfoHashVecVisitor { fn visit_str(self, value: &str) -> Result where E: ::serde::de::Error, { - match TwentyCharStringVisitor::visit_str::(TwentyCharStringVisitor, value){ + match TwentyByteVisitor::visit_str::(TwentyByteVisitor, value){ Ok(arr) => Ok(vec![InfoHash(arr)]), Err(err) => Err(E::custom(format!("got string, but {}", err))) } @@ -98,8 +118,8 @@ impl<'de> Visitor<'de> for InfoHashVecVisitor { let mut info_hashes: Self::Value = Vec::new(); while let Ok(Some(value)) = seq.next_element::<&str>(){ - let arr = TwentyCharStringVisitor::visit_str( - TwentyCharStringVisitor, value + let arr = TwentyByteVisitor::visit_str( + TwentyByteVisitor, value )?; info_hashes.push(InfoHash(arr));