Coverage Report

Created: 2026-08-14 07:34

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}