use crate::InfoHash;
use bendy::decoding::{Error, FromBencode, Object};
use std::collections::HashMap;
#[derive(Debug, Default)]
pub struct Total {
pub complete: u32,
pub incomplete: u32,
pub downloaded: u32,
}
#[derive(Default)]
pub struct Scrape {
pub total: Total,
pub stats: HashMap<InfoHash, Total>,
}
impl FromBencode for Scrape {
fn decode_bencode_object(object: Object) -> Result<Self, Error> {
let mut root_dict = object.try_into_dictionary()?;
let mut response = Self::default();
while let Some(root_pair) = root_dict.next_pair()? {
match root_pair {
(b"files", files_value) => {
let mut files_dict = files_value.try_into_dictionary()?;
while let Some((id, torrent_data_value)) = files_dict.next_pair()? {
let info_hash = InfoHash::V1(id.to_vec());
let mut total = Total::default();
let mut torrent_dict = torrent_data_value.try_into_dictionary()?;
while let Some(stat_pair) = torrent_dict.next_pair()? {
match stat_pair {
(b"complete", value) => {
let count: u32 = value
.try_into_integer()
.map_err(Error::malformed_content)?
.parse()
.map_err(Error::malformed_content)?;
total.complete = count;
response.total.complete += count;
}
(b"incomplete", value) => {
let count: u32 = value
.try_into_integer()
.map_err(Error::malformed_content)?
.parse()
.map_err(Error::malformed_content)?;
total.incomplete = count;
response.total.incomplete += count;
}
(b"downloaded", value) => {
let count: u32 = value
.try_into_integer()
.map_err(Error::malformed_content)?
.parse()
.map_err(Error::malformed_content)?;
total.downloaded = count;
response.total.downloaded += count;
}
_ => continue,
}
}
response.stats.insert(info_hash, total);
}
}
_ => continue,
}
}
Ok(response)
}
}