rubit_bencode/
util.rs

1use std::collections::HashMap;
2
3use sha1::{Digest, Sha1};
4
5use crate::{BencodeTypes, ParseError, Peers};
6
7pub fn get_hash(slice: &[u8]) -> Result<[u8; 20], ParseError> {
8    let mut hasher = Sha1::new();
9    hasher.update(slice);
10    Ok(hasher.finalize().into())
11}
12
13pub fn unwrap_string(string: BencodeTypes) -> Option<String> {
14    if let BencodeTypes::String(s) = string {
15        Some(s)
16    } else {
17        None
18    }
19}
20
21pub fn unwrap_integer(int: BencodeTypes) -> Option<u64> {
22    if let BencodeTypes::Integer(i) = int {
23        Some(i)
24    } else {
25        None
26    }
27}
28
29pub fn unwrap_announce_list(vec: BencodeTypes) -> Option<Vec<Vec<String>>> {
30    let BencodeTypes::List(vec) = vec else {
31        return None;
32    };
33
34    let out = vec
35        .iter()
36        .map(|item| match item {
37            BencodeTypes::List(v) => v
38                .iter()
39                .map(|item| match item {
40                    BencodeTypes::String(s) => s.clone(),
41                    _ => panic!("not a String"),
42                })
43                .collect(),
44            _ => panic!("not a List"),
45        })
46        .collect();
47
48    Some(out)
49}
50
51pub fn unwrap_dict(dict: BencodeTypes) -> Option<HashMap<String, BencodeTypes>> {
52    if let BencodeTypes::Dict(d) = dict {
53        Some(d)
54    } else {
55        None
56    }
57}
58
59pub fn unwrap_info_hash(info_hash: BencodeTypes) -> Option<[u8; 20]> {
60    if let BencodeTypes::InfoHash(ih) = info_hash {
61        Some(ih)
62    } else {
63        None
64    }
65}
66
67pub fn unwrap_pieces(pieces: BencodeTypes) -> Option<Vec<[u8; 20]>> {
68    if let BencodeTypes::Pieces(p) = pieces {
69        Some(p)
70    } else {
71        None
72    }
73}
74
75fn parse_ip(string: String) -> (u8, u8, u8, u8) {
76    let vec: Vec<_> = string
77        .split(".")
78        .map(|s| s.parse::<u8>().expect("failed to parse ip"))
79        .collect();
80    (vec[0], vec[1], vec[2], vec[3])
81}
82
83pub fn unwrap_peers(peers: BencodeTypes) -> Option<Peers> {
84    match peers {
85        BencodeTypes::PeersCompact(p) => Some(p),
86        BencodeTypes::List(mut l) => Some(
87            l.iter_mut()
88                .map(|item| match item {
89                    BencodeTypes::Dict(d) => {
90                        let ip = parse_ip(
91                            unwrap_string(d.remove("ip").expect("no ip param found"))
92                                .expect("failed to get ip"),
93                        );
94
95                        let port = unwrap_integer(d.remove("port").expect("no portW param found"))
96                            .expect("failed to get port");
97
98                        (ip, port as u16)
99                    }
100                    _ => panic!("not a List"),
101                })
102                .collect(),
103        ),
104        _ => unimplemented!(),
105    }
106}