Skip to content

Commit 7727f98

Browse files
committed
Added hex parser, and options struct
1 parent cd96176 commit 7727f98

File tree

5 files changed

+40
-19
lines changed

5 files changed

+40
-19
lines changed

Cargo.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@ version = "0.1.0"
1313
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
1414

1515
[dependencies]
16-
# No Dependencies!
16+
hex = "0.4.3"
1717

1818
[dev-dependencies]
1919
clap = { version = "4.0.7", features = ["derive"] }
20-
hex = "0.4.3"

examples/cli.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use bencode_parser::BEncode;
1+
use bencode_parser::{BEncode, Options};
22
use clap::Parser;
33
use std::fs;
44
use std::io::Write;
@@ -28,7 +28,8 @@ fn main() {
2828
let path: PathBuf = PathBuf::from(&args.input);
2929
let bytes = fs::read(path).expect("Couldn't Read File!");
3030

31-
let res: BEncode = BEncode::parse(bytes);
31+
let options: Options = Options::default();
32+
let res: BEncode = BEncode::parse(bytes, options);
3233

3334
if let BEncode::Dictionary(_) = res {
3435
let file_path: PathBuf = PathBuf::from(args.output);

examples/info_hash_extractor.rs

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use bencode_parser::BEncode;
1+
use bencode_parser::{BEncode, Options};
22
use clap::Parser;
33
use std::fs;
44
use std::path::PathBuf;
@@ -16,7 +16,12 @@ fn main() {
1616

1717
let path: PathBuf = PathBuf::from(args.input);
1818
let bytes: Vec<u8> = fs::read(path).expect("Cannot read File!");
19-
let res: BEncode = BEncode::parse(bytes);
19+
20+
let options: Options = Options::default();
21+
let res: BEncode = BEncode::parse(bytes, options);
22+
23+
// The length is 20 in torrent files, but parsing 1 byte to hex returns 2 characters, so the length also has to be doubled
24+
let hash_length: usize = 40;
2025

2126
if let BEncode::Dictionary(obj) = res {
2227
let info: &BEncode = obj
@@ -25,17 +30,20 @@ fn main() {
2530

2631
if let BEncode::Dictionary(info_obj) = info {
2732
let pieces: &BEncode = info_obj.get("pieces").expect("Cannot find Pieces!");
28-
if let BEncode::BinaryStr(str) = pieces {
29-
if str.len() % 20 != 0 {
30-
panic!("Pieces Hash not valid! (The length is not a multiple of 20)");
33+
if let BEncode::String(str) = pieces {
34+
if str.len() % hash_length != 0 {
35+
panic!(
36+
"Pieces Hash not valid! (The length is not a multiple of {})",
37+
hash_length
38+
);
3139
}
3240
let mut hashes: Vec<String> = Vec::new();
3341
let mut start_idx: usize = 0;
3442

35-
while (start_idx + 20) <= str.len() {
36-
let hash: String = hex::encode(&str[start_idx..start_idx + 20]);
43+
while (start_idx + hash_length) <= str.len() {
44+
let hash: String = str[start_idx..start_idx + hash_length].to_string();
3745
hashes.push(hash);
38-
start_idx += 20;
46+
start_idx += hash_length;
3947
}
4048

4149
println!("{:?}", hashes);

src/lib.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
//!
1212
//! ```
1313
14+
mod options;
15+
16+
pub use options::Options;
1417
use std::cmp::Ordering;
1518
use std::collections::HashMap;
1619
use std::fmt;
@@ -49,7 +52,7 @@ impl fmt::Debug for BEncode {
4952
impl BEncode {
5053
/// This function returns the parsed [`BEncode`] object, given a valid path to a file containing bencode.
5154
/// returns a `Bencode::Int(-1)` if the bencode cannot be parsed
52-
pub fn parse(bytes: Vec<u8>) -> Self {
55+
pub fn parse(bytes: Vec<u8>, options: Options) -> Self {
5356
// =====================STATE VARIABLES==========================
5457
let mut parents: Vec<BEncode> = Vec::new();
5558
let mut dict_keys: Vec<String> = Vec::new();
@@ -92,7 +95,7 @@ impl BEncode {
9295
}
9396
// String
9497
c if c.chars().next().unwrap().is_numeric() => {
95-
let (new_idx, out_str) = Self::parse_str(&bytes, idx - 1);
98+
let (new_idx, out_str) = Self::parse_str(&bytes, idx - 1, options.parse_hex);
9699
idx = new_idx;
97100
// println!("Parsed String: {:?}", out_str);
98101
if !parents.is_empty() {
@@ -220,7 +223,7 @@ impl BEncode {
220223
}
221224

222225
/// Internal function to parse a bencode ByteString
223-
fn parse_str(bytes: &[u8], mut idx: usize) -> (usize, BEncode) {
226+
fn parse_str(bytes: &[u8], mut idx: usize, parse_hex: bool) -> (usize, BEncode) {
224227
let mut len_str: String = String::new();
225228

226229
// This loop determines the length of the string
@@ -244,10 +247,9 @@ impl BEncode {
244247
let out_str = String::from_utf8(byte_slice.clone()).unwrap_or_else(|_e| "".to_string());
245248

246249
if out_str.is_empty() {
247-
// unsafe {
248-
// // let bin = String::from_utf8_unchecked(byte_slice);
249-
// return (idx + len, BEncode::BinaryStr(byte_slice.to_vec()));
250-
// }
250+
if parse_hex {
251+
return (idx + len, BEncode::String(hex::encode(byte_slice)));
252+
}
251253
return (idx + len, BEncode::BinaryStr(byte_slice.to_vec()));
252254
}
253255

src/options.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
//! The `Options` struct contains the configurable options that the parser can take
2+
pub struct Options {
3+
/// `parse_hex` tells the parser if the hex data from pieces should be parsed. Default value: `true`
4+
pub parse_hex: bool,
5+
}
6+
7+
impl Options {
8+
pub fn default() -> Self {
9+
Self { parse_hex: true }
10+
}
11+
}

0 commit comments

Comments
 (0)