[bencode/ser] Implement structs

This commit is contained in:
Fabian 2024-08-06 21:54:16 +02:00
parent b085afe9d7
commit f90876a324

View File

@ -51,7 +51,7 @@ impl<'a> ser::Serializer for &'a mut Serializer
type SerializeTupleStruct = Self; type SerializeTupleStruct = Self;
type SerializeTupleVariant = Self; type SerializeTupleVariant = Self;
type SerializeMap = MapSerializer<'a>; type SerializeMap = MapSerializer<'a>;
type SerializeStruct = Self; type SerializeStruct = MapSerializer<'a>;
type SerializeStructVariant = Self; type SerializeStructVariant = Self;
fn serialize_bool(self, v: bool) -> Result<()> { fn serialize_bool(self, v: bool) -> Result<()> {
@ -196,8 +196,14 @@ impl<'a> ser::Serializer for &'a mut Serializer
}) })
} }
fn serialize_struct(self, name: &'static str, len: usize) -> Result<Self::SerializeStruct> { fn serialize_struct(self, _name: &'static str, _len: usize) -> Result<Self::SerializeStruct> {
todo!() self.output.push('d' as u8);
Ok(MapSerializer{
super_serializer: self,
sorted_map: BTreeMap::new(),
last_inserted_key: Vec::new(),
value_serializer: Serializer::new(),
})
} }
fn serialize_struct_variant(self, _name: &'static str, _variant_index: u32, _variant: &'static str, _len: usize) -> Result<Self::SerializeStructVariant> { fn serialize_struct_variant(self, _name: &'static str, _variant_index: u32, _variant: &'static str, _len: usize) -> Result<Self::SerializeStructVariant> {
@ -270,6 +276,16 @@ impl <'a> ser::SerializeTupleVariant for &'a mut Serializer {
} }
} }
impl<'a> MapSerializer<'a> {
fn finalize(self) {
for (key, value) in self.sorted_map.into_iter() {
self.super_serializer.output.extend(key);
self.super_serializer.output.extend(value);
}
self.super_serializer.output.push('e' as u8);
}
}
impl <'a> ser::SerializeMap for MapSerializer<'a> { impl <'a> ser::SerializeMap for MapSerializer<'a> {
type Ok = (); type Ok = ();
type Error = Error; type Error = Error;
@ -313,16 +329,12 @@ impl <'a> ser::SerializeMap for MapSerializer<'a> {
} }
fn end(self) -> Result<()> { fn end(self) -> Result<()> {
for (key, value) in self.sorted_map.into_iter() { self.finalize();
self.super_serializer.output.extend(key);
self.super_serializer.output.extend(value);
}
self.super_serializer.output.push('e' as u8);
Ok(()) Ok(())
} }
} }
impl <'a> ser::SerializeStruct for &'a mut Serializer { impl <'a> ser::SerializeStruct for MapSerializer<'a> {
type Ok = (); type Ok = ();
type Error = Error; type Error = Error;
@ -330,11 +342,25 @@ impl <'a> ser::SerializeStruct for &'a mut Serializer {
where where
T: ?Sized + Serialize T: ?Sized + Serialize
{ {
todo!() match value.serialize(&mut self.value_serializer) {
Ok(_) => (),
Err(e) =>
return match e {
Error::OptionNone => Ok(()),
_ => Err(e),
},
};
let mut val_str = Vec::new();
swap(&mut self.value_serializer.output, &mut val_str);
key.serialize(&mut self.value_serializer)?;
let mut key_str = Vec::new();
swap(&mut self.value_serializer.output, &mut key_str);
self.sorted_map.insert(key_str, val_str);
Ok(())
} }
fn end(self) -> Result<()> { fn end(self) -> Result<()> {
self.output.push('e' as u8); self.finalize();
Ok(()) Ok(())
} }
} }
@ -358,7 +384,7 @@ impl <'a> ser::SerializeStructVariant for &'a mut Serializer {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use std::collections::HashMap; use std::collections::HashMap;
use serde::Serialize;
use crate::bencode::ser::to_string; use crate::bencode::ser::to_string;
#[test] #[test]
@ -407,4 +433,32 @@ mod test {
"d3:foo4:💩e" "d3:foo4:💩e"
); );
} }
#[test]
fn test_dict() {
#[derive(Serialize)]
struct A {
a: i32,
}
assert_eq!(to_string(&A{a: 23}).unwrap(), "d1:ai23ee");
#[derive(Serialize)]
struct B {
l: Vec<i16>,
m: HashMap<String, i32>,
o: Option<String>,
o2: Option<String>,
}
assert_eq!(to_string(&B{
l: vec![3, 7, 9],
m: HashMap::from([
("foo".to_string(), 23),
("bar".to_string(), 18),
]),
o: Some("baz".to_string()),
o2: None,
}).unwrap(),
"d1:lli3ei7ei9ee1:md3:bari18e3:fooi23ee1:o3:baze"
)
}
} }