irontide_bencode/lib.rs
1#![warn(missing_docs)]
2//! Serde-based bencode codec for `BitTorrent`.
3//!
4//! Bencode is the serialization format used throughout `BitTorrent` for .torrent
5//! files, tracker responses, and DHT messages. It has four types:
6//!
7//! - **Integers**: `i42e`, `i-1e`, `i0e`
8//! - **Byte strings**: `4:spam` (length-prefixed)
9//! - **Lists**: `l<values>e`
10//! - **Dictionaries**: `d<key><value>...e` (keys are byte strings, sorted)
11//!
12//! # Usage
13//!
14//! ```
15//! use serde::{Serialize, Deserialize};
16//! use irontide_bencode::{to_bytes, from_bytes};
17//!
18//! #[derive(Serialize, Deserialize, PartialEq, Debug)]
19//! struct Torrent {
20//! announce: String,
21//! #[serde(rename = "piece length")]
22//! piece_length: i64,
23//! }
24//!
25//! let torrent = Torrent {
26//! announce: "http://tracker.example.com/announce".into(),
27//! piece_length: 262144,
28//! };
29//!
30//! let encoded = to_bytes(&torrent).unwrap();
31//! let decoded: Torrent = from_bytes(&encoded).unwrap();
32//! assert_eq!(torrent, decoded);
33//! ```
34
35mod de;
36mod error;
37mod ser;
38mod span;
39mod value;
40
41pub use de::Deserializer;
42pub use error::{Error, Result};
43pub use ser::Serializer;
44pub use span::find_dict_key_span;
45pub use value::BencodeValue;
46
47/// Serialize a value to bencode bytes.
48///
49/// # Errors
50///
51/// Returns an error if the value cannot be serialized to bencode.
52pub fn to_bytes<T: serde::Serialize + ?Sized>(value: &T) -> Result<Vec<u8>> {
53 let mut buf = Vec::new();
54 let mut serializer = Serializer::new(&mut buf);
55 serde::Serialize::serialize(value, &mut serializer)?;
56 Ok(buf)
57}
58
59/// Deserialize a value from bencode bytes.
60///
61/// Enforces BEP 3 dictionary key ordering. Use [`from_bytes_lenient`] for
62/// peer wire messages where real-world clients may send unsorted keys.
63///
64/// # Errors
65///
66/// Returns an error if the bytes are not valid bencode or cannot be deserialized into `T`.
67pub fn from_bytes<'de, T: serde::Deserialize<'de>>(bytes: &'de [u8]) -> Result<T> {
68 let mut deserializer = Deserializer::new(bytes);
69 let value = serde::Deserialize::deserialize(&mut deserializer)?;
70 deserializer.finish()?;
71 Ok(value)
72}
73
74/// Deserialize a value from bencode bytes, accepting unsorted dictionary keys.
75///
76/// Many real-world `BitTorrent` clients send extension handshakes and other
77/// messages with unsorted dictionary keys. This function accepts such input
78/// while still correctly parsing all bencode types.
79///
80/// # Errors
81///
82/// Returns an error if the bytes are not valid bencode or cannot be deserialized into `T`.
83pub fn from_bytes_lenient<'de, T: serde::Deserialize<'de>>(bytes: &'de [u8]) -> Result<T> {
84 let mut deserializer = Deserializer::lenient(bytes);
85 let value = serde::Deserialize::deserialize(&mut deserializer)?;
86 deserializer.finish()?;
87 Ok(value)
88}