1use std::error;
2
3use derive_more::{Display, Error};
4use serde::{Deserialize, Serialize};
5use serde_bencode::value::Value;
6use serde_bencode::{de, Error};
7use sha1::{Digest, Sha1};
8
9use crate::models::info_hash::InfoHash;
10use crate::models::torrent_file::Torrent;
11
12#[derive(Debug, Display, PartialEq, Eq, Error)]
13pub enum DecodeTorrentFileError {
14 #[display(fmt = "Torrent data could not be decoded from the bencoded format.")]
15 InvalidBencodeData,
16
17 #[display(fmt = "Torrent info dictionary key could not be decoded from the bencoded format.")]
18 InvalidInfoDictionary,
19
20 #[display(fmt = "Torrent has an invalid pieces key length. It should be a multiple of 20.")]
21 InvalidTorrentPiecesLength,
22
23 #[display(fmt = "Cannot bencode the parsed `info` dictionary again to generate the info-hash.")]
24 CannotBencodeInfoDict,
25}
26
27pub fn decode_and_validate_torrent_file(bytes: &[u8]) -> Result<(Torrent, InfoHash), DecodeTorrentFileError> {
41 let original_info_hash = calculate_info_hash(bytes)?;
42
43 let torrent = decode_torrent(bytes).map_err(|_| DecodeTorrentFileError::InvalidBencodeData)?;
44
45 if let Some(pieces) = torrent.info.pieces.as_ref() {
47 if pieces.as_ref().len() % 20 != 0 {
48 return Err(DecodeTorrentFileError::InvalidTorrentPiecesLength);
49 }
50 }
51
52 Ok((torrent, original_info_hash))
53}
54
55pub fn decode_torrent(bytes: &[u8]) -> Result<Torrent, Box<dyn error::Error>> {
61 match de::from_bytes::<Torrent>(bytes) {
62 Ok(torrent) => Ok(torrent),
63 Err(e) => {
64 println!("{e:?}");
65 Err(e.into())
66 }
67 }
68}
69
70pub fn encode_torrent(torrent: &Torrent) -> Result<Vec<u8>, Error> {
76 match serde_bencode::to_bytes(torrent) {
77 Ok(bencode_bytes) => Ok(bencode_bytes),
78 Err(e) => {
79 eprintln!("{e:?}");
80 Err(e)
81 }
82 }
83}
84
85#[derive(Serialize, Deserialize, Debug, PartialEq)]
86struct ParsedInfoDictFromMetainfoFile {
87 pub info: Value,
88}
89
90pub fn calculate_info_hash(bytes: &[u8]) -> Result<InfoHash, DecodeTorrentFileError> {
101 let metainfo: ParsedInfoDictFromMetainfoFile =
103 serde_bencode::from_bytes(bytes).map_err(|_| DecodeTorrentFileError::InvalidInfoDictionary)?;
104
105 let info_dict_bytes = serde_bencode::to_bytes(&metainfo.info).map_err(|_| DecodeTorrentFileError::CannotBencodeInfoDict)?;
107
108 let mut hasher = Sha1::new();
110 hasher.update(&info_dict_bytes);
111 let result = hasher.finalize();
112
113 Ok(InfoHash::from_bytes(&result))
114}
115
116#[cfg(test)]
117mod tests {
118 use std::str::FromStr;
119
120 use crate::models::info_hash::InfoHash;
121
122 fn torrent_with_custom_info_dict_key() -> Vec<u8> {
126 [
148 100, 56, 58, 97, 110, 110, 111, 117, 110, 99, 101, 52, 49, 58, 104, 116, 116, 112, 115, 58, 47, 47, 97, 99, 97, 100,
149 101, 109, 105, 99, 116, 111, 114, 114, 101, 110, 116, 115, 46, 99, 111, 109, 47, 97, 110, 110, 111, 117, 110, 99,
150 101, 46, 112, 104, 112, 49, 51, 58, 97, 110, 110, 111, 117, 110, 99, 101, 45, 108, 105, 115, 116, 108, 108, 52, 49,
151 58, 104, 116, 116, 112, 115, 58, 47, 47, 97, 99, 97, 100, 101, 109, 105, 99, 116, 111, 114, 114, 101, 110, 116, 115,
152 46, 99, 111, 109, 47, 97, 110, 110, 111, 117, 110, 99, 101, 46, 112, 104, 112, 101, 108, 52, 54, 58, 104, 116, 116,
153 112, 115, 58, 47, 47, 105, 112, 118, 54, 46, 97, 99, 97, 100, 101, 109, 105, 99, 116, 111, 114, 114, 101, 110, 116,
154 115, 46, 99, 111, 109, 47, 97, 110, 110, 111, 117, 110, 99, 101, 46, 112, 104, 112, 101, 108, 52, 50, 58, 117, 100,
155 112, 58, 47, 47, 116, 114, 97, 99, 107, 101, 114, 46, 111, 112, 101, 110, 116, 114, 97, 99, 107, 114, 46, 111, 114,
156 103, 58, 49, 51, 51, 55, 47, 97, 110, 110, 111, 117, 110, 99, 101, 101, 108, 52, 52, 58, 117, 100, 112, 58, 47, 47,
157 116, 114, 97, 99, 107, 101, 114, 46, 111, 112, 101, 110, 98, 105, 116, 116, 111, 114, 114, 101, 110, 116, 46, 99,
158 111, 109, 58, 56, 48, 47, 97, 110, 110, 111, 117, 110, 99, 101, 101, 108, 51, 54, 58, 104, 116, 116, 112, 58, 47, 47,
159 98, 116, 49, 46, 97, 114, 99, 104, 105, 118, 101, 46, 111, 114, 103, 58, 54, 57, 54, 57, 47, 97, 110, 110, 111, 117,
160 110, 99, 101, 101, 108, 51, 54, 58, 104, 116, 116, 112, 58, 47, 47, 98, 116, 50, 46, 97, 114, 99, 104, 105, 118, 101,
161 46, 111, 114, 103, 58, 54, 57, 54, 57, 47, 97, 110, 110, 111, 117, 110, 99, 101, 101, 101, 55, 58, 99, 111, 109, 109,
162 101, 110, 116, 54, 51, 52, 58, 84, 104, 105, 115, 32, 99, 111, 110, 116, 101, 110, 116, 32, 104, 111, 115, 116, 101,
163 100, 32, 97, 116, 32, 116, 104, 101, 32, 73, 110, 116, 101, 114, 110, 101, 116, 32, 65, 114, 99, 104, 105, 118, 101,
164 32, 97, 116, 32, 104, 116, 116, 112, 115, 58, 47, 47, 97, 114, 99, 104, 105, 118, 101, 46, 111, 114, 103, 47, 100,
165 101, 116, 97, 105, 108, 115, 47, 114, 97, 112, 112, 112, 105, 100, 45, 119, 101, 105, 103, 104, 116, 115, 46, 116,
166 97, 114, 10, 70, 105, 108, 101, 115, 32, 109, 97, 121, 32, 104, 97, 118, 101, 32, 99, 104, 97, 110, 103, 101, 100,
167 44, 32, 119, 104, 105, 99, 104, 32, 112, 114, 101, 118, 101, 110, 116, 115, 32, 116, 111, 114, 114, 101, 110, 116,
168 115, 32, 102, 114, 111, 109, 32, 100, 111, 119, 110, 108, 111, 97, 100, 105, 110, 103, 32, 99, 111, 114, 114, 101,
169 99, 116, 108, 121, 32, 111, 114, 32, 99, 111, 109, 112, 108, 101, 116, 101, 108, 121, 59, 32, 112, 108, 101, 97, 115,
170 101, 32, 99, 104, 101, 99, 107, 32, 102, 111, 114, 32, 97, 110, 32, 117, 112, 100, 97, 116, 101, 100, 32, 116, 111,
171 114, 114, 101, 110, 116, 32, 97, 116, 32, 104, 116, 116, 112, 115, 58, 47, 47, 97, 114, 99, 104, 105, 118, 101, 46,
172 111, 114, 103, 47, 100, 111, 119, 110, 108, 111, 97, 100, 47, 114, 97, 112, 112, 112, 105, 100, 45, 119, 101, 105,
173 103, 104, 116, 115, 46, 116, 97, 114, 47, 114, 97, 112, 112, 112, 105, 100, 45, 119, 101, 105, 103, 104, 116, 115,
174 46, 116, 97, 114, 95, 97, 114, 99, 104, 105, 118, 101, 46, 116, 111, 114, 114, 101, 110, 116, 10, 78, 111, 116, 101,
175 58, 32, 114, 101, 116, 114, 105, 101, 118, 97, 108, 32, 117, 115, 117, 97, 108, 108, 121, 32, 114, 101, 113, 117,
176 105, 114, 101, 115, 32, 97, 32, 99, 108, 105, 101, 110, 116, 32, 116, 104, 97, 116, 32, 115, 117, 112, 112, 111, 114,
177 116, 115, 32, 119, 101, 98, 115, 101, 101, 100, 105, 110, 103, 32, 40, 71, 101, 116, 82, 105, 103, 104, 116, 32, 115,
178 116, 121, 108, 101, 41, 46, 10, 78, 111, 116, 101, 58, 32, 109, 97, 110, 121, 32, 73, 110, 116, 101, 114, 110, 101,
179 116, 32, 65, 114, 99, 104, 105, 118, 101, 32, 116, 111, 114, 114, 101, 110, 116, 115, 32, 99, 111, 110, 116, 97, 105,
180 110, 32, 97, 32, 39, 112, 97, 100, 32, 102, 105, 108, 101, 39, 32, 100, 105, 114, 101, 99, 116, 111, 114, 121, 46,
181 32, 84, 104, 105, 115, 32, 100, 105, 114, 101, 99, 116, 111, 114, 121, 32, 97, 110, 100, 32, 116, 104, 101, 32, 102,
182 105, 108, 101, 115, 32, 119, 105, 116, 104, 105, 110, 32, 105, 116, 32, 109, 97, 121, 32, 98, 101, 32, 101, 114, 97,
183 115, 101, 100, 32, 111, 110, 99, 101, 32, 114, 101, 116, 114, 105, 101, 118, 97, 108, 32, 99, 111, 109, 112, 108,
184 101, 116, 101, 115, 46, 10, 78, 111, 116, 101, 58, 32, 116, 104, 101, 32, 102, 105, 108, 101, 32, 114, 97, 112, 112,
185 112, 105, 100, 45, 119, 101, 105, 103, 104, 116, 115, 46, 116, 97, 114, 95, 109, 101, 116, 97, 46, 120, 109, 108, 32,
186 99, 111, 110, 116, 97, 105, 110, 115, 32, 109, 101, 116, 97, 100, 97, 116, 97, 32, 97, 98, 111, 117, 116, 32, 116,
187 104, 105, 115, 32, 116, 111, 114, 114, 101, 110, 116, 39, 115, 32, 99, 111, 110, 116, 101, 110, 116, 115, 46, 49, 48,
188 58, 99, 114, 101, 97, 116, 101, 100, 32, 98, 121, 49, 53, 58, 105, 97, 95, 109, 97, 107, 101, 95, 116, 111, 114, 114,
189 101, 110, 116, 49, 51, 58, 99, 114, 101, 97, 116, 105, 111, 110, 32, 100, 97, 116, 101, 105, 49, 54, 56, 57, 50, 55,
190 51, 55, 56, 55, 101, 52, 58, 105, 110, 102, 111, 100, 49, 49, 58, 99, 111, 108, 108, 101, 99, 116, 105, 111, 110,
191 115, 108, 51, 49, 58, 111, 114, 103, 46, 97, 114, 99, 104, 105, 118, 101, 46, 114, 97, 112, 112, 112, 105, 100, 45,
192 119, 101, 105, 103, 104, 116, 115, 46, 116, 97, 114, 101, 53, 58, 102, 105, 108, 101, 115, 108, 100, 53, 58, 99, 114,
193 99, 51, 50, 56, 58, 53, 55, 100, 51, 51, 102, 99, 99, 54, 58, 108, 101, 110, 103, 116, 104, 105, 49, 49, 53, 50, 56,
194 51, 50, 52, 101, 51, 58, 109, 100, 53, 51, 50, 58, 101, 57, 49, 98, 98, 52, 98, 97, 56, 50, 54, 57, 53, 49, 54, 49,
195 98, 101, 54, 56, 102, 56, 98, 51, 51, 97, 101, 55, 54, 49, 52, 50, 53, 58, 109, 116, 105, 109, 101, 49, 48, 58, 49,
196 54, 56, 57, 50, 55, 51, 55, 51, 48, 52, 58, 112, 97, 116, 104, 108, 50, 50, 58, 82, 65, 80, 80, 80, 73, 68, 32, 87,
197 101, 105, 103, 104, 116, 115, 46, 116, 97, 114, 46, 103, 122, 101, 52, 58, 115, 104, 97, 49, 52, 48, 58, 52, 53, 57,
198 55, 48, 101, 102, 51, 51, 99, 98, 51, 48, 52, 57, 97, 55, 97, 56, 54, 50, 57, 101, 52, 48, 99, 56, 102, 53, 101, 53,
199 50, 54, 56, 100, 49, 100, 99, 53, 51, 101, 100, 53, 58, 99, 114, 99, 51, 50, 56, 58, 99, 54, 53, 56, 102, 100, 52,
200 102, 54, 58, 108, 101, 110, 103, 116, 104, 105, 50, 48, 52, 56, 48, 101, 51, 58, 109, 100, 53, 51, 50, 58, 97, 55,
201 56, 50, 98, 50, 97, 53, 51, 98, 97, 52, 57, 102, 48, 100, 52, 53, 102, 51, 100, 100, 54, 101, 51, 53, 101, 48, 100,
202 53, 57, 51, 53, 58, 109, 116, 105, 109, 101, 49, 48, 58, 49, 54, 56, 57, 50, 55, 51, 55, 56, 51, 52, 58, 112, 97,
203 116, 104, 108, 51, 49, 58, 114, 97, 112, 112, 112, 105, 100, 45, 119, 101, 105, 103, 104, 116, 115, 46, 116, 97, 114,
204 95, 109, 101, 116, 97, 46, 115, 113, 108, 105, 116, 101, 101, 52, 58, 115, 104, 97, 49, 52, 48, 58, 98, 99, 98, 48,
205 54, 98, 51, 49, 54, 52, 102, 49, 100, 50, 97, 98, 97, 50, 50, 101, 102, 54, 48, 52, 54, 101, 98, 56, 48, 102, 54, 53,
206 50, 54, 52, 101, 57, 102, 98, 97, 101, 100, 53, 58, 99, 114, 99, 51, 50, 56, 58, 56, 49, 52, 48, 97, 53, 99, 55, 54,
207 58, 108, 101, 110, 103, 116, 104, 105, 49, 48, 52, 52, 101, 51, 58, 109, 100, 53, 51, 50, 58, 49, 98, 97, 98, 50, 49,
208 101, 53, 48, 101, 48, 54, 97, 98, 52, 50, 100, 51, 97, 55, 55, 100, 56, 55, 50, 98, 102, 50, 53, 50, 101, 53, 53, 58,
209 109, 116, 105, 109, 101, 49, 48, 58, 49, 54, 56, 57, 50, 55, 51, 55, 54, 51, 52, 58, 112, 97, 116, 104, 108, 50, 56,
210 58, 114, 97, 112, 112, 112, 105, 100, 45, 119, 101, 105, 103, 104, 116, 115, 46, 116, 97, 114, 95, 109, 101, 116, 97,
211 46, 120, 109, 108, 101, 52, 58, 115, 104, 97, 49, 52, 48, 58, 98, 50, 102, 48, 102, 50, 98, 98, 101, 99, 51, 52, 97,
212 97, 57, 49, 52, 48, 102, 98, 57, 97, 99, 51, 102, 99, 98, 49, 57, 48, 53, 56, 56, 97, 52, 57, 54, 97, 97, 51, 101,
213 101, 52, 58, 110, 97, 109, 101, 49, 57, 58, 114, 97, 112, 112, 112, 105, 100, 45, 119, 101, 105, 103, 104, 116, 115,
214 46, 116, 97, 114, 49, 50, 58, 112, 105, 101, 99, 101, 32, 108, 101, 110, 103, 116, 104, 105, 53, 50, 52, 50, 56, 56,
215 101, 54, 58, 112, 105, 101, 99, 101, 115, 52, 54, 48, 58, 171, 236, 85, 110, 15, 123, 231, 211, 48, 12, 246, 104,
216 140, 144, 109, 153, 12, 62, 50, 181, 44, 242, 182, 124, 12, 50, 82, 188, 114, 111, 7, 30, 115, 171, 118, 241, 188,
217 50, 43, 252, 33, 212, 127, 26, 233, 114, 53, 64, 126, 195, 180, 137, 9, 43, 237, 75, 216, 176, 108, 101, 140, 39, 88,
218 174, 251, 114, 117, 115, 68, 55, 136, 40, 32, 210, 148, 189, 164, 106, 248, 210, 166, 253, 2, 101, 28, 28, 223, 184,
219 86, 109, 58, 210, 126, 167, 61, 202, 226, 73, 247, 54, 141, 23, 119, 110, 50, 173, 239, 165, 68, 194, 143, 182, 156,
220 36, 86, 173, 232, 251, 123, 166, 113, 192, 129, 229, 67, 3, 145, 212, 79, 176, 166, 100, 202, 41, 27, 13, 29, 64,
221 125, 57, 78, 118, 150, 235, 1, 24, 243, 245, 80, 142, 47, 250, 84, 252, 73, 102, 133, 216, 56, 135, 120, 155, 10,
222 143, 122, 163, 44, 143, 114, 54, 173, 109, 116, 11, 252, 197, 87, 113, 134, 251, 243, 207, 202, 201, 218, 236, 97,
223 98, 162, 42, 27, 167, 133, 137, 145, 143, 170, 192, 192, 203, 13, 87, 216, 183, 231, 100, 77, 242, 132, 115, 118,
224 152, 251, 58, 23, 72, 215, 156, 1, 254, 202, 109, 31, 197, 151, 52, 5, 84, 57, 218, 194, 110, 23, 65, 17, 105, 243,
225 70, 209, 125, 22, 211, 192, 135, 59, 195, 178, 12, 29, 224, 226, 73, 195, 5, 210, 76, 0, 90, 91, 120, 1, 18, 62, 191,
226 82, 67, 73, 109, 26, 238, 35, 121, 210, 14, 40, 182, 132, 126, 197, 237, 121, 222, 100, 2, 237, 71, 113, 61, 147, 22,
227 196, 162, 118, 24, 119, 84, 197, 49, 72, 150, 58, 81, 193, 74, 146, 144, 145, 243, 207, 72, 91, 36, 134, 85, 168,
228 235, 12, 198, 45, 134, 226, 41, 86, 9, 44, 56, 11, 205, 193, 202, 69, 230, 100, 106, 71, 254, 187, 46, 71, 154, 119,
229 69, 41, 233, 114, 25, 32, 111, 66, 121, 43, 55, 185, 83, 37, 237, 15, 41, 4, 213, 226, 150, 241, 222, 207, 153, 190,
230 50, 170, 184, 10, 29, 11, 159, 185, 214, 171, 92, 80, 67, 120, 133, 65, 9, 1, 36, 207, 224, 137, 118, 91, 77, 169,
231 202, 114, 192, 223, 146, 71, 15, 13, 206, 202, 150, 198, 126, 165, 65, 95, 43, 167, 187, 4, 204, 247, 68, 127, 148,
232 30, 36, 210, 27, 23, 202, 24, 121, 144, 163, 214, 32, 117, 162, 150, 104, 6, 88, 90, 222, 245, 44, 26, 144, 34, 114,
233 51, 142, 213, 178, 168, 250, 229, 233, 231, 105, 98, 2, 124, 9, 179, 76, 101, 54, 58, 108, 111, 99, 97, 108, 101, 50,
234 58, 101, 110, 53, 58, 116, 105, 116, 108, 101, 49, 57, 58, 114, 97, 112, 112, 112, 105, 100, 45, 119, 101, 105, 103,
235 104, 116, 115, 46, 116, 97, 114, 56, 58, 117, 114, 108, 45, 108, 105, 115, 116, 108, 50, 57, 58, 104, 116, 116, 112,
236 115, 58, 47, 47, 97, 114, 99, 104, 105, 118, 101, 46, 111, 114, 103, 47, 100, 111, 119, 110, 108, 111, 97, 100, 47,
237 52, 48, 58, 104, 116, 116, 112, 58, 47, 47, 105, 97, 57, 48, 50, 55, 48, 50, 46, 117, 115, 46, 97, 114, 99, 104, 105,
238 118, 101, 46, 111, 114, 103, 47, 50, 50, 47, 105, 116, 101, 109, 115, 47, 52, 48, 58, 104, 116, 116, 112, 58, 47, 47,
239 105, 97, 56, 48, 50, 55, 48, 50, 46, 117, 115, 46, 97, 114, 99, 104, 105, 118, 101, 46, 111, 114, 103, 47, 50, 50,
240 47, 105, 116, 101, 109, 115, 47, 101, 101,
241 ]
242 .to_vec()
243 }
244
245 #[test]
246 fn it_should_calculate_the_original_info_hash_using_all_fields_in_the_info_key_dictionary() {
247 let original_info_hash = super::calculate_info_hash(&torrent_with_custom_info_dict_key()).unwrap();
248
249 assert_eq!(
250 original_info_hash,
251 InfoHash::from_str("6c690018c5786dbbb00161f62b0712d69296df97").unwrap() );
253 }
254
255 #[test]
256 fn it_should_calculate_the_new_info_hash_ignoring_non_standard_fields_in_the_info_key_dictionary() {
257 let torrent = super::decode_torrent(&torrent_with_custom_info_dict_key()).unwrap();
258
259 assert_eq!(
262 torrent.canonical_info_hash_hex(),
263 "8aa01a4c816332045ffec83247ccbc654547fedf".to_string() );
265 }
266}