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}