1pub trait BElement<T> where T: BElement<T> {
29 fn decode(encoded: &[u8]) -> Result<(usize, T), &'static str>;
34}
35
36#[derive(Eq, PartialEq, Debug)]
38pub struct BNumber {
39 number: i64,
41}
42
43impl BNumber {
44 pub fn new(number: i64) -> BNumber {
46 BNumber { number: number }
47 }
48}
49
50impl BElement<BNumber> for BNumber {
51
52 fn decode(encoded: &[u8]) -> Result<(usize, BNumber), &'static str> {
85 if encoded.len() < 1 {
86 Err("empty string isn't valid BNumber")
87 } else {
88 match encoded[0] as char {
89 'i' => {
90 let mut i : usize = 1;
91 while i < encoded.len() && encoded[i] as char != 'e' {
92 i += 1;
93 }
94 if i == encoded.len() {
95 return Err("expected 'e' after number");
96 }
97 let number: &[u8] = &encoded[1..i];
98 let str_number: String = String::from_utf8_lossy(number).into_owned();
99 if let Ok(x) = str_number.parse::<i64>() {
100 Ok((i, BNumber::new(x)))
101 } else {
102 Err("expected correct i64 number")
103 }
104 },
105 _ => Err("expected 'i' before number")
106 }
107 }
108 }
109}
110
111#[derive(Eq, PartialEq, Debug)]
113pub struct BString {
114 data: String,
116}
117
118impl BString {
119 pub fn new(data: &[u8]) -> BString {
121 BString { data: String::from_utf8_lossy(data).into_owned() }
122 }
123}
124
125impl BElement<BString> for BString {
126 fn decode(encoded: &[u8]) -> Result<(usize, BString), &'static str> {
143 let mut i: usize = 0;
144 while i < encoded.len() && encoded[i] as char != ':' {
145 i += 1;
146 }
147 if i == encoded.len() {
148 Err("expected :, but end was found")
149 } else {
150 let length: &[u8] = &encoded[0..i];
151 if let Ok(x) = String::from_utf8_lossy(length).into_owned().parse::<usize>() {
152 if i + x + 1 <= encoded.len() {
153 let value: &[u8] = &encoded[i + 1..i + x + 1];
154 Ok((i + x, BString::new(value)))
155 } else {
156 Err("expected more bytes, but end was found")
157 }
158 } else {
159 Err("expected correct usize number, representing length")
160 }
161 }
162 }
163}
164#[cfg(test)]
206mod bnumber_tests {
207 extern crate rand;
208
209 use super::*;
210
211 fn test_bnumber(string: &[u8], index: usize, result: i64) {
212 let (ind, num) = BNumber::decode(string).ok().expect("invalid test");
213 assert_eq!(result, num.number);
214 assert_eq!(index, ind);
215 }
216
217 fn test_bnumber_invalid(string: &[u8], expected: &str) {
218 let error = BNumber::decode(string).err().expect("invalid test");
219 assert_eq!(expected, error);
220 }
221
222 #[test]
223 fn test1_bnumber_simple() {
224 test_bnumber("i300e".as_bytes(), 4, 300);
225 }
226
227 #[test]
228 fn test2_bnumber_negative() {
229 test_bnumber("i-23487e".as_bytes(), 7, -23487);
230 }
231
232 #[test]
233 fn test3_bnumber_invalid_format() {
234 test_bnumber_invalid("l487e".as_bytes(), "expected 'i' before number");
235 }
236
237 #[test]
238 fn test4_bnumber_invalid_format() {
239 test_bnumber_invalid("i487k".as_bytes(), "expected 'e' after number");
240 }
241
242 #[test]
243 fn test5_bnumber_invalid_number() {
244 test_bnumber_invalid("i-650-4e".as_bytes(), "expected correct i64 number");
245 }
246
247 #[test]
248 fn test6_bnumber_too_big_number() {
249 test_bnumber_invalid("i2398475629384765298346529384756293487562923452983e".as_bytes()
250 , "expected correct i64 number");
251 }
252
253 #[test]
254 fn test7_bnumber_zero() {
255 test_bnumber("i0e".as_bytes(), 2, 0);
256 }
257
258 #[test]
259 fn test8_bnumer_empty_number() {
260 test_bnumber_invalid("ie".as_bytes(), "expected correct i64 number");
261 }
262
263 #[test]
264 fn test9_bnumer_too_short() {
265 test_bnumber_invalid("i".as_bytes(), "expected 'e' after number");
266 }
267
268 #[test]
269 fn test10_bnumer_even_shorter() {
270 test_bnumber_invalid("".as_bytes(), "empty string isn't valid BNumber");
271 }
272
273 #[test]
274 fn test11_bnumer_stress() {
275 for _ in 0..100000 {
276 let number: i64 = rand::random::<i64>();
277 let string: String = format!("i{}e", number);
278 test_bnumber(string.as_bytes(), string.len() - 1, number);
279 }
280 }
281}
282
283#[cfg(test)]
284mod bstring_tests {
285 use super::*;
286 fn test_bstring(string: &[u8], index: usize, result: String) {
287 let (ind, bstr) = BString::decode(string).ok().expect("invalid test");
288 assert_eq!(index, ind);
289 assert_eq!(result, bstr.data);
290 }
291
292 fn test_bstring_invalid(string: &[u8], expected: &str) {
293 let error = BString::decode(string).err().expect("invalid test");
294 assert_eq!(expected, error);
295 }
296
297 #[test]
298 fn test1_bstring_simple() {
299 test_bstring("3:abc".as_bytes(), 4, "abc".to_string());
300 }
301
302 #[test]
303 fn test2_bstring_short() {
304 test_bstring("1:a".as_bytes(), 2, "a".to_string());
305 }
306
307 #[test]
308 fn test3_bstring_even_shorter() {
309 test_bstring("0:".as_bytes(), 1, "".to_string());
310 }
311
312 #[test]
313 fn test4_bstring_digits() {
314 test_bstring("5:12345".as_bytes(), 6, "12345".to_string());
315 }
316
317 #[test]
318 fn test5_bstring_bad_symbols() {
319 test_bstring("14:!@#$%^&*()_+-=".as_bytes(), 16, "!@#$%^&*()_+-=".to_string());
320 }
321
322 #[test]
323 fn test6_bstring_empty() {
324 test_bstring_invalid("".as_bytes(), "expected :, but end was found");
325 }
326
327 #[test]
328 fn test7_bstring_bad_len() {
329 test_bstring_invalid("1:".as_bytes(), "expected more bytes, but end was found");
330 }
331
332 #[test]
333 fn test8_bstring_no_colon() {
334 test_bstring_invalid("128911".as_bytes(), "expected :, but end was found");
335 }
336
337 #[test]
338 fn test9_bstring_invalid_len() {
339 test_bstring_invalid("2a:a".as_bytes(), "expected correct usize number, representing length");
340 }
341
342 #[test]
343 fn test10_bstring_colon_first() {
344 test_bstring_invalid(":123".as_bytes(), "expected correct usize number, representing length");
345 }
346}