-- | BitTorrent metainfo files
--
-- <http://www.bittorrent.org/beps/bep_0003.html>

{-# LANGUAGE DeriveDataTypeable #-}

module Data.Torrent
	( Torrent(..)
	, TorrentInfo(..)
	, TorrentFile(..)
	, readTorrent
	, serializeTorrent
	, torrentSize
	, showTorrent
	) where

import Data.BEncode
import Data.BEncode.Parser
import Data.Binary
import Data.Generics
import Data.Maybe

import qualified Data.ByteString.Lazy as BS
import Data.ByteString.Lazy (ByteString)

import qualified Data.Map as Map

data Torrent
	= Torrent
		{ Torrent -> Maybe ByteString
tAnnounce     :: Maybe ByteString
		, Torrent -> [ByteString]
tAnnounceList :: [ByteString]
		, Torrent -> ByteString
tComment      :: ByteString
		, Torrent -> Maybe ByteString
tCreatedBy    :: Maybe ByteString
		, Torrent -> TorrentInfo
tInfo         :: TorrentInfo
		}
	deriving (Int -> Torrent -> ShowS
[Torrent] -> ShowS
Torrent -> String
(Int -> Torrent -> ShowS)
-> (Torrent -> String) -> ([Torrent] -> ShowS) -> Show Torrent
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Torrent] -> ShowS
$cshowList :: [Torrent] -> ShowS
show :: Torrent -> String
$cshow :: Torrent -> String
showsPrec :: Int -> Torrent -> ShowS
$cshowsPrec :: Int -> Torrent -> ShowS
Show, ReadPrec [Torrent]
ReadPrec Torrent
Int -> ReadS Torrent
ReadS [Torrent]
(Int -> ReadS Torrent)
-> ReadS [Torrent]
-> ReadPrec Torrent
-> ReadPrec [Torrent]
-> Read Torrent
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [Torrent]
$creadListPrec :: ReadPrec [Torrent]
readPrec :: ReadPrec Torrent
$creadPrec :: ReadPrec Torrent
readList :: ReadS [Torrent]
$creadList :: ReadS [Torrent]
readsPrec :: Int -> ReadS Torrent
$creadsPrec :: Int -> ReadS Torrent
Read, Typeable, Typeable Torrent
DataType
Constr
Typeable Torrent
-> (forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> Torrent -> c Torrent)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c Torrent)
-> (Torrent -> Constr)
-> (Torrent -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c Torrent))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Torrent))
-> ((forall b. Data b => b -> b) -> Torrent -> Torrent)
-> (forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> Torrent -> r)
-> (forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> Torrent -> r)
-> (forall u. (forall d. Data d => d -> u) -> Torrent -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> Torrent -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> Torrent -> m Torrent)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> Torrent -> m Torrent)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> Torrent -> m Torrent)
-> Data Torrent
Torrent -> DataType
Torrent -> Constr
(forall b. Data b => b -> b) -> Torrent -> Torrent
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Torrent -> c Torrent
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Torrent
forall a.
Typeable a
-> (forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u. Int -> (forall d. Data d => d -> u) -> Torrent -> u
forall u. (forall d. Data d => d -> u) -> Torrent -> [u]
forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> Torrent -> r
forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> Torrent -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> Torrent -> m Torrent
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Torrent -> m Torrent
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Torrent
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Torrent -> c Torrent
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c Torrent)
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Torrent)
$cTorrent :: Constr
$tTorrent :: DataType
gmapMo :: (forall d. Data d => d -> m d) -> Torrent -> m Torrent
$cgmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Torrent -> m Torrent
gmapMp :: (forall d. Data d => d -> m d) -> Torrent -> m Torrent
$cgmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Torrent -> m Torrent
gmapM :: (forall d. Data d => d -> m d) -> Torrent -> m Torrent
$cgmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> Torrent -> m Torrent
gmapQi :: Int -> (forall d. Data d => d -> u) -> Torrent -> u
$cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> Torrent -> u
gmapQ :: (forall d. Data d => d -> u) -> Torrent -> [u]
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> Torrent -> [u]
gmapQr :: (r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> Torrent -> r
$cgmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> Torrent -> r
gmapQl :: (r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> Torrent -> r
$cgmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> Torrent -> r
gmapT :: (forall b. Data b => b -> b) -> Torrent -> Torrent
$cgmapT :: (forall b. Data b => b -> b) -> Torrent -> Torrent
dataCast2 :: (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Torrent)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Torrent)
dataCast1 :: (forall d. Data d => c (t d)) -> Maybe (c Torrent)
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c Torrent)
dataTypeOf :: Torrent -> DataType
$cdataTypeOf :: Torrent -> DataType
toConstr :: Torrent -> Constr
$ctoConstr :: Torrent -> Constr
gunfold :: (forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Torrent
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Torrent
gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Torrent -> c Torrent
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Torrent -> c Torrent
$cp1Data :: Typeable Torrent
Data)

data TorrentInfo
	= SingleFile
		{ TorrentInfo -> Integer
tLength      :: Integer
		, TorrentInfo -> ByteString
tName        :: ByteString
		, TorrentInfo -> Integer
tPieceLength :: Integer
		, TorrentInfo -> ByteString
tPieces      :: ByteString }
	| MultiFile
		{ TorrentInfo -> [TorrentFile]
tFiles       :: [TorrentFile]
		, tName        :: ByteString
		, tPieceLength :: Integer
		, tPieces      :: ByteString
		}
	deriving (Int -> TorrentInfo -> ShowS
[TorrentInfo] -> ShowS
TorrentInfo -> String
(Int -> TorrentInfo -> ShowS)
-> (TorrentInfo -> String)
-> ([TorrentInfo] -> ShowS)
-> Show TorrentInfo
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [TorrentInfo] -> ShowS
$cshowList :: [TorrentInfo] -> ShowS
show :: TorrentInfo -> String
$cshow :: TorrentInfo -> String
showsPrec :: Int -> TorrentInfo -> ShowS
$cshowsPrec :: Int -> TorrentInfo -> ShowS
Show, ReadPrec [TorrentInfo]
ReadPrec TorrentInfo
Int -> ReadS TorrentInfo
ReadS [TorrentInfo]
(Int -> ReadS TorrentInfo)
-> ReadS [TorrentInfo]
-> ReadPrec TorrentInfo
-> ReadPrec [TorrentInfo]
-> Read TorrentInfo
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [TorrentInfo]
$creadListPrec :: ReadPrec [TorrentInfo]
readPrec :: ReadPrec TorrentInfo
$creadPrec :: ReadPrec TorrentInfo
readList :: ReadS [TorrentInfo]
$creadList :: ReadS [TorrentInfo]
readsPrec :: Int -> ReadS TorrentInfo
$creadsPrec :: Int -> ReadS TorrentInfo
Read, Typeable, Typeable TorrentInfo
DataType
Constr
Typeable TorrentInfo
-> (forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> TorrentInfo -> c TorrentInfo)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c TorrentInfo)
-> (TorrentInfo -> Constr)
-> (TorrentInfo -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c TorrentInfo))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e))
    -> Maybe (c TorrentInfo))
-> ((forall b. Data b => b -> b) -> TorrentInfo -> TorrentInfo)
-> (forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> TorrentInfo -> r)
-> (forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> TorrentInfo -> r)
-> (forall u. (forall d. Data d => d -> u) -> TorrentInfo -> [u])
-> (forall u.
    Int -> (forall d. Data d => d -> u) -> TorrentInfo -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> TorrentInfo -> m TorrentInfo)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> TorrentInfo -> m TorrentInfo)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> TorrentInfo -> m TorrentInfo)
-> Data TorrentInfo
TorrentInfo -> DataType
TorrentInfo -> Constr
(forall b. Data b => b -> b) -> TorrentInfo -> TorrentInfo
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> TorrentInfo -> c TorrentInfo
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c TorrentInfo
forall a.
Typeable a
-> (forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u. Int -> (forall d. Data d => d -> u) -> TorrentInfo -> u
forall u. (forall d. Data d => d -> u) -> TorrentInfo -> [u]
forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> TorrentInfo -> r
forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> TorrentInfo -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> TorrentInfo -> m TorrentInfo
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> TorrentInfo -> m TorrentInfo
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c TorrentInfo
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> TorrentInfo -> c TorrentInfo
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c TorrentInfo)
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c TorrentInfo)
$cMultiFile :: Constr
$cSingleFile :: Constr
$tTorrentInfo :: DataType
gmapMo :: (forall d. Data d => d -> m d) -> TorrentInfo -> m TorrentInfo
$cgmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> TorrentInfo -> m TorrentInfo
gmapMp :: (forall d. Data d => d -> m d) -> TorrentInfo -> m TorrentInfo
$cgmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> TorrentInfo -> m TorrentInfo
gmapM :: (forall d. Data d => d -> m d) -> TorrentInfo -> m TorrentInfo
$cgmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> TorrentInfo -> m TorrentInfo
gmapQi :: Int -> (forall d. Data d => d -> u) -> TorrentInfo -> u
$cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> TorrentInfo -> u
gmapQ :: (forall d. Data d => d -> u) -> TorrentInfo -> [u]
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> TorrentInfo -> [u]
gmapQr :: (r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> TorrentInfo -> r
$cgmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> TorrentInfo -> r
gmapQl :: (r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> TorrentInfo -> r
$cgmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> TorrentInfo -> r
gmapT :: (forall b. Data b => b -> b) -> TorrentInfo -> TorrentInfo
$cgmapT :: (forall b. Data b => b -> b) -> TorrentInfo -> TorrentInfo
dataCast2 :: (forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c TorrentInfo)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c TorrentInfo)
dataCast1 :: (forall d. Data d => c (t d)) -> Maybe (c TorrentInfo)
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c TorrentInfo)
dataTypeOf :: TorrentInfo -> DataType
$cdataTypeOf :: TorrentInfo -> DataType
toConstr :: TorrentInfo -> Constr
$ctoConstr :: TorrentInfo -> Constr
gunfold :: (forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c TorrentInfo
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c TorrentInfo
gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> TorrentInfo -> c TorrentInfo
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> TorrentInfo -> c TorrentInfo
$cp1Data :: Typeable TorrentInfo
Data)

data TorrentFile
	= TorrentFile
		{ TorrentFile -> Integer
fileLength :: Integer
		, TorrentFile -> [ByteString]
filePath   :: [ByteString]
		}
	deriving (Int -> TorrentFile -> ShowS
[TorrentFile] -> ShowS
TorrentFile -> String
(Int -> TorrentFile -> ShowS)
-> (TorrentFile -> String)
-> ([TorrentFile] -> ShowS)
-> Show TorrentFile
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [TorrentFile] -> ShowS
$cshowList :: [TorrentFile] -> ShowS
show :: TorrentFile -> String
$cshow :: TorrentFile -> String
showsPrec :: Int -> TorrentFile -> ShowS
$cshowsPrec :: Int -> TorrentFile -> ShowS
Show, ReadPrec [TorrentFile]
ReadPrec TorrentFile
Int -> ReadS TorrentFile
ReadS [TorrentFile]
(Int -> ReadS TorrentFile)
-> ReadS [TorrentFile]
-> ReadPrec TorrentFile
-> ReadPrec [TorrentFile]
-> Read TorrentFile
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [TorrentFile]
$creadListPrec :: ReadPrec [TorrentFile]
readPrec :: ReadPrec TorrentFile
$creadPrec :: ReadPrec TorrentFile
readList :: ReadS [TorrentFile]
$creadList :: ReadS [TorrentFile]
readsPrec :: Int -> ReadS TorrentFile
$creadsPrec :: Int -> ReadS TorrentFile
Read, Typeable, Typeable TorrentFile
DataType
Constr
Typeable TorrentFile
-> (forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> TorrentFile -> c TorrentFile)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c TorrentFile)
-> (TorrentFile -> Constr)
-> (TorrentFile -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c TorrentFile))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e))
    -> Maybe (c TorrentFile))
-> ((forall b. Data b => b -> b) -> TorrentFile -> TorrentFile)
-> (forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> TorrentFile -> r)
-> (forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> TorrentFile -> r)
-> (forall u. (forall d. Data d => d -> u) -> TorrentFile -> [u])
-> (forall u.
    Int -> (forall d. Data d => d -> u) -> TorrentFile -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> TorrentFile -> m TorrentFile)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> TorrentFile -> m TorrentFile)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> TorrentFile -> m TorrentFile)
-> Data TorrentFile
TorrentFile -> DataType
TorrentFile -> Constr
(forall b. Data b => b -> b) -> TorrentFile -> TorrentFile
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> TorrentFile -> c TorrentFile
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c TorrentFile
forall a.
Typeable a
-> (forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u. Int -> (forall d. Data d => d -> u) -> TorrentFile -> u
forall u. (forall d. Data d => d -> u) -> TorrentFile -> [u]
forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> TorrentFile -> r
forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> TorrentFile -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> TorrentFile -> m TorrentFile
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> TorrentFile -> m TorrentFile
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c TorrentFile
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> TorrentFile -> c TorrentFile
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c TorrentFile)
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c TorrentFile)
$cTorrentFile :: Constr
$tTorrentFile :: DataType
gmapMo :: (forall d. Data d => d -> m d) -> TorrentFile -> m TorrentFile
$cgmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> TorrentFile -> m TorrentFile
gmapMp :: (forall d. Data d => d -> m d) -> TorrentFile -> m TorrentFile
$cgmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> TorrentFile -> m TorrentFile
gmapM :: (forall d. Data d => d -> m d) -> TorrentFile -> m TorrentFile
$cgmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> TorrentFile -> m TorrentFile
gmapQi :: Int -> (forall d. Data d => d -> u) -> TorrentFile -> u
$cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> TorrentFile -> u
gmapQ :: (forall d. Data d => d -> u) -> TorrentFile -> [u]
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> TorrentFile -> [u]
gmapQr :: (r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> TorrentFile -> r
$cgmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> TorrentFile -> r
gmapQl :: (r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> TorrentFile -> r
$cgmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> TorrentFile -> r
gmapT :: (forall b. Data b => b -> b) -> TorrentFile -> TorrentFile
$cgmapT :: (forall b. Data b => b -> b) -> TorrentFile -> TorrentFile
dataCast2 :: (forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c TorrentFile)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c TorrentFile)
dataCast1 :: (forall d. Data d => c (t d)) -> Maybe (c TorrentFile)
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c TorrentFile)
dataTypeOf :: TorrentFile -> DataType
$cdataTypeOf :: TorrentFile -> DataType
toConstr :: TorrentFile -> Constr
$ctoConstr :: TorrentFile -> Constr
gunfold :: (forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c TorrentFile
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c TorrentFile
gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> TorrentFile -> c TorrentFile
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> TorrentFile -> c TorrentFile
$cp1Data :: Typeable TorrentFile
Data)

instance Binary Torrent where
	put :: Torrent -> Put
put = BEncode -> Put
forall t. Binary t => t -> Put
put (BEncode -> Put) -> (Torrent -> BEncode) -> Torrent -> Put
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Torrent -> BEncode
serializeTorrent
	get :: Get Torrent
get = do
		ByteString
e <- Get ByteString
forall t. Binary t => Get t
get
		case ByteString -> Either String Torrent
readTorrent ByteString
e of
			Left String
err -> String -> Get Torrent
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String -> Get Torrent) -> String -> Get Torrent
forall a b. (a -> b) -> a -> b
$ String
"Failed to parse torrent: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
err
			Right Torrent
t  -> Torrent -> Get Torrent
forall (m :: * -> *) a. Monad m => a -> m a
return Torrent
t

-- | Size of the files in the torrent.
torrentSize :: Torrent -> Integer
torrentSize :: Torrent -> Integer
torrentSize Torrent
torrent = case Torrent -> TorrentInfo
tInfo Torrent
torrent of
	s :: TorrentInfo
s@SingleFile{} -> TorrentInfo -> Integer
tLength TorrentInfo
s
	MultiFile{tFiles :: TorrentInfo -> [TorrentFile]
tFiles=[TorrentFile]
files} -> [Integer] -> Integer
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum ((TorrentFile -> Integer) -> [TorrentFile] -> [Integer]
forall a b. (a -> b) -> [a] -> [b]
map TorrentFile -> Integer
fileLength [TorrentFile]
files)

readTorrent :: ByteString -> Either String Torrent
readTorrent :: ByteString -> Either String Torrent
readTorrent ByteString
inp = case ByteString -> Maybe BEncode
bRead ByteString
inp of
	Maybe BEncode
Nothing -> String -> Either String Torrent
forall a b. a -> Either a b
Left String
"Not BEncoded"
	Just BEncode
be -> BParser Torrent -> BEncode -> Either String Torrent
forall a. BParser a -> BEncode -> Either String a
runParser BParser Torrent
parseTorrent BEncode
be

parseTorrent :: BParser Torrent
parseTorrent :: BParser Torrent
parseTorrent = do
	Maybe ByteString
announce <- BParser ByteString -> BParser (Maybe ByteString)
forall a. BParser a -> BParser (Maybe a)
optional (BParser ByteString -> BParser (Maybe ByteString))
-> BParser ByteString -> BParser (Maybe ByteString)
forall a b. (a -> b) -> a -> b
$ BParser BEncode -> BParser ByteString
bbytestring (BParser BEncode -> BParser ByteString)
-> BParser BEncode -> BParser ByteString
forall a b. (a -> b) -> a -> b
$ String -> BParser BEncode
dict String
"announce"
	Maybe ByteString
creator <- BParser ByteString -> BParser (Maybe ByteString)
forall a. BParser a -> BParser (Maybe a)
optional (BParser ByteString -> BParser (Maybe ByteString))
-> BParser ByteString -> BParser (Maybe ByteString)
forall a b. (a -> b) -> a -> b
$ BParser BEncode -> BParser ByteString
bbytestring (BParser BEncode -> BParser ByteString)
-> BParser BEncode -> BParser ByteString
forall a b. (a -> b) -> a -> b
$ String -> BParser BEncode
dict String
"created by"
	BEncode
info <- String -> BParser BEncode
dict String
"info"
	BEncode -> BParser ()
setInput BEncode
info
	ByteString
name <- BParser BEncode -> BParser ByteString
bbytestring (BParser BEncode -> BParser ByteString)
-> BParser BEncode -> BParser ByteString
forall a b. (a -> b) -> a -> b
$ String -> BParser BEncode
dict String
"name"
	Integer
pLen <- BParser BEncode -> BParser Integer
bint (BParser BEncode -> BParser Integer)
-> BParser BEncode -> BParser Integer
forall a b. (a -> b) -> a -> b
$ String -> BParser BEncode
dict String
"piece length"
	ByteString
pieces <- BParser BEncode -> BParser ByteString
bbytestring (BParser BEncode -> BParser ByteString)
-> BParser BEncode -> BParser ByteString
forall a b. (a -> b) -> a -> b
$ String -> BParser BEncode
dict String
"pieces"
	TorrentInfo
torrentInfo <- ByteString -> Integer -> ByteString -> BParser TorrentInfo
parseTorrentInfo ByteString
name Integer
pLen ByteString
pieces
	Torrent -> BParser Torrent
forall (m :: * -> *) a. Monad m => a -> m a
return (Torrent -> BParser Torrent) -> Torrent -> BParser Torrent
forall a b. (a -> b) -> a -> b
$ Maybe ByteString
-> [ByteString]
-> ByteString
-> Maybe ByteString
-> TorrentInfo
-> Torrent
Torrent Maybe ByteString
announce [] ByteString
BS.empty Maybe ByteString
creator TorrentInfo
torrentInfo

parseTorrentInfo :: ByteString -> Integer -> ByteString -> BParser TorrentInfo
parseTorrentInfo :: ByteString -> Integer -> ByteString -> BParser TorrentInfo
parseTorrentInfo ByteString
name Integer
pLen ByteString
pieces = BParser TorrentInfo
single BParser TorrentInfo -> BParser TorrentInfo -> BParser TorrentInfo
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> BParser TorrentInfo
multi
  where
	single :: BParser TorrentInfo
single = do
		Integer
len <- BParser BEncode -> BParser Integer
bint (BParser BEncode -> BParser Integer)
-> BParser BEncode -> BParser Integer
forall a b. (a -> b) -> a -> b
$ String -> BParser BEncode
dict String
"length"
		TorrentInfo -> BParser TorrentInfo
forall (m :: * -> *) a. Monad m => a -> m a
return (TorrentInfo -> BParser TorrentInfo)
-> TorrentInfo -> BParser TorrentInfo
forall a b. (a -> b) -> a -> b
$ Integer -> ByteString -> Integer -> ByteString -> TorrentInfo
SingleFile Integer
len ByteString
name Integer
pLen ByteString
pieces
	multi :: BParser TorrentInfo
multi = do
		[TorrentFile]
files <- String -> BParser TorrentFile -> BParser [TorrentFile]
forall a. String -> BParser a -> BParser [a]
list String
"files" (BParser TorrentFile -> BParser [TorrentFile])
-> BParser TorrentFile -> BParser [TorrentFile]
forall a b. (a -> b) -> a -> b
$ do
			Integer
len <- BParser BEncode -> BParser Integer
bint (BParser BEncode -> BParser Integer)
-> BParser BEncode -> BParser Integer
forall a b. (a -> b) -> a -> b
$ String -> BParser BEncode
dict String
"length"
			[ByteString]
filePaths <- String -> BParser ByteString -> BParser [ByteString]
forall a. String -> BParser a -> BParser [a]
list String
"path" (BParser ByteString -> BParser [ByteString])
-> BParser ByteString -> BParser [ByteString]
forall a b. (a -> b) -> a -> b
$ BParser BEncode -> BParser ByteString
bbytestring BParser BEncode
token
			TorrentFile -> BParser TorrentFile
forall (m :: * -> *) a. Monad m => a -> m a
return (TorrentFile -> BParser TorrentFile)
-> TorrentFile -> BParser TorrentFile
forall a b. (a -> b) -> a -> b
$ Integer -> [ByteString] -> TorrentFile
TorrentFile Integer
len [ByteString]
filePaths
		TorrentInfo -> BParser TorrentInfo
forall (m :: * -> *) a. Monad m => a -> m a
return (TorrentInfo -> BParser TorrentInfo)
-> TorrentInfo -> BParser TorrentInfo
forall a b. (a -> b) -> a -> b
$ [TorrentFile] -> ByteString -> Integer -> ByteString -> TorrentInfo
MultiFile [TorrentFile]
files ByteString
name Integer
pLen ByteString
pieces

serializeTorrent :: Torrent -> BEncode
serializeTorrent :: Torrent -> BEncode
serializeTorrent Torrent
torrent = Map String BEncode -> BEncode
BDict (Map String BEncode -> BEncode) -> Map String BEncode -> BEncode
forall a b. (a -> b) -> a -> b
$ [(String, BEncode)] -> Map String BEncode
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList ([(String, BEncode)] -> Map String BEncode)
-> [(String, BEncode)] -> Map String BEncode
forall a b. (a -> b) -> a -> b
$ [Maybe (String, BEncode)] -> [(String, BEncode)]
forall a. [Maybe a] -> [a]
catMaybes
	[ (ByteString -> (String, BEncode))
-> Maybe ByteString -> Maybe (String, BEncode)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\ByteString
b -> (String
"announce", ByteString -> BEncode
BString ByteString
b)) (Torrent -> Maybe ByteString
tAnnounce Torrent
torrent)
	, (String, BEncode) -> Maybe (String, BEncode)
forall a. a -> Maybe a
Just (String
"comment", ByteString -> BEncode
BString (ByteString -> BEncode) -> ByteString -> BEncode
forall a b. (a -> b) -> a -> b
$ Torrent -> ByteString
tComment Torrent
torrent)
	, (String, BEncode) -> Maybe (String, BEncode)
forall a. a -> Maybe a
Just (String
"info", BEncode
info)
	]
  where
	info :: BEncode
info = Map String BEncode -> BEncode
BDict (Map String BEncode -> BEncode) -> Map String BEncode -> BEncode
forall a b. (a -> b) -> a -> b
$ [(String, BEncode)] -> Map String BEncode
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList ([(String, BEncode)] -> Map String BEncode)
-> [(String, BEncode)] -> Map String BEncode
forall a b. (a -> b) -> a -> b
$
		[ (String
"name", ByteString -> BEncode
BString (ByteString -> BEncode) -> ByteString -> BEncode
forall a b. (a -> b) -> a -> b
$ TorrentInfo -> ByteString
tName (Torrent -> TorrentInfo
tInfo Torrent
torrent))
		, (String
"pieces", ByteString -> BEncode
BString (ByteString -> BEncode) -> ByteString -> BEncode
forall a b. (a -> b) -> a -> b
$ TorrentInfo -> ByteString
tPieces (Torrent -> TorrentInfo
tInfo Torrent
torrent))
		, (String
"piece length", Integer -> BEncode
BInt (Integer -> BEncode) -> Integer -> BEncode
forall a b. (a -> b) -> a -> b
$ TorrentInfo -> Integer
tPieceLength (Torrent -> TorrentInfo
tInfo Torrent
torrent))
		] [(String, BEncode)] -> [(String, BEncode)] -> [(String, BEncode)]
forall a. [a] -> [a] -> [a]
++ case Torrent -> TorrentInfo
tInfo Torrent
torrent of
			SingleFile Integer
len ByteString
_ Integer
_ ByteString
_ ->
				[ (String
"length", Integer -> BEncode
BInt Integer
len) ]
			MultiFile [TorrentFile]
files ByteString
_ Integer
_ ByteString
_ ->
				[ (String
"files", [BEncode] -> BEncode
BList ([BEncode] -> BEncode) -> [BEncode] -> BEncode
forall a b. (a -> b) -> a -> b
$ (TorrentFile -> BEncode) -> [TorrentFile] -> [BEncode]
forall a b. (a -> b) -> [a] -> [b]
map TorrentFile -> BEncode
serfile [TorrentFile]
files) ]

	serfile :: TorrentFile -> BEncode
serfile TorrentFile
file = Map String BEncode -> BEncode
BDict (Map String BEncode -> BEncode) -> Map String BEncode -> BEncode
forall a b. (a -> b) -> a -> b
$ [(String, BEncode)] -> Map String BEncode
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList
		[ (String
"length", Integer -> BEncode
BInt (TorrentFile -> Integer
fileLength TorrentFile
file))
		, (String
"path", [BEncode] -> BEncode
BList ((ByteString -> BEncode) -> [ByteString] -> [BEncode]
forall a b. (a -> b) -> [a] -> [b]
map ByteString -> BEncode
BString ([ByteString] -> [BEncode]) -> [ByteString] -> [BEncode]
forall a b. (a -> b) -> a -> b
$ TorrentFile -> [ByteString]
filePath TorrentFile
file))
		]

-- | generates a torrent file
--
-- Due to lexographical ordering requirements of BEncoded data, this
-- should generate the same ByteString that readTorrent read to generate
-- the Torrent. However, torrent files may contain extensions and
-- nonstandard fields that prevent that from holding for all torrent files.
showTorrent :: Torrent -> ByteString
showTorrent :: Torrent -> ByteString
showTorrent = BEncode -> ByteString
bPack (BEncode -> ByteString)
-> (Torrent -> BEncode) -> Torrent -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Torrent -> BEncode
serializeTorrent