summaryrefslogtreecommitdiff
path: root/src/Data/Torrent.hs
diff options
context:
space:
mode:
authorSam T <pxqr.sta@gmail.com>2013-06-12 07:34:34 +0400
committerSam T <pxqr.sta@gmail.com>2013-06-12 07:34:34 +0400
commit5c3c114e0e84339f88892e08010bd8b1408431d1 (patch)
tree70763a0fa0fc3c9f7ecbf1242b479a55b07cf1e2 /src/Data/Torrent.hs
parent8b005c4eb0f58db974c342efe0821240f39a6331 (diff)
~ Minor fixes.
* Annotate all required fields as strict. These are always used and there is no reason to keep them lazy. * Augment user errors with location.
Diffstat (limited to 'src/Data/Torrent.hs')
-rw-r--r--src/Data/Torrent.hs51
1 files changed, 29 insertions, 22 deletions
diff --git a/src/Data/Torrent.hs b/src/Data/Torrent.hs
index 068e9cb6..ad57403e 100644
--- a/src/Data/Torrent.hs
+++ b/src/Data/Torrent.hs
@@ -21,6 +21,7 @@
21{-# LANGUAGE FlexibleInstances #-} 21{-# LANGUAGE FlexibleInstances #-}
22{-# LANGUAGE OverloadedStrings #-} 22{-# LANGUAGE OverloadedStrings #-}
23{-# LANGUAGE RecordWildCards #-} 23{-# LANGUAGE RecordWildCards #-}
24{-# LANGUAGE BangPatterns #-}
24-- TODO refine interface 25-- TODO refine interface
25module Data.Torrent 26module Data.Torrent
26 ( -- * Torrent 27 ( -- * Torrent
@@ -83,14 +84,14 @@ type Time = Text
83-- TODO more convenient form of torrent info. 84-- TODO more convenient form of torrent info.
84-- | Metainfo about particular torrent. 85-- | Metainfo about particular torrent.
85data Torrent = Torrent { 86data Torrent = Torrent {
86 tInfoHash :: InfoHash 87 tInfoHash :: !InfoHash
87 -- ^ SHA1 hash of the 'TorrentInfo' of the 'Torrent'. 88 -- ^ SHA1 hash of the 'TorrentInfo' of the 'Torrent'.
88 89
89 , tAnnounce :: URI 90 , tAnnounce :: !URI
90 -- ^ The URL of the tracker. 91 -- ^ The URL of the tracker.
91 92
92 -- NOTE: out of lexicographic order! 93 -- NOTE: out of lexicographic order!
93 , tInfo :: ContentInfo 94 , tInfo :: !ContentInfo
94 -- ^ Info about each content file. 95 -- ^ Info about each content file.
95 96
96 , tAnnounceList :: Maybe [[URI]] 97 , tAnnounceList :: Maybe [[URI]]
@@ -112,9 +113,9 @@ data Torrent = Torrent {
112 -- the info dictionary in the .torrent metafile. 113 -- the info dictionary in the .torrent metafile.
113 114
114 , tPublisher :: Maybe URI 115 , tPublisher :: Maybe URI
115 -- ^ Containing the RSA public key of the publisher of the torrent. 116 -- ^ Containing the RSA public key of the publisher of the
116 -- Private counterpart of this key that has the authority to allow 117 -- torrent. Private counterpart of this key that has the
117 -- new peers onto the swarm. 118 -- authority to allow new peers onto the swarm.
118 119
119 , tPublisherURL :: Maybe URI 120 , tPublisherURL :: Maybe URI
120 , tSignature :: Maybe ByteString 121 , tSignature :: Maybe ByteString
@@ -144,22 +145,22 @@ simpleTorrent announce info = torrent announce info
144-- | Info part of the .torrent file contain info about each content file. 145-- | Info part of the .torrent file contain info about each content file.
145data ContentInfo = 146data ContentInfo =
146 SingleFile { 147 SingleFile {
147 ciLength :: Integer 148 ciLength :: !Integer
148 -- ^ Length of the file in bytes. 149 -- ^ Length of the file in bytes.
149 150
150 , ciMD5sum :: Maybe ByteString 151 , ciMD5sum :: Maybe ByteString
151 -- ^ 32 character long MD5 sum of the file. 152 -- ^ 32 character long MD5 sum of the file.
152 -- Used by third-party tools, not by bittorrent protocol itself. 153 -- Used by third-party tools, not by bittorrent protocol itself.
153 154
154 , ciName :: ByteString 155 , ciName :: !ByteString
155 -- ^ Suggested name of the file single file. 156 -- ^ Suggested name of the file single file.
156 157
157 158
158 159
159 , ciPieceLength :: Int 160 , ciPieceLength :: !Int
160 -- ^ Number of bytes in each piece. 161 -- ^ Number of bytes in each piece.
161 162
162 , ciPieces :: ByteString 163 , ciPieces :: !ByteString
163 -- ^ Concatenation of all 20-byte SHA1 hash values. 164 -- ^ Concatenation of all 20-byte SHA1 hash values.
164 165
165 , ciPrivate :: Maybe Bool 166 , ciPrivate :: Maybe Bool
@@ -171,28 +172,28 @@ data ContentInfo =
171 } 172 }
172 173
173 | MultiFile { 174 | MultiFile {
174 ciFiles :: [FileInfo] 175 ciFiles :: ![FileInfo]
175 -- ^ List of the all files that torrent contains. 176 -- ^ List of the all files that torrent contains.
176 177
177 , ciName :: ByteString 178 , ciName :: !ByteString
178 -- | The file path of the directory in which to store all the files. 179 -- | The file path of the directory in which to store all the files.
179 180
180 , ciPieceLength :: Int 181 , ciPieceLength :: !Int
181 , ciPieces :: ByteString 182 , ciPieces :: !ByteString
182 , ciPrivate :: Maybe Bool 183 , ciPrivate :: Maybe Bool
183 } deriving (Show, Read, Eq) 184 } deriving (Show, Read, Eq)
184 185
185 186
186-- | Contain info about one single file. 187-- | Contain info about one single file.
187data FileInfo = FileInfo { 188data FileInfo = FileInfo {
188 fiLength :: Integer 189 fiLength :: !Integer
189 -- ^ Length of the file in bytes. 190 -- ^ Length of the file in bytes.
190 191
191 , fiMD5sum :: Maybe ByteString 192 , fiMD5sum :: Maybe ByteString
192 -- ^ 32 character long MD5 sum of the file. 193 -- ^ 32 character long MD5 sum of the file.
193 -- Used by third-party tools, not by bittorrent protocol itself. 194 -- Used by third-party tools, not by bittorrent protocol itself.
194 195
195 , fiPath :: [ByteString] 196 , fiPath :: ![ByteString]
196 -- ^ One or more string elements that together represent the 197 -- ^ One or more string elements that together represent the
197 -- path and filename. Each element in the list corresponds to 198 -- path and filename. Each element in the list corresponds to
198 -- either a directory name or (in the case of the last 199 -- either a directory name or (in the case of the last
@@ -323,16 +324,18 @@ blockCount :: Int -- ^ Block size.
323 -> Int -- ^ Number of blocks. 324 -> Int -- ^ Number of blocks.
324blockCount blkSize ci = contentLength ci `sizeInBase` blkSize 325blockCount blkSize ci = contentLength ci `sizeInBase` blkSize
325 326
326-- | File layout specifies the order and the size of each file in the storage. 327-- | File layout specifies the order and the size of each file in the
327-- Note that order of files is highly important since we coalesce all 328-- storage. Note that order of files is highly important since we
328-- the files in the given order to get the linear block address space. 329-- coalesce all the files in the given order to get the linear block
330-- address space.
329-- 331--
330type Layout = [(FilePath, Int)] 332type Layout = [(FilePath, Int)]
331 333
332-- | Extract files layout from torrent info with the given root path. 334-- | Extract files layout from torrent info with the given root path.
333contentLayout :: FilePath -- ^ Root path for the all torrent files. 335contentLayout :: FilePath -- ^ Root path for the all torrent files.
334 -> ContentInfo -- ^ Torrent content information. 336 -> ContentInfo -- ^ Torrent content information.
335 -> Layout -- ^ The all file paths prefixed with the given root. 337 -> Layout -- ^ The all file paths prefixed with the
338 -- given root.
336contentLayout rootPath = filesLayout 339contentLayout rootPath = filesLayout
337 where 340 where
338 filesLayout (SingleFile { ciName = name, ciLength = len }) 341 filesLayout (SingleFile { ciName = name, ciLength = len })
@@ -356,7 +359,11 @@ isMultiFile _ = False
356 359
357-- | Read and decode a .torrent file. 360-- | Read and decode a .torrent file.
358fromFile :: FilePath -> IO Torrent 361fromFile :: FilePath -> IO Torrent
359fromFile = B.readFile >=> either (throwIO . userError) return . decoded 362fromFile path = do
363 contents <- B.readFile path
364 case decoded contents of
365 Right !t -> return t
366 Left msg -> throwIO $ userError $ msg ++ " while reading torrent"
360 367
361{----------------------------------------------------------------------- 368{-----------------------------------------------------------------------
362 Info hash 369 Info hash