#bencode

bencodex

bencode parser

3 releases

0.1.3 May 9, 2020
0.1.2 Apr 16, 2020
0.1.1 Apr 14, 2020
0.1.0 Apr 14, 2020

#9 in #bencode

MIT license

17KB
439 lines

bencodex

A bencode parser.

Example

Plain text

use bencodex::BNode;

fn main() {
    unmarshal();
    println!("-----------------");
    marshal();
}

fn unmarshal() {
    let b = "d3:inti233e3:lstl7:bencodeee";
    let result = bencodex::parse(&mut b.bytes());

    match result {
        Ok(node) => {
            let map = node.as_map().unwrap();
            let int = map.get("int").unwrap().as_int().unwrap();
            println!("Int = {}", int);
            let lst = map.get("lst").unwrap().as_list().unwrap();
            println!("There're {} values in the list", lst.len());
            println!(
                "The first value in the list is `{}`",
                &lst[0].as_string().unwrap()
            );
        }
        Err(e) => panic!(e),
    }
}

fn marshal() {
    let mut map = std::collections::BTreeMap::new();
    map.insert("int".to_string(), BNode::Int(2333));
    map.insert(
        "lst".to_string(),
        BNode::List(vec![BNode::Str("bencode".bytes().collect::<Vec<u8>>())]),
    );

    println!("{}", &BNode::Map(map));
}

Output

Int = 233
There're 1 values in the list
The first value in the list is `bencode`
-----------------
d3:inti2333e3:lstl7:bencodeee

BitTorrent file

Iterator adapter

struct Adapter {
    bytes: Bytes<BufReader<File>>,
}

impl Iterator for Adapter {
    type Item = u8;
    fn next(&mut self) -> Option<<Self as Iterator>::Item> {
        match self.bytes.next() {
            Some(Ok(v)) => Some(v),
            _ => None,
        }
    }
}

Unmarshal

fn unmarshal_from_bitorrent_file() -> Option<BNode> {
    if let Ok(f) = File::open("Ps.torrent") {
        let reader = BufReader::new(f);

        let mut adapter = Adapter {
            bytes: reader.bytes(),
        };
        let root = bencodex::parse(&mut adapter);
        if let Ok(BNode::Map(map)) = &root {
            for k in map.keys() {
                println!("{}", k);
            }
            return Some(root.unwrap());
        }
        return None;
    }
    None
}

Output

announce
announce-list
created by
creation date
encoding
info

Marshal

let res = unmarshal_from_bitorrent_file();
if let Some(bn) = res {
    let mut buf: Vec<u8> = Vec::new();
    bn.marshal(&mut buf);
    let mut file = File::create("./out.torrent")?;
    file.write_all(&buf)?;
}

No runtime deps