/rust/registry/src/index.crates.io-1949cf8c6b5b557f/bendy-0.3.3/src/value.rs
Line | Count | Source |
1 | | //! `Value`s hold arbitrary borrowed or owneed bencode data. Unlike `Objects`, |
2 | | //! they can be cloned and traversed multiple times. |
3 | | //! |
4 | | //! `Value` implements `FromBencode`, `ToBencode`. If the `serde` feature is |
5 | | //! enabled, it also implements `Serialize` and `Deserialize`. |
6 | | |
7 | | use alloc::{ |
8 | | borrow::{Cow, ToOwned}, |
9 | | collections::BTreeMap, |
10 | | vec::Vec, |
11 | | }; |
12 | | |
13 | | #[cfg(feature = "serde")] |
14 | | use std::{ |
15 | | convert::TryInto, |
16 | | fmt::{self, Formatter}, |
17 | | marker::PhantomData, |
18 | | }; |
19 | | |
20 | | #[cfg(feature = "serde")] |
21 | | use serde_ as serde; |
22 | | |
23 | | #[cfg(feature = "serde")] |
24 | | use serde::{ |
25 | | ser::{SerializeMap, SerializeSeq}, |
26 | | Serialize, |
27 | | }; |
28 | | |
29 | | use crate::{ |
30 | | decoding::{FromBencode, Object}, |
31 | | encoding::{SingleItemEncoder, ToBencode}, |
32 | | }; |
33 | | |
34 | | /// An owned or borrowed bencoded value. |
35 | | #[derive(PartialEq, Eq, Clone, Debug)] |
36 | | pub enum Value<'a> { |
37 | | /// An owned or borrowed byte string |
38 | | Bytes(Cow<'a, [u8]>), |
39 | | /// A dictionary mapping byte strings to values |
40 | | Dict(BTreeMap<Cow<'a, [u8]>, Value<'a>>), |
41 | | /// A signed integer |
42 | | Integer(i64), |
43 | | /// A list of values |
44 | | List(Vec<Value<'a>>), |
45 | | } |
46 | | |
47 | | impl<'a> Value<'a> { |
48 | | /// Convert this Value into an owned Value with static lifetime |
49 | 0 | pub fn into_owned(self) -> Value<'static> { |
50 | 0 | match self { |
51 | 0 | Value::Bytes(bytes) => Value::Bytes(Cow::Owned(bytes.into_owned())), |
52 | 0 | Value::Dict(dict) => Value::Dict( |
53 | 0 | dict.into_iter() |
54 | 0 | .map(|(key, value)| (Cow::Owned(key.into_owned()), value.into_owned())) Unexecuted instantiation: <bendy::value::Value>::into_owned::{closure#0}Unexecuted instantiation: <bendy::value::Value>::into_owned::{closure#0} |
55 | 0 | .collect(), |
56 | | ), |
57 | 0 | Value::Integer(integer) => Value::Integer(integer), |
58 | 0 | Value::List(list) => Value::List(list.into_iter().map(Value::into_owned).collect()), |
59 | | } |
60 | 0 | } Unexecuted instantiation: <bendy::value::Value>::into_owned Unexecuted instantiation: <bendy::value::Value>::into_owned |
61 | | } |
62 | | |
63 | | impl<'a> ToBencode for Value<'a> { |
64 | | // This leaves some room for external containers. |
65 | | // TODO(#38): Change this to 0 for v0.4 |
66 | | const MAX_DEPTH: usize = usize::max_value() / 4; |
67 | | |
68 | 0 | fn encode(&self, encoder: SingleItemEncoder) -> Result<(), crate::encoding::Error> { |
69 | 0 | match self { |
70 | 0 | Value::Bytes(bytes) => encoder.emit_bytes(bytes), |
71 | 0 | Value::Dict(dict) => dict.encode(encoder), |
72 | 0 | Value::Integer(integer) => integer.encode(encoder), |
73 | 0 | Value::List(list) => list.encode(encoder), |
74 | | } |
75 | 0 | } Unexecuted instantiation: <bendy::value::Value as bendy::encoding::to_bencode::ToBencode>::encode Unexecuted instantiation: <bendy::value::Value as bendy::encoding::to_bencode::ToBencode>::encode |
76 | | } |
77 | | |
78 | | impl<'a> FromBencode for Value<'a> { |
79 | | const EXPECTED_RECURSION_DEPTH: usize = <Self as ToBencode>::MAX_DEPTH; |
80 | | |
81 | 0 | fn decode_bencode_object(object: Object) -> Result<Self, crate::decoding::Error> { |
82 | 0 | match object { |
83 | 0 | Object::Bytes(bytes) => Ok(Value::Bytes(Cow::Owned(bytes.to_owned()))), |
84 | 0 | Object::Dict(mut decoder) => { |
85 | 0 | let mut dict = BTreeMap::new(); |
86 | 0 | while let Some((key, value)) = decoder.next_pair()? { |
87 | 0 | dict.insert( |
88 | 0 | Cow::Owned(key.to_owned()), |
89 | 0 | Value::decode_bencode_object(value)?, |
90 | | ); |
91 | | } |
92 | 0 | Ok(Value::Dict(dict)) |
93 | | }, |
94 | 0 | Object::Integer(text) => Ok(Value::Integer(text.parse()?)), |
95 | 0 | Object::List(mut decoder) => { |
96 | 0 | let mut list = Vec::new(); |
97 | 0 | while let Some(object) = decoder.next_object()? { |
98 | 0 | list.push(Value::decode_bencode_object(object)?); |
99 | | } |
100 | 0 | Ok(Value::List(list)) |
101 | | }, |
102 | | } |
103 | 0 | } Unexecuted instantiation: <bendy::value::Value as bendy::decoding::from_bencode::FromBencode>::decode_bencode_object Unexecuted instantiation: <bendy::value::Value as bendy::decoding::from_bencode::FromBencode>::decode_bencode_object |
104 | | } |
105 | | |
106 | | #[cfg(feature = "serde")] |
107 | | mod serde_impls { |
108 | | use super::*; |
109 | | |
110 | | use serde_bytes::Bytes; |
111 | | |
112 | | impl<'a> Serialize for Value<'a> { |
113 | | fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> |
114 | | where |
115 | | S: serde::ser::Serializer, |
116 | | { |
117 | | match self { |
118 | | Value::Bytes(string) => serializer.serialize_bytes(string), |
119 | | Value::Integer(int) => serializer.serialize_i64(*int), |
120 | | Value::List(list) => { |
121 | | let mut seed = serializer.serialize_seq(Some(list.len()))?; |
122 | | for value in list { |
123 | | seed.serialize_element(value)?; |
124 | | } |
125 | | seed.end() |
126 | | }, |
127 | | Value::Dict(dict) => { |
128 | | let mut seed = serializer.serialize_map(Some(dict.len()))?; |
129 | | for (k, v) in dict { |
130 | | let bytes = Bytes::new(k); |
131 | | seed.serialize_entry(bytes, v)?; |
132 | | } |
133 | | seed.end() |
134 | | }, |
135 | | } |
136 | | } |
137 | | } |
138 | | |
139 | | impl<'de: 'a, 'a> serde::de::Deserialize<'de> for Value<'a> { |
140 | | #[inline] |
141 | | fn deserialize<D>(deserializer: D) -> Result<Value<'a>, D::Error> |
142 | | where |
143 | | D: serde::de::Deserializer<'de>, |
144 | | { |
145 | | deserializer.deserialize_any(Visitor(PhantomData)) |
146 | | } |
147 | | } |
148 | | |
149 | | struct Visitor<'a>(PhantomData<&'a ()>); |
150 | | |
151 | | impl<'de: 'a, 'a> serde::de::Visitor<'de> for Visitor<'a> { |
152 | | type Value = Value<'a>; |
153 | | |
154 | | fn expecting(&self, formatter: &mut Formatter) -> fmt::Result { |
155 | | formatter.write_str("any valid BEncode value") |
156 | | } |
157 | | |
158 | | fn visit_i64<E>(self, value: i64) -> Result<Value<'a>, E> { |
159 | | Ok(Value::Integer(value)) |
160 | | } |
161 | | |
162 | | fn visit_u64<E>(self, value: u64) -> Result<Value<'a>, E> { |
163 | | Ok(Value::Integer(value.try_into().unwrap())) |
164 | | } |
165 | | |
166 | | fn visit_borrowed_bytes<E>(self, value: &'de [u8]) -> Result<Value<'a>, E> |
167 | | where |
168 | | E: serde::de::Error, |
169 | | { |
170 | | Ok(Value::Bytes(Cow::Borrowed(value))) |
171 | | } |
172 | | |
173 | | fn visit_borrowed_str<E>(self, value: &'de str) -> Result<Value<'a>, E> |
174 | | where |
175 | | E: serde::de::Error, |
176 | | { |
177 | | Ok(Value::Bytes(Cow::Borrowed(value.as_bytes()))) |
178 | | } |
179 | | |
180 | | fn visit_string<E>(self, value: String) -> Result<Value<'a>, E> { |
181 | | Ok(Value::Bytes(Cow::Owned(value.into_bytes()))) |
182 | | } |
183 | | |
184 | | fn visit_byte_buf<E>(self, value: Vec<u8>) -> Result<Value<'a>, E> { |
185 | | Ok(Value::Bytes(Cow::Owned(value))) |
186 | | } |
187 | | |
188 | | fn visit_seq<V>(self, mut access: V) -> Result<Value<'a>, V::Error> |
189 | | where |
190 | | V: serde::de::SeqAccess<'de>, |
191 | | { |
192 | | let mut list = Vec::new(); |
193 | | while let Some(e) = access.next_element()? { |
194 | | list.push(e); |
195 | | } |
196 | | Ok(Value::List(list)) |
197 | | } |
198 | | |
199 | | fn visit_map<V>(self, mut access: V) -> Result<Value<'a>, V::Error> |
200 | | where |
201 | | V: serde::de::MapAccess<'de>, |
202 | | { |
203 | | let mut map = BTreeMap::new(); |
204 | | while let Some((k, v)) = access.next_entry::<&Bytes, _>()? { |
205 | | map.insert(Cow::Borrowed(k.as_ref()), v); |
206 | | } |
207 | | Ok(Value::Dict(map)) |
208 | | } |
209 | | } |
210 | | } |
211 | | |
212 | | #[cfg(test)] |
213 | | mod tests { |
214 | | use super::*; |
215 | | |
216 | | use alloc::{string::String, vec}; |
217 | | |
218 | | fn case(value: Value, expected: impl AsRef<[u8]>) { |
219 | | let expected = expected.as_ref(); |
220 | | |
221 | | let encoded = match value.to_bencode() { |
222 | | Ok(bytes) => bytes, |
223 | | Err(err) => panic!("Failed to encode `{:?}`: {}", value, err), |
224 | | }; |
225 | | |
226 | | if encoded != expected { |
227 | | panic!( |
228 | | "Expected `{:?}` to encode as `{}`, but got `{}", |
229 | | value, |
230 | | String::from_utf8_lossy(expected), |
231 | | String::from_utf8_lossy(&encoded) |
232 | | ) |
233 | | } |
234 | | |
235 | | let decoded = match Value::from_bencode(&encoded) { |
236 | | Ok(decoded) => decoded, |
237 | | Err(err) => panic!( |
238 | | "Failed to decode value from `{}`: {}", |
239 | | String::from_utf8_lossy(&encoded), |
240 | | err, |
241 | | ), |
242 | | }; |
243 | | |
244 | | assert_eq!(decoded, value); |
245 | | |
246 | | #[cfg(feature = "serde")] |
247 | | { |
248 | | let deserialized = match crate::serde::de::from_bytes::<Value>(expected) { |
249 | | Ok(deserialized) => deserialized, |
250 | | Err(err) => panic!( |
251 | | "Failed to deserialize value from `{}`: {}", |
252 | | String::from_utf8_lossy(&expected), |
253 | | err |
254 | | ), |
255 | | }; |
256 | | |
257 | | if deserialized != value { |
258 | | panic!( |
259 | | "Deserialize Serialize produced unexpected value: `{:?}` != `{:?}`", |
260 | | deserialized, value |
261 | | ); |
262 | | } |
263 | | |
264 | | let serialized = match crate::serde::ser::to_bytes(&value) { |
265 | | Ok(serialized) => serialized, |
266 | | Err(err) => panic!("Failed to serialize `{:?}`: {}", value, err), |
267 | | }; |
268 | | |
269 | | if serialized != expected { |
270 | | panic!( |
271 | | "Serialize Serialize produced unexpected bencode: `{:?}` != `{:?}`", |
272 | | String::from_utf8_lossy(&serialized), |
273 | | String::from_utf8_lossy(expected) |
274 | | ); |
275 | | } |
276 | | } |
277 | | } |
278 | | |
279 | | #[test] |
280 | | fn bytes() { |
281 | | case(Value::Bytes(Cow::Borrowed(&[1, 2, 3])), b"3:\x01\x02\x03"); |
282 | | case(Value::Bytes(Cow::Owned(vec![1, 2, 3])), b"3:\x01\x02\x03"); |
283 | | } |
284 | | |
285 | | #[test] |
286 | | fn dict() { |
287 | | case(Value::Dict(BTreeMap::new()), "de"); |
288 | | |
289 | | let mut dict = BTreeMap::new(); |
290 | | dict.insert(Cow::Borrowed("foo".as_bytes()), Value::Integer(1)); |
291 | | dict.insert(Cow::Borrowed("bar".as_bytes()), Value::Integer(2)); |
292 | | case(Value::Dict(dict), "d3:bari2e3:fooi1ee"); |
293 | | } |
294 | | |
295 | | #[test] |
296 | | fn integer() { |
297 | | case(Value::Integer(0), "i0e"); |
298 | | case(Value::Integer(-1), "i-1e"); |
299 | | } |
300 | | |
301 | | #[test] |
302 | | fn list() { |
303 | | case(Value::List(Vec::new()), "le"); |
304 | | case( |
305 | | Value::List(vec![ |
306 | | Value::Integer(0), |
307 | | Value::Bytes(Cow::Borrowed(&[1, 2, 3])), |
308 | | ]), |
309 | | b"li0e3:\x01\x02\x03e", |
310 | | ); |
311 | | } |
312 | | } |