1
+ use log:: error;
1
2
use serde:: { Deserialize , Serialize } ;
2
3
use serde_bencode:: ser;
3
4
use serde_bytes:: ByteBuf ;
@@ -77,12 +78,31 @@ impl Torrent {
77
78
torrent_http_seed_urls : Vec < String > ,
78
79
torrent_nodes : Vec < ( String , i64 ) > ,
79
80
) -> Self {
81
+ let pieces_or_root_hash = if db_torrent. is_bep_30 == 0 {
82
+ match & db_torrent. pieces {
83
+ Some ( pieces) => pieces. clone ( ) ,
84
+ None => {
85
+ error ! ( "Invalid torrent #{}. Null `pieces` in database" , db_torrent. torrent_id) ;
86
+ String :: new ( )
87
+ }
88
+ }
89
+ } else {
90
+ // A BEP-30 torrent
91
+ match & db_torrent. root_hash {
92
+ Some ( root_hash) => root_hash. clone ( ) ,
93
+ None => {
94
+ error ! ( "Invalid torrent #{}. Null `root_hash` in database" , db_torrent. torrent_id) ;
95
+ String :: new ( )
96
+ }
97
+ }
98
+ } ;
99
+
80
100
let info_dict = TorrentInfoDictionary :: with (
81
101
& db_torrent. name ,
82
102
db_torrent. piece_length ,
83
103
db_torrent. private ,
84
104
db_torrent. is_bep_30 ,
85
- & db_torrent . pieces ,
105
+ & pieces_or_root_hash ,
86
106
torrent_files,
87
107
) ;
88
108
@@ -235,7 +255,14 @@ impl TorrentInfoDictionary {
235
255
/// - The `pieces` field is not a valid hex string.
236
256
/// - For single files torrents the `TorrentFile` path is empty.
237
257
#[ must_use]
238
- pub fn with ( name : & str , piece_length : i64 , private : Option < u8 > , is_bep_30 : i64 , pieces : & str , files : & [ TorrentFile ] ) -> Self {
258
+ pub fn with (
259
+ name : & str ,
260
+ piece_length : i64 ,
261
+ private : Option < u8 > ,
262
+ is_bep_30 : i64 ,
263
+ pieces_or_root_hash : & str ,
264
+ files : & [ TorrentFile ] ,
265
+ ) -> Self {
239
266
let mut info_dict = Self {
240
267
name : name. to_string ( ) ,
241
268
pieces : None ,
@@ -249,13 +276,13 @@ impl TorrentInfoDictionary {
249
276
source : None ,
250
277
} ;
251
278
252
- // a torrent file has a root hash or a pieces key, but not both.
253
- if is_bep_30 > 0 {
254
- // If `is_bep_30` is true the `pieces` field contains the `root hash`
255
- info_dict. root_hash = Some ( pieces. to_owned ( ) ) ;
256
- } else {
257
- let buffer = into_bytes ( pieces) . expect ( "variable `torrent_info.pieces` is not a valid hex string" ) ;
279
+ // BEP 30: <http://www.bittorrent.org/beps/bep_0030.html>.
280
+ // Torrent file can only hold a `pieces` key or a `root hash` key
281
+ if is_bep_30 == 0 {
282
+ let buffer = into_bytes ( pieces_or_root_hash) . expect ( "variable `torrent_info.pieces` is not a valid hex string" ) ;
258
283
info_dict. pieces = Some ( ByteBuf :: from ( buffer) ) ;
284
+ } else {
285
+ info_dict. root_hash = Some ( pieces_or_root_hash. to_owned ( ) ) ;
259
286
}
260
287
261
288
// either set the single file or the multiple files information
@@ -298,22 +325,22 @@ impl TorrentInfoDictionary {
298
325
}
299
326
}
300
327
301
- /// It returns the root hash as a `i64` value.
302
- ///
303
- /// # Panics
304
- ///
305
- /// This function will panic if the root hash cannot be converted into a
306
- /// `i64` value.
328
+ /// torrent file can only hold a pieces key or a root hash key:
329
+ /// [BEP 39](http://www.bittorrent.org/beps/bep_0030.html)
307
330
#[ must_use]
308
- pub fn get_root_hash_as_i64 ( & self ) -> i64 {
331
+ pub fn get_root_hash_as_string ( & self ) -> String {
309
332
match & self . root_hash {
310
- None => 0i64 ,
311
- Some ( root_hash) => root_hash
312
- . parse :: < i64 > ( )
313
- . expect ( "variable `root_hash` cannot be converted into a `i64`" ) ,
333
+ None => String :: new ( ) ,
334
+ Some ( root_hash) => root_hash. clone ( ) ,
314
335
}
315
336
}
316
337
338
+ /// It returns true if the torrent is a BEP-30 torrent.
339
+ #[ must_use]
340
+ pub fn is_bep_30 ( & self ) -> bool {
341
+ self . root_hash . is_some ( )
342
+ }
343
+
317
344
#[ must_use]
318
345
pub fn is_a_single_file_torrent ( & self ) -> bool {
319
346
self . length . is_some ( )
@@ -330,7 +357,8 @@ pub struct DbTorrent {
330
357
pub torrent_id : i64 ,
331
358
pub info_hash : String ,
332
359
pub name : String ,
333
- pub pieces : String ,
360
+ pub pieces : Option < String > ,
361
+ pub root_hash : Option < String > ,
334
362
pub piece_length : i64 ,
335
363
#[ serde( default ) ]
336
364
pub private : Option < u8 > ,
0 commit comments