11use std:: error;
22
3+ use derive_more:: { Display , Error } ;
34use serde:: { self , Deserialize , Serialize } ;
45use serde_bencode:: value:: Value ;
56use serde_bencode:: { de, Error } ;
@@ -8,6 +9,43 @@ use sha1::{Digest, Sha1};
89use crate :: models:: info_hash:: InfoHash ;
910use crate :: models:: torrent_file:: Torrent ;
1011
12+ #[ derive( Debug , Display , PartialEq , Eq , Error ) ]
13+ pub enum MetainfoFileDataError {
14+ #[ display( fmt = "Torrent data could not be decoded from the bencoded format." ) ]
15+ InvalidBencodeData ,
16+
17+ #[ display( fmt = "Torrent has an invalid pieces key length. It should be a multiple of 20." ) ]
18+ InvalidTorrentPiecesLength ,
19+ }
20+
21+ /// It decodes and validate an array of bytes containing a torrent file.
22+ ///
23+ /// It returns a tuple containing the decoded torrent and the original info hash.
24+ /// The original info-hash migth not match the new one in the `Torrent` because
25+ /// the info dictionary might have been modified. For example, ignoring some
26+ /// non-standard fields.
27+ ///
28+ /// # Errors
29+ ///
30+ /// This function will return an error if
31+ ///
32+ /// - The torrent file is not a valid bencoded file.
33+ /// - The pieces key has a length that is not a multiple of 20.
34+ pub fn decode_and_validate_torrent_file ( bytes : & [ u8 ] ) -> Result < ( Torrent , InfoHash ) , MetainfoFileDataError > {
35+ let original_info_hash = calculate_info_hash ( bytes) ;
36+
37+ let torrent = decode_torrent ( bytes) . map_err ( |_| MetainfoFileDataError :: InvalidBencodeData ) ?;
38+
39+ // Make sure that the pieces key has a length that is a multiple of 20
40+ if let Some ( pieces) = torrent. info . pieces . as_ref ( ) {
41+ if pieces. as_ref ( ) . len ( ) % 20 != 0 {
42+ return Err ( MetainfoFileDataError :: InvalidTorrentPiecesLength ) ;
43+ }
44+ }
45+
46+ Ok ( ( torrent, original_info_hash) )
47+ }
48+
1149/// Decode a Torrent from Bencoded Bytes.
1250///
1351/// # Errors
0 commit comments