#![feature(proc_macro)]
extern crate serde_bencode;
extern crate serde;
#[macro_use]
extern crate serde_derive;
use serde_bencode::decoder;
use std::io::{self, Read};
use serde::bytes::ByteBuf;
#[derive(Debug, Deserialize)]
struct Node(String, i64);
#[derive(Debug, Deserialize)]
struct File {
path: Vec<String>,
length: i64,
#[serde(default)]
md5sum: Option<String>,
}
#[derive(Debug, Deserialize)]
struct Info {
name: String,
pieces: ByteBuf,
#[serde(rename="piece length")]
piece_length: i64,
#[serde(default)]
md5sum: Option<String>,
#[serde(default)]
length: Option<i64>,
#[serde(default)]
files: Option<Vec<File>>,
#[serde(default)]
private: Option<u8>,
#[serde(default)]
path: Option<Vec<String>>,
#[serde(default)]
#[serde(rename="root hash")]
root_hash: Option<String>,
}
#[derive(Debug, Deserialize)]
struct Torrent {
info: Info,
#[serde(default)]
announce: Option<String>,
#[serde(default)]
nodes: Option<Vec<Node>>,
#[serde(default)]
encoding: Option<String>,
#[serde(default)]
httpseeds: Option<Vec<String>>,
#[serde(default)]
#[serde(rename="announce-list")]
announce_list: Option<Vec<Vec<String>>>,
#[serde(default)]
#[serde(rename="creation date")]
creation_date: Option<i64>,
#[serde(rename="comment")]
comment: Option<String>,
#[serde(default)]
#[serde(rename="created by")]
created_by: Option<String>,
}
fn render_torrent(torrent: &Torrent) {
println!("name:\t\t{}", torrent.info.name);
println!("announce:\t{:?}", torrent.announce);
println!("nodes:\t\t{:?}", torrent.nodes);
if let &Some(ref al) = &torrent.announce_list {
for a in al {
println!("announce list:\t{}", a[0]);
}
}
println!("httpseeds:\t{:?}", torrent.httpseeds);
println!("creation date:\t{:?}", torrent.creation_date);
println!("comment:\t{:?}", torrent.comment);
println!("created by:\t{:?}", torrent.created_by);
println!("encoding:\t{:?}", torrent.encoding);
println!("piece length:\t{:?}", torrent.info.piece_length);
println!("private:\t{:?}", torrent.info.private);
println!("root hash:\t{:?}", torrent.info.root_hash);
println!("md5sum:\t\t{:?}", torrent.info.md5sum);
println!("path:\t\t{:?}", torrent.info.path);
if let &Some(ref files) = &torrent.info.files {
for f in files {
println!("file path:\t{:?}", f.path);
println!("file length:\t{}", f.length);
println!("file md5sum:\t{:?}", f.md5sum);
}
}
}
fn main() {
let stdin = io::stdin();
let mut buffer = Vec::new();
let mut handle = stdin.lock();
match handle.read_to_end(&mut buffer) {
Ok(_) => {
match decoder::from_bytes::<Torrent>(&buffer) {
Ok(t) => render_torrent(&t),
Err(e) => println!("ERROR: {:?}", e)
}
},
Err(e) => println!("ERROR: {:?}", e)
}
}