Skip to main content

irontide_bencode/
ser.rs

1#![allow(
2    clippy::cast_possible_wrap,
3    reason = "M175: bencode `u64 → i64` for serializer compat — bencode integers are i64 by spec; user values > i64::MAX would round-trip incorrectly but are vanishingly rare in real torrents"
4)]
5
6use serde::ser::{self, Serialize};
7use std::io::Write;
8
9use crate::error::{Error, Result};
10
11/// Bencode serializer.
12///
13/// Writes bencode-encoded data to any `std::io::Write` sink.
14pub struct Serializer<W> {
15    writer: W,
16}
17
18impl<W: Write> Serializer<W> {
19    /// Create a new serializer writing to the given sink.
20    pub fn new(writer: W) -> Self {
21        Self { writer }
22    }
23
24    fn write_byte_string(&mut self, v: &[u8]) -> Result<()> {
25        write!(self.writer, "{}:", v.len()).map_err(|e| Error::Custom(e.to_string()))?;
26        self.writer
27            .write_all(v)
28            .map_err(|e| Error::Custom(e.to_string()))
29    }
30
31    fn write_integer(&mut self, v: i64) -> Result<()> {
32        write!(self.writer, "i{v}e").map_err(|e| Error::Custom(e.to_string()))
33    }
34}
35
36impl<'a, W: Write> ser::Serializer for &'a mut Serializer<W> {
37    type Ok = ();
38    type Error = Error;
39    type SerializeSeq = &'a mut Serializer<W>;
40    type SerializeTuple = &'a mut Serializer<W>;
41    type SerializeTupleStruct = &'a mut Serializer<W>;
42    type SerializeTupleVariant = &'a mut Serializer<W>;
43    type SerializeMap = SortedMapSerializer<'a, W>;
44    type SerializeStruct = SortedMapSerializer<'a, W>;
45    type SerializeStructVariant = SortedMapSerializer<'a, W>;
46
47    fn serialize_bool(self, v: bool) -> Result<()> {
48        self.write_integer(i64::from(v))
49    }
50
51    fn serialize_i8(self, v: i8) -> Result<()> {
52        self.write_integer(i64::from(v))
53    }
54
55    fn serialize_i16(self, v: i16) -> Result<()> {
56        self.write_integer(i64::from(v))
57    }
58
59    fn serialize_i32(self, v: i32) -> Result<()> {
60        self.write_integer(i64::from(v))
61    }
62
63    fn serialize_i64(self, v: i64) -> Result<()> {
64        self.write_integer(v)
65    }
66
67    fn serialize_u8(self, v: u8) -> Result<()> {
68        self.write_integer(i64::from(v))
69    }
70
71    fn serialize_u16(self, v: u16) -> Result<()> {
72        self.write_integer(i64::from(v))
73    }
74
75    fn serialize_u32(self, v: u32) -> Result<()> {
76        self.write_integer(i64::from(v))
77    }
78
79    fn serialize_u64(self, v: u64) -> Result<()> {
80        self.write_integer(v as i64)
81    }
82
83    fn serialize_f32(self, _v: f32) -> Result<()> {
84        Err(Error::Custom("bencode does not support floats".into()))
85    }
86
87    fn serialize_f64(self, _v: f64) -> Result<()> {
88        Err(Error::Custom("bencode does not support floats".into()))
89    }
90
91    fn serialize_char(self, v: char) -> Result<()> {
92        let mut buf = [0u8; 4];
93        let s = v.encode_utf8(&mut buf);
94        self.write_byte_string(s.as_bytes())
95    }
96
97    fn serialize_str(self, v: &str) -> Result<()> {
98        self.write_byte_string(v.as_bytes())
99    }
100
101    fn serialize_bytes(self, v: &[u8]) -> Result<()> {
102        self.write_byte_string(v)
103    }
104
105    fn serialize_none(self) -> Result<()> {
106        Err(Error::Custom("bencode does not support None/null".into()))
107    }
108
109    fn serialize_some<T: ?Sized + Serialize>(self, value: &T) -> Result<()> {
110        value.serialize(self)
111    }
112
113    fn serialize_unit(self) -> Result<()> {
114        Err(Error::Custom("bencode does not support unit".into()))
115    }
116
117    fn serialize_unit_struct(self, _name: &'static str) -> Result<()> {
118        Err(Error::Custom(
119            "bencode does not support unit structs".into(),
120        ))
121    }
122
123    fn serialize_unit_variant(
124        self,
125        _name: &'static str,
126        _variant_index: u32,
127        variant: &'static str,
128    ) -> Result<()> {
129        self.write_byte_string(variant.as_bytes())
130    }
131
132    fn serialize_newtype_struct<T: ?Sized + Serialize>(
133        self,
134        _name: &'static str,
135        value: &T,
136    ) -> Result<()> {
137        value.serialize(self)
138    }
139
140    fn serialize_newtype_variant<T: ?Sized + Serialize>(
141        self,
142        _name: &'static str,
143        _variant_index: u32,
144        variant: &'static str,
145        value: &T,
146    ) -> Result<()> {
147        self.writer
148            .write_all(b"d")
149            .map_err(|e| Error::Custom(e.to_string()))?;
150        self.write_byte_string(variant.as_bytes())?;
151        value.serialize(&mut *self)?;
152        self.writer
153            .write_all(b"e")
154            .map_err(|e| Error::Custom(e.to_string()))
155    }
156
157    fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq> {
158        self.writer
159            .write_all(b"l")
160            .map_err(|e| Error::Custom(e.to_string()))?;
161        Ok(self)
162    }
163
164    fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple> {
165        self.serialize_seq(Some(len))
166    }
167
168    fn serialize_tuple_struct(
169        self,
170        _name: &'static str,
171        len: usize,
172    ) -> Result<Self::SerializeTupleStruct> {
173        self.serialize_seq(Some(len))
174    }
175
176    fn serialize_tuple_variant(
177        self,
178        _name: &'static str,
179        _variant_index: u32,
180        variant: &'static str,
181        _len: usize,
182    ) -> Result<Self::SerializeTupleVariant> {
183        self.writer
184            .write_all(b"d")
185            .map_err(|e| Error::Custom(e.to_string()))?;
186        self.write_byte_string(variant.as_bytes())?;
187        self.writer
188            .write_all(b"l")
189            .map_err(|e| Error::Custom(e.to_string()))?;
190        Ok(self)
191    }
192
193    fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap> {
194        Ok(SortedMapSerializer::new(self))
195    }
196
197    fn serialize_struct(self, _name: &'static str, _len: usize) -> Result<Self::SerializeStruct> {
198        Ok(SortedMapSerializer::new(self))
199    }
200
201    fn serialize_struct_variant(
202        self,
203        _name: &'static str,
204        _variant_index: u32,
205        variant: &'static str,
206        _len: usize,
207    ) -> Result<Self::SerializeStructVariant> {
208        // Wrap in a dict: d<variant><dict-value>e
209        // The outer dict is handled by the caller; we buffer this inner dict.
210        // Actually, for struct variants we need to write the outer dict key.
211        self.writer
212            .write_all(b"d")
213            .map_err(|e| Error::Custom(e.to_string()))?;
214        self.write_byte_string(variant.as_bytes())?;
215        Ok(SortedMapSerializer::new_nested(self))
216    }
217}
218
219// Sequence serialization
220impl<W: Write> ser::SerializeSeq for &mut Serializer<W> {
221    type Ok = ();
222    type Error = Error;
223
224    fn serialize_element<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<()> {
225        value.serialize(&mut **self)
226    }
227
228    fn end(self) -> Result<()> {
229        self.writer
230            .write_all(b"e")
231            .map_err(|e| Error::Custom(e.to_string()))
232    }
233}
234
235impl<W: Write> ser::SerializeTuple for &mut Serializer<W> {
236    type Ok = ();
237    type Error = Error;
238
239    fn serialize_element<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<()> {
240        ser::SerializeSeq::serialize_element(self, value)
241    }
242
243    fn end(self) -> Result<()> {
244        ser::SerializeSeq::end(self)
245    }
246}
247
248impl<W: Write> ser::SerializeTupleStruct for &mut Serializer<W> {
249    type Ok = ();
250    type Error = Error;
251
252    fn serialize_field<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<()> {
253        ser::SerializeSeq::serialize_element(self, value)
254    }
255
256    fn end(self) -> Result<()> {
257        ser::SerializeSeq::end(self)
258    }
259}
260
261impl<W: Write> ser::SerializeTupleVariant for &mut Serializer<W> {
262    type Ok = ();
263    type Error = Error;
264
265    fn serialize_field<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<()> {
266        ser::SerializeSeq::serialize_element(self, value)
267    }
268
269    fn end(self) -> Result<()> {
270        // Close list, then close outer dict
271        self.writer
272            .write_all(b"e")
273            .map_err(|e| Error::Custom(e.to_string()))?;
274        self.writer
275            .write_all(b"e")
276            .map_err(|e| Error::Custom(e.to_string()))
277    }
278}
279
280/// Buffering map serializer that sorts keys before writing.
281///
282/// BEP 3 requires dictionary keys to be in sorted order. We buffer all
283/// key-value pairs, sort by key, then write them all at once in `end()`.
284pub struct SortedMapSerializer<'a, W> {
285    ser: &'a mut Serializer<W>,
286    entries: Vec<(Vec<u8>, Vec<u8>)>,
287    current_key: Option<Vec<u8>>,
288    /// If true, we need to close an outer dict wrapper on `end()`.
289    nested: bool,
290}
291
292impl<'a, W: Write> SortedMapSerializer<'a, W> {
293    fn new(ser: &'a mut Serializer<W>) -> Self {
294        SortedMapSerializer {
295            ser,
296            entries: Vec::new(),
297            current_key: None,
298            nested: false,
299        }
300    }
301
302    fn new_nested(ser: &'a mut Serializer<W>) -> Self {
303        SortedMapSerializer {
304            ser,
305            entries: Vec::new(),
306            current_key: None,
307            nested: true,
308        }
309    }
310
311    fn flush_sorted(&mut self) -> Result<()> {
312        self.entries.sort_by(|a, b| a.0.cmp(&b.0));
313        self.ser
314            .writer
315            .write_all(b"d")
316            .map_err(|e| Error::Custom(e.to_string()))?;
317        for (key, value) in &self.entries {
318            self.ser.write_byte_string(key)?;
319            self.ser
320                .writer
321                .write_all(value)
322                .map_err(|e| Error::Custom(e.to_string()))?;
323        }
324        self.ser
325            .writer
326            .write_all(b"e")
327            .map_err(|e| Error::Custom(e.to_string()))
328    }
329}
330
331impl<W: Write> ser::SerializeMap for SortedMapSerializer<'_, W> {
332    type Ok = ();
333    type Error = Error;
334
335    fn serialize_key<T: ?Sized + Serialize>(&mut self, key: &T) -> Result<()> {
336        let mut buf = Vec::new();
337        let mut key_ser = Serializer::new(&mut buf);
338        key.serialize(&mut key_ser)?;
339        // Extract the raw key bytes from the serialized bencode string.
340        // Keys serialize as `<len>:<bytes>`, so we need the raw bytes.
341        self.current_key = Some(extract_string_content(&buf)?);
342        Ok(())
343    }
344
345    fn serialize_value<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<()> {
346        let key = self
347            .current_key
348            .take()
349            .ok_or_else(|| Error::Custom("serialize_value called before serialize_key".into()))?;
350        let mut buf = Vec::new();
351        let mut val_ser = Serializer::new(&mut buf);
352        value.serialize(&mut val_ser)?;
353        self.entries.push((key, buf));
354        Ok(())
355    }
356
357    fn end(mut self) -> Result<()> {
358        self.flush_sorted()?;
359        if self.nested {
360            self.ser
361                .writer
362                .write_all(b"e")
363                .map_err(|e| Error::Custom(e.to_string()))?;
364        }
365        Ok(())
366    }
367}
368
369impl<W: Write> ser::SerializeStruct for SortedMapSerializer<'_, W> {
370    type Ok = ();
371    type Error = Error;
372
373    fn serialize_field<T: ?Sized + Serialize>(
374        &mut self,
375        key: &'static str,
376        value: &T,
377    ) -> Result<()> {
378        let mut buf = Vec::new();
379        let mut val_ser = Serializer::new(&mut buf);
380        value.serialize(&mut val_ser)?;
381        self.entries.push((key.as_bytes().to_vec(), buf));
382        Ok(())
383    }
384
385    fn end(mut self) -> Result<()> {
386        self.flush_sorted()?;
387        if self.nested {
388            self.ser
389                .writer
390                .write_all(b"e")
391                .map_err(|e| Error::Custom(e.to_string()))?;
392        }
393        Ok(())
394    }
395
396    fn skip_field(&mut self, _key: &'static str) -> Result<()> {
397        Ok(())
398    }
399}
400
401impl<W: Write> ser::SerializeStructVariant for SortedMapSerializer<'_, W> {
402    type Ok = ();
403    type Error = Error;
404
405    fn serialize_field<T: ?Sized + Serialize>(
406        &mut self,
407        key: &'static str,
408        value: &T,
409    ) -> Result<()> {
410        ser::SerializeStruct::serialize_field(self, key, value)
411    }
412
413    fn end(self) -> Result<()> {
414        ser::SerializeStruct::end(self)
415    }
416}
417
418/// Extract the raw byte content from a bencode-encoded string `<len>:<data>`.
419fn extract_string_content(encoded: &[u8]) -> Result<Vec<u8>> {
420    let colon_pos = encoded
421        .iter()
422        .position(|&b| b == b':')
423        .ok_or_else(|| Error::Custom("map key must be a string".into()))?;
424    Ok(encoded[colon_pos + 1..].to_vec())
425}
426
427#[cfg(test)]
428mod tests {
429    use serde::Serialize;
430
431    #[test]
432    fn serialize_integer() {
433        assert_eq!(to_bytes(&42i64), b"i42e");
434        assert_eq!(to_bytes(&0i64), b"i0e");
435        assert_eq!(to_bytes(&-1i64), b"i-1e");
436    }
437
438    #[test]
439    fn serialize_string() {
440        assert_eq!(to_bytes("spam"), b"4:spam");
441        assert_eq!(to_bytes(""), b"0:");
442    }
443
444    #[test]
445    fn serialize_list() {
446        let list = vec!["spam", "eggs"];
447        assert_eq!(to_bytes(&list), b"l4:spam4:eggse");
448    }
449
450    #[test]
451    fn serialize_struct_sorted_keys() {
452        #[derive(Serialize)]
453        struct Test {
454            zebra: i64,
455            alpha: i64,
456        }
457        let val = Test { zebra: 2, alpha: 1 };
458        // Keys must be sorted: alpha before zebra
459        assert_eq!(to_bytes(&val), b"d5:alphai1e5:zebrai2ee");
460    }
461
462    fn to_bytes<T: Serialize + ?Sized>(value: &T) -> Vec<u8> {
463        crate::to_bytes(value).unwrap()
464    }
465}