torrust_tracker_contrib_bencode/mutable/
bencode_mut.rs1use std::borrow::Cow;
2use std::collections::BTreeMap;
3use std::str;
4
5use crate::access::bencode::{BMutAccess, BRefAccess, MutKind, RefKind};
6use crate::access::dict::BDictAccess;
7use crate::access::list::BListAccess;
8use crate::mutable::encode;
9
10#[derive(Debug, Eq, PartialEq, Clone, Hash)]
12pub enum Inner<'a> {
13 Int(i64),
15 Bytes(Cow<'a, [u8]>),
17 List(Vec<BencodeMut<'a>>),
19 Dict(BTreeMap<Cow<'a, [u8]>, BencodeMut<'a>>),
21}
22
23#[derive(Debug, Eq, PartialEq, Clone, Hash)]
25pub struct BencodeMut<'a> {
26 inner: Inner<'a>,
27}
28
29impl<'a> BencodeMut<'a> {
30 fn new(inner: Inner<'a>) -> BencodeMut<'a> {
31 BencodeMut { inner }
32 }
33
34 #[must_use]
36 pub fn new_int(value: i64) -> BencodeMut<'a> {
37 BencodeMut::new(Inner::Int(value))
38 }
39
40 #[must_use]
42 pub fn new_bytes(value: Cow<'a, [u8]>) -> BencodeMut<'a> {
43 BencodeMut::new(Inner::Bytes(value))
44 }
45
46 #[must_use]
48 pub fn new_list() -> BencodeMut<'a> {
49 BencodeMut::new(Inner::List(Vec::new()))
50 }
51
52 #[must_use]
54 pub fn new_dict() -> BencodeMut<'a> {
55 BencodeMut::new(Inner::Dict(BTreeMap::new()))
56 }
57
58 #[must_use]
60 pub fn encode(&self) -> Vec<u8> {
61 let mut buffer = Vec::new();
62
63 encode::encode(self, &mut buffer);
64
65 buffer
66 }
67}
68
69impl<'a> BRefAccess for BencodeMut<'a> {
70 type BKey = Cow<'a, [u8]>;
71 type BType = BencodeMut<'a>;
72
73 fn kind<'b>(&'b self) -> RefKind<'b, Cow<'a, [u8]>, BencodeMut<'a>> {
74 match self.inner {
75 Inner::Int(n) => RefKind::Int(n),
76 Inner::Bytes(ref n) => RefKind::Bytes(n),
77 Inner::List(ref n) => RefKind::List(n),
78 Inner::Dict(ref n) => RefKind::Dict(n),
79 }
80 }
81
82 fn str(&self) -> Option<&str> {
83 let bytes = self.bytes()?;
84
85 match str::from_utf8(bytes) {
86 Ok(n) => Some(n),
87 Err(_) => None,
88 }
89 }
90
91 fn int(&self) -> Option<i64> {
92 match self.inner {
93 Inner::Int(n) => Some(n),
94 _ => None,
95 }
96 }
97
98 fn bytes(&self) -> Option<&[u8]> {
99 match self.inner {
100 Inner::Bytes(ref n) => Some(n.as_ref()),
101 _ => None,
102 }
103 }
104
105 fn list(&self) -> Option<&dyn BListAccess<BencodeMut<'a>>> {
106 match self.inner {
107 Inner::List(ref n) => Some(n),
108 _ => None,
109 }
110 }
111
112 fn dict(&self) -> Option<&dyn BDictAccess<Cow<'a, [u8]>, BencodeMut<'a>>> {
113 match self.inner {
114 Inner::Dict(ref n) => Some(n),
115 _ => None,
116 }
117 }
118}
119
120impl<'a> BMutAccess for BencodeMut<'a> {
121 fn kind_mut<'b>(&'b mut self) -> MutKind<'b, Cow<'a, [u8]>, BencodeMut<'a>> {
122 match self.inner {
123 Inner::Int(n) => MutKind::Int(n),
124 Inner::Bytes(ref mut n) => MutKind::Bytes((*n).as_ref()),
125 Inner::List(ref mut n) => MutKind::List(n),
126 Inner::Dict(ref mut n) => MutKind::Dict(n),
127 }
128 }
129
130 fn list_mut(&mut self) -> Option<&mut dyn BListAccess<BencodeMut<'a>>> {
131 match self.inner {
132 Inner::List(ref mut n) => Some(n),
133 _ => None,
134 }
135 }
136
137 fn dict_mut(&mut self) -> Option<&mut dyn BDictAccess<Cow<'a, [u8]>, BencodeMut<'a>>> {
138 match self.inner {
139 Inner::Dict(ref mut n) => Some(n),
140 _ => None,
141 }
142 }
143}
144
145#[cfg(test)]
166mod test {
167 use crate::access::bencode::BMutAccess;
168 use crate::mutable::bencode_mut::BencodeMut;
169
170 #[test]
171 fn positive_int_encode() {
172 let bencode_int = BencodeMut::new_int(-560);
173
174 let int_bytes = b"i-560e"; assert_eq!(&int_bytes[..], &bencode_int.encode()[..]);
176 }
177
178 #[test]
179 fn positive_bytes_encode() {
180 let bencode_bytes = BencodeMut::new_bytes((&b"asdasd"[..]).into());
182
183 let bytes_bytes = b"6:asdasd"; assert_eq!(&bytes_bytes[..], &bencode_bytes.encode()[..]);
185 }
186
187 #[test]
188 fn positive_empty_list_encode() {
189 let bencode_list = BencodeMut::new_list();
190
191 let list_bytes = b"le"; assert_eq!(&list_bytes[..], &bencode_list.encode()[..]);
193 }
194
195 #[test]
196 fn positive_nonempty_list_encode() {
197 let mut bencode_list = BencodeMut::new_list();
198
199 {
200 let list_mut = bencode_list.list_mut().unwrap();
201 list_mut.push(BencodeMut::new_int(56));
202 }
203
204 let list_bytes = b"li56ee"; assert_eq!(&list_bytes[..], &bencode_list.encode()[..]);
206 }
207
208 #[test]
209 fn positive_empty_dict_encode() {
210 let bencode_dict = BencodeMut::new_dict();
211
212 let dict_bytes = b"de"; assert_eq!(&dict_bytes[..], &bencode_dict.encode()[..]);
214 }
215
216 #[test]
217 fn positive_nonempty_dict_encode() {
218 let mut bencode_dict = BencodeMut::new_dict();
219
220 {
221 let dict_mut = bencode_dict.dict_mut().unwrap();
222 dict_mut.insert((&b"asd"[..]).into(), BencodeMut::new_bytes((&b"asdasd"[..]).into()));
224 }
225
226 let dict_bytes = b"d3:asd6:asdasde"; assert_eq!(&dict_bytes[..], &bencode_dict.encode()[..]);
228 }
229}