use info_hash::{InfoHash};
pub mod metainfo;
const PIECE_HASH_LEN: usize = 20;
pub type Node<'a> = (&'a str, u16);
pub type MainTracker<'a> = &'a str;
pub enum ContactType<'a> {
Tracker(MainTracker<'a>),
Trackerless(Nodes<'a>),
Either(MainTracker<'a>, Nodes<'a>),
None
}
pub struct Nodes<'a> {
iter: Box<Iterator<Item=Node<'a>> + 'a>
}
impl<'a> Iterator for Nodes<'a> {
type Item = Node<'a>;
fn next(&mut self) -> Option<Node<'a>> {
self.iter.next()
}
}
pub trait TorrentView {
fn contact<'a>(&'a self) -> ContactType<'a>;
fn comment(&self) -> Option<&str>;
fn created_by(&self) -> Option<&str>;
fn creation_date(&self) -> Option<i64>;
fn piece_info<'a>(&'a self) -> PieceInfo<'a>;
fn file_info<'a>(&'a self) -> FileInfo<'a>;
fn info_hash(&self) -> InfoHash;
}
impl<'b, T> TorrentView for &'b T where T: TorrentView {
fn contact<'a>(&'a self) -> ContactType<'a> {
TorrentView::contact(*self)
}
fn comment(&self) -> Option<&str> {
TorrentView::comment(*self)
}
fn created_by(&self) -> Option<&str> {
TorrentView::created_by(*self)
}
fn creation_date(&self) -> Option<i64> {
TorrentView::creation_date(*self)
}
fn piece_info<'a>(&'a self) -> PieceInfo<'a> {
TorrentView::piece_info(*self)
}
fn file_info<'a>(&'a self) -> FileInfo<'a> {
TorrentView::file_info(*self)
}
fn info_hash(&self) -> InfoHash {
TorrentView::info_hash(*self)
}
}
impl<'b, T> TorrentView for &'b mut T where T: TorrentView {
fn contact<'a>(&'a self) -> ContactType<'a> {
TorrentView::contact(*self)
}
fn comment(&self) -> Option<&str> {
TorrentView::comment(*self)
}
fn created_by(&self) -> Option<&str> {
TorrentView::created_by(*self)
}
fn creation_date(&self) -> Option<i64> {
TorrentView::creation_date(*self)
}
fn piece_info<'a>(&'a self) -> PieceInfo<'a> {
TorrentView::piece_info(*self)
}
fn file_info<'a>(&'a self) -> FileInfo<'a> {
TorrentView::file_info(*self)
}
fn info_hash(&self) -> InfoHash {
TorrentView::info_hash(*self)
}
}
pub struct PieceInfo<'a> {
pieces: &'a [u8],
length: i64
}
impl<'a> PieceInfo<'a> {
fn new(pieces: &'a [u8], length: i64) -> PieceInfo<'a> {
PieceInfo{ pieces: pieces, length: length }
}
pub fn length(&self) -> i64 {
self.length
}
pub fn pieces(&self) -> Pieces<'a> {
Pieces::new(self.pieces)
}
}
pub struct Pieces<'a> {
pieces: &'a [u8],
position: usize
}
impl<'a> Pieces<'a> {
fn new(pieces: &'a [u8]) -> Pieces<'a> {
Pieces{ pieces: pieces, position: 0 }
}
}
impl<'a> Iterator for Pieces<'a> {
type Item = &'a [u8];
fn next(&mut self) -> Option<&'a [u8]> {
if self.position >= self.pieces.len() {
None
} else {
let curr_pos = self.position;
self.position += PIECE_HASH_LEN;
Some(&self.pieces[curr_pos..curr_pos + PIECE_HASH_LEN])
}
}
}
pub struct FileInfo<'a> {
directory: Option<&'a str>,
file_iter: Files<'a>
}
impl<'a> FileInfo<'a> {
pub fn directory(&self) -> Option<&'a str> {
self.directory
}
pub fn files(self) -> Files<'a> {
self.file_iter
}
}
pub struct Files<'a> {
iter: Box<Iterator<Item=File<'a>> + 'a>
}
impl<'a> Iterator for Files<'a> {
type Item = File<'a>;
fn next(&mut self) -> Option<File<'a>> {
self.iter.next()
}
}
pub struct File<'a> {
length: i64,
checksum: Option<&'a [u8]>,
path_iter: FilePath<'a>
}
impl<'a> File<'a> {
pub fn length(&self) -> i64 {
self.length
}
pub fn checksum(&self) -> Option<&'a [u8]> {
self.checksum
}
pub fn path(self) -> FilePath<'a> {
self.path_iter
}
}
pub struct FilePath<'a> {
iter: Box<Iterator<Item=&'a str> + 'a>
}
impl<'a> Iterator for FilePath<'a> {
type Item = &'a str;
fn next(&mut self) -> Option<&'a str> {
self.iter.next()
}
}