Skip to main content

irontide_bencode/
value.rs

1use std::collections::BTreeMap;
2use std::fmt;
3
4/// A dynamically-typed bencode value.
5///
6/// Useful for inspecting bencode data without a schema, and for
7/// `find_dict_key_span` operations.
8#[derive(Debug, Clone, PartialEq, Eq)]
9pub enum BencodeValue {
10    /// Integer: `i42e`
11    Integer(i64),
12    /// Byte string: `4:spam`
13    Bytes(Vec<u8>),
14    /// List: `l...e`
15    List(Vec<BencodeValue>),
16    /// Dictionary: `d...e` (keys sorted lexicographically)
17    Dict(BTreeMap<Vec<u8>, BencodeValue>),
18}
19
20impl BencodeValue {
21    /// Returns the integer value if this is a `BencodeValue::Integer`.
22    pub fn as_int(&self) -> Option<i64> {
23        match self {
24            BencodeValue::Integer(n) => Some(*n),
25            _ => None,
26        }
27    }
28
29    /// Returns the raw byte slice if this is a `BencodeValue::Bytes`.
30    pub fn as_bytes_raw(&self) -> Option<&[u8]> {
31        match self {
32            BencodeValue::Bytes(b) => Some(b),
33            _ => None,
34        }
35    }
36
37    /// Returns the list if this is a `BencodeValue::List`.
38    pub fn as_list(&self) -> Option<&[BencodeValue]> {
39        match self {
40            BencodeValue::List(items) => Some(items),
41            _ => None,
42        }
43    }
44
45    /// Returns the dictionary if this is a `BencodeValue::Dict`.
46    pub fn as_dict(&self) -> Option<&BTreeMap<Vec<u8>, BencodeValue>> {
47        match self {
48            BencodeValue::Dict(map) => Some(map),
49            _ => None,
50        }
51    }
52}
53
54impl fmt::Display for BencodeValue {
55    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
56        match self {
57            BencodeValue::Integer(n) => write!(f, "{n}"),
58            BencodeValue::Bytes(b) => match std::str::from_utf8(b) {
59                Ok(s) => write!(f, "\"{s}\""),
60                Err(_) => write!(f, "<{} bytes>", b.len()),
61            },
62            BencodeValue::List(items) => {
63                write!(f, "[")?;
64                for (i, item) in items.iter().enumerate() {
65                    if i > 0 {
66                        write!(f, ", ")?;
67                    }
68                    write!(f, "{item}")?;
69                }
70                write!(f, "]")
71            }
72            BencodeValue::Dict(map) => {
73                write!(f, "{{")?;
74                for (i, (key, val)) in map.iter().enumerate() {
75                    if i > 0 {
76                        write!(f, ", ")?;
77                    }
78                    match std::str::from_utf8(key) {
79                        Ok(s) => write!(f, "\"{s}\": {val}")?,
80                        Err(_) => write!(f, "<{} bytes>: {val}", key.len())?,
81                    }
82                }
83                write!(f, "}}")
84            }
85        }
86    }
87}
88
89impl serde::Serialize for BencodeValue {
90    fn serialize<S: serde::Serializer>(
91        &self,
92        serializer: S,
93    ) -> std::result::Result<S::Ok, S::Error> {
94        match self {
95            BencodeValue::Integer(n) => serializer.serialize_i64(*n),
96            BencodeValue::Bytes(b) => serializer.serialize_bytes(b),
97            BencodeValue::List(items) => {
98                use serde::ser::SerializeSeq;
99                let mut seq = serializer.serialize_seq(Some(items.len()))?;
100                for item in items {
101                    seq.serialize_element(item)?;
102                }
103                seq.end()
104            }
105            BencodeValue::Dict(map) => {
106                use serde::ser::SerializeMap;
107                let mut m = serializer.serialize_map(Some(map.len()))?;
108                for (key, val) in map {
109                    m.serialize_entry(&serde_bytes::Bytes::new(key), val)?;
110                }
111                m.end()
112            }
113        }
114    }
115}
116
117impl<'de> serde::Deserialize<'de> for BencodeValue {
118    fn deserialize<D: serde::Deserializer<'de>>(
119        deserializer: D,
120    ) -> std::result::Result<Self, D::Error> {
121        deserializer.deserialize_any(BencodeValueVisitor)
122    }
123}
124
125struct BencodeValueVisitor;
126
127impl<'de> serde::de::Visitor<'de> for BencodeValueVisitor {
128    type Value = BencodeValue;
129
130    fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
131        write!(f, "a bencode value")
132    }
133
134    fn visit_i64<E: serde::de::Error>(self, v: i64) -> std::result::Result<Self::Value, E> {
135        Ok(BencodeValue::Integer(v))
136    }
137
138    fn visit_u64<E: serde::de::Error>(self, v: u64) -> std::result::Result<Self::Value, E> {
139        Ok(BencodeValue::Integer(v as i64))
140    }
141
142    fn visit_bytes<E: serde::de::Error>(self, v: &[u8]) -> std::result::Result<Self::Value, E> {
143        Ok(BencodeValue::Bytes(v.to_vec()))
144    }
145
146    fn visit_borrowed_bytes<E: serde::de::Error>(
147        self,
148        v: &'de [u8],
149    ) -> std::result::Result<Self::Value, E> {
150        Ok(BencodeValue::Bytes(v.to_vec()))
151    }
152
153    fn visit_str<E: serde::de::Error>(self, v: &str) -> std::result::Result<Self::Value, E> {
154        Ok(BencodeValue::Bytes(v.as_bytes().to_vec()))
155    }
156
157    fn visit_seq<A: serde::de::SeqAccess<'de>>(
158        self,
159        mut seq: A,
160    ) -> std::result::Result<Self::Value, A::Error> {
161        let mut items = Vec::new();
162        while let Some(item) = seq.next_element()? {
163            items.push(item);
164        }
165        Ok(BencodeValue::List(items))
166    }
167
168    fn visit_map<A: serde::de::MapAccess<'de>>(
169        self,
170        mut map: A,
171    ) -> std::result::Result<Self::Value, A::Error> {
172        let mut dict = BTreeMap::new();
173        while let Some((key, val)) = map.next_entry::<serde_bytes::ByteBuf, BencodeValue>()? {
174            dict.insert(key.into_vec(), val);
175        }
176        Ok(BencodeValue::Dict(dict))
177    }
178}