bip_bencode/reference/
bencode_ref.rs1use access::bencode::BRefAccessExt;
2use std::collections::BTreeMap;
3use std::str;
4
5use access::bencode::{BRefAccess, BencodeRefKind};
6use reference::decode;
7use reference::decode_opt::BDecodeOpt;
8use access::dict::BDictAccess;
9use access::list::BListAccess;
10use error::{BencodeParseResult, BencodeParseError, BencodeParseErrorKind};
11
12#[derive(Debug, Eq, PartialEq, Clone, Hash)]
14pub enum InnerBencodeRef<'a> {
15 Int(i64, &'a [u8]),
17 Bytes(&'a [u8], &'a [u8]),
19 List(Vec<BencodeRef<'a>>, &'a [u8]),
21 Dict(BTreeMap<&'a [u8], BencodeRef<'a>>, &'a [u8]),
23}
24
25impl<'a> Into<BencodeRef<'a>> for InnerBencodeRef<'a> {
26 fn into(self) -> BencodeRef<'a> {
27 BencodeRef{ inner: self }
28 }
29}
30
31#[derive(Debug, Eq, PartialEq, Clone, Hash)]
33pub struct BencodeRef<'a> {
34 inner: InnerBencodeRef<'a>
35}
36
37impl<'a> BencodeRef<'a> {
38 pub fn decode(bytes: &'a [u8], opts: BDecodeOpt) -> BencodeParseResult<BencodeRef<'a>> {
40 let (bencode, end_pos) = try!(decode::decode(bytes, 0, opts, 0));
42
43 if end_pos != bytes.len() && opts.enforce_full_decode() {
44 return Err(BencodeParseError::from_kind(BencodeParseErrorKind::BytesEmpty{ pos: end_pos }));
45 }
46
47 Ok(bencode)
48 }
49
50 pub fn buffer(&self) -> &'a [u8] {
52 match self.inner {
53 InnerBencodeRef::Int(_, buffer) => buffer,
54 InnerBencodeRef::Bytes(_, buffer) => buffer,
55 InnerBencodeRef::List(_, buffer) => buffer,
56 InnerBencodeRef::Dict(_, buffer) => buffer
57 }
58 }
59}
60
61impl<'a> BRefAccess for BencodeRef<'a> {
62 type BKey = &'a [u8];
63 type BType = BencodeRef<'a>;
64
65 fn kind<'b>(&'b self) -> BencodeRefKind<'b, &'a [u8], BencodeRef<'a>> {
66 match self.inner {
67 InnerBencodeRef::Int(n, _) => BencodeRefKind::Int(n),
68 InnerBencodeRef::Bytes(ref n, _) => BencodeRefKind::Bytes(n),
69 InnerBencodeRef::List(ref n, _) => BencodeRefKind::List(n),
70 InnerBencodeRef::Dict(ref n, _) => BencodeRefKind::Dict(n),
71 }
72 }
73
74 fn str(&self) -> Option<&str> {
75 self.str_ext()
76 }
77
78 fn int(&self) -> Option<i64> {
79 match self.inner {
80 InnerBencodeRef::Int(n, _) => Some(n),
81 _ => None,
82 }
83 }
84
85 fn bytes(&self) -> Option<&[u8]> {
86 self.bytes_ext()
87 }
88
89 fn list(&self) -> Option<&BListAccess<BencodeRef<'a>>> {
90 match self.inner {
91 InnerBencodeRef::List(ref n, _) => Some(n),
92 _ => None,
93 }
94 }
95
96 fn dict(&self) -> Option<&BDictAccess<&'a [u8], BencodeRef<'a>>> {
97 match self.inner {
98 InnerBencodeRef::Dict(ref n, _) => Some(n),
99 _ => None,
100 }
101 }
102}
103
104impl<'a> BRefAccessExt<'a> for BencodeRef<'a> {
105 fn str_ext(&self) -> Option<&'a str> {
106 let bytes = match self.bytes_ext() {
107 Some(n) => n,
108 None => return None,
109 };
110
111 match str::from_utf8(bytes) {
112 Ok(n) => Some(n),
113 Err(_) => None,
114 }
115 }
116
117 fn bytes_ext(&self) -> Option<&'a [u8]> {
118 match self.inner {
119 InnerBencodeRef::Bytes(ref n, _) => Some(&n[0..]),
120 _ => None,
121 }
122 }
123}
124
125#[cfg(test)]
126mod tests {
127 use std::default::Default;
128
129 use access::bencode::BRefAccess;
130 use reference::bencode_ref::BencodeRef;
131 use reference::decode_opt::BDecodeOpt;
132
133 #[test]
134 fn positive_int_buffer() {
135 let int_bytes = b"i-500e";
136 let bencode = BencodeRef::decode(&int_bytes[..], BDecodeOpt::default()).unwrap();
137
138 assert_eq!(int_bytes, bencode.buffer());
139 }
140
141 #[test]
142 fn positive_bytes_buffer() {
143 let bytes_bytes = b"3:asd";
144 let bencode = BencodeRef::decode(&bytes_bytes[..], BDecodeOpt::default()).unwrap();
145
146 assert_eq!(bytes_bytes, bencode.buffer());
147 }
148
149 #[test]
150 fn positive_list_buffer() {
151 let list_bytes = b"l3:asde";
152 let bencode = BencodeRef::decode(&list_bytes[..], BDecodeOpt::default()).unwrap();
153
154 assert_eq!(list_bytes, bencode.buffer());
155 }
156
157 #[test]
158 fn positive_dict_buffer() {
159 let dict_bytes = b"d3:asd3:asde";
160 let bencode = BencodeRef::decode(&dict_bytes[..], BDecodeOpt::default()).unwrap();
161
162 assert_eq!(dict_bytes, bencode.buffer());
163 }
164
165 #[test]
166 fn positive_list_nested_int_buffer() {
167 let nested_int_bytes = b"li-500ee";
168 let bencode = BencodeRef::decode(&nested_int_bytes[..], BDecodeOpt::default()).unwrap();
169
170 let bencode_list = bencode.list().unwrap();
171 let bencode_int = bencode_list.get(0).unwrap();
172
173 let int_bytes = b"i-500e";
174 assert_eq!(int_bytes, bencode_int.buffer());
175 }
176
177 #[test]
178 fn positive_dict_nested_int_buffer() {
179 let nested_int_bytes = b"d3:asdi-500ee";
180 let bencode = BencodeRef::decode(&nested_int_bytes[..], BDecodeOpt::default()).unwrap();
181
182 let bencode_dict = bencode.dict().unwrap();
183 let bencode_int = bencode_dict.lookup(&b"asd"[..]).unwrap();
184
185 let int_bytes = b"i-500e";
186 assert_eq!(int_bytes, bencode_int.buffer());
187 }
188
189 #[test]
190 fn positive_list_nested_bytes_buffer() {
191 let nested_bytes_bytes = b"l3:asde";
192 let bencode = BencodeRef::decode(&nested_bytes_bytes[..], BDecodeOpt::default()).unwrap();
193
194 let bencode_list = bencode.list().unwrap();
195 let bencode_bytes = bencode_list.get(0).unwrap();
196
197 let bytes_bytes = b"3:asd";
198 assert_eq!(bytes_bytes, bencode_bytes.buffer());
199 }
200
201 #[test]
202 fn positive_dict_nested_bytes_buffer() {
203 let nested_bytes_bytes = b"d3:asd3:asde";
204 let bencode = BencodeRef::decode(&nested_bytes_bytes[..], BDecodeOpt::default()).unwrap();
205
206 let bencode_dict = bencode.dict().unwrap();
207 let bencode_bytes = bencode_dict.lookup(&b"asd"[..]).unwrap();
208
209 let bytes_bytes = b"3:asd";
210 assert_eq!(bytes_bytes, bencode_bytes.buffer());
211 }
212
213 #[test]
214 fn positive_list_nested_list_buffer() {
215 let nested_list_bytes = b"ll3:asdee";
216 let bencode = BencodeRef::decode(&nested_list_bytes[..], BDecodeOpt::default()).unwrap();
217
218 let bencode_list = bencode.list().unwrap();
219 let bencode_list = bencode_list.get(0).unwrap();
220
221 let list_bytes = b"l3:asde";
222 assert_eq!(list_bytes, bencode_list.buffer());
223 }
224
225 #[test]
226 fn positive_dict_nested_list_buffer() {
227 let nested_list_bytes = b"d3:asdl3:asdee";
228 let bencode = BencodeRef::decode(&nested_list_bytes[..], BDecodeOpt::default()).unwrap();
229
230 let bencode_dict = bencode.dict().unwrap();
231 let bencode_list = bencode_dict.lookup(&b"asd"[..]).unwrap();
232
233 let list_bytes = b"l3:asde";
234 assert_eq!(list_bytes, bencode_list.buffer());
235 }
236
237 #[test]
238 fn positive_list_nested_dict_buffer() {
239 let nested_dict_bytes = b"ld3:asd3:asdee";
240 let bencode = BencodeRef::decode(&nested_dict_bytes[..], BDecodeOpt::default()).unwrap();
241
242 let bencode_list = bencode.list().unwrap();
243 let bencode_dict = bencode_list.get(0).unwrap();
244
245 let dict_bytes = b"d3:asd3:asde";
246 assert_eq!(dict_bytes, bencode_dict.buffer());
247 }
248
249 #[test]
250 fn positive_dict_nested_dict_buffer() {
251 let nested_dict_bytes = b"d3:asdd3:asd3:asdee";
252 let bencode = BencodeRef::decode(&nested_dict_bytes[..], BDecodeOpt::default()).unwrap();
253
254 let bencode_dict = bencode.dict().unwrap();
255 let bencode_dict = bencode_dict.lookup(&b"asd"[..]).unwrap();
256
257 let dict_bytes = b"d3:asd3:asde";
258 assert_eq!(dict_bytes, bencode_dict.buffer());
259 }
260}