summaryrefslogtreecommitdiff
path: root/src/Data/Torrent/Layout.hs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Data/Torrent/Layout.hs')
-rw-r--r--src/Data/Torrent/Layout.hs47
1 files changed, 33 insertions, 14 deletions
diff --git a/src/Data/Torrent/Layout.hs b/src/Data/Torrent/Layout.hs
index 409426be..6f0668f2 100644
--- a/src/Data/Torrent/Layout.hs
+++ b/src/Data/Torrent/Layout.hs
@@ -5,6 +5,8 @@
5-- Stability : experimental 5-- Stability : experimental
6-- Portability : portable 6-- Portability : portable
7-- 7--
8--
9--
8{-# LANGUAGE BangPatterns #-} 10{-# LANGUAGE BangPatterns #-}
9{-# LANGUAGE FlexibleInstances #-} 11{-# LANGUAGE FlexibleInstances #-}
10{-# LANGUAGE StandaloneDeriving #-} 12{-# LANGUAGE StandaloneDeriving #-}
@@ -13,25 +15,33 @@
13{-# LANGUAGE TemplateHaskell #-} 15{-# LANGUAGE TemplateHaskell #-}
14{-# OPTIONS -fno-warn-orphans #-} 16{-# OPTIONS -fno-warn-orphans #-}
15module Data.Torrent.Layout 17module Data.Torrent.Layout
16 ( -- * File attribytes 18 ( -- * File attributes
17 FileOffset 19 FileOffset
18 , FileSize 20 , FileSize
19 21
20 -- * Single file info 22 -- * Single file info
21 , FileInfo (..) 23 , FileInfo (..)
24
25 -- ** Lens
22 , fileLength 26 , fileLength
23 , filePath 27 , filePath
24 , fileMD5Sum 28 , fileMD5Sum
25 29
26 -- * File layout 30 -- * File layout
27 , LayoutInfo (..) 31 , LayoutInfo (..)
32
33 -- ** Lens
28 , singleFile 34 , singleFile
29 , multiFile 35 , multiFile
30 , rootDirName 36 , rootDirName
37
38 -- ** Predicates
31 , isSingleFile 39 , isSingleFile
32 , isMultiFile 40 , isMultiFile
33 , fileNumber 41
42 -- ** Folds
34 , contentLength 43 , contentLength
44 , fileCount
35 , blockCount 45 , blockCount
36 46
37 -- * Flat file layout 47 -- * Flat file layout
@@ -60,11 +70,14 @@ import Data.Typeable
60import System.FilePath 70import System.FilePath
61import System.Posix.Types 71import System.Posix.Types
62 72
73import Data.Torrent.Block
74
63 75
64{----------------------------------------------------------------------- 76{-----------------------------------------------------------------------
65-- File attribytes 77-- File attribytes
66-----------------------------------------------------------------------} 78-----------------------------------------------------------------------}
67 79
80-- | Size of a file in bytes.
68type FileSize = FileOffset 81type FileSize = FileOffset
69 82
70deriving instance FromJSON FileOffset 83deriving instance FromJSON FileOffset
@@ -75,7 +88,7 @@ deriving instance BEncode FileOffset
75-- File info both either from info dict or file list 88-- File info both either from info dict or file list
76-----------------------------------------------------------------------} 89-----------------------------------------------------------------------}
77 90
78-- | Contain info about one single file. 91-- | Contain metainfo about one single file.
79data FileInfo a = FileInfo { 92data FileInfo a = FileInfo {
80 fiLength :: {-# UNPACK #-} !FileSize 93 fiLength :: {-# UNPACK #-} !FileSize
81 -- ^ Length of the file in bytes. 94 -- ^ Length of the file in bytes.
@@ -87,9 +100,9 @@ data FileInfo a = FileInfo {
87 100
88 , fiName :: !a 101 , fiName :: !a
89 -- ^ One or more string elements that together represent the 102 -- ^ One or more string elements that together represent the
90 -- path and filename. Each element in the list corresponds to 103 -- path and filename. Each element in the list corresponds to
91 -- either a directory name or (in the case of the last 104 -- either a directory name or (in the case of the last element)
92 -- element) the filename. For example, the file: 105 -- the filename. For example, the file:
93 -- 106 --
94 -- > "dir1/dir2/file.ext" 107 -- > "dir1/dir2/file.ext"
95 -- 108 --
@@ -152,9 +165,16 @@ instance BEncode (FileInfo ByteString) where
152-- Original torrent file layout info 165-- Original torrent file layout info
153-----------------------------------------------------------------------} 166-----------------------------------------------------------------------}
154 167
168-- | Original (found in torrent file) layout info is either:
169--
170-- * Single file with its /name/.
171--
172-- * Multiple files with its relative file /paths/.
173--
155data LayoutInfo 174data LayoutInfo
156 = SingleFile 175 = SingleFile
157 { liFile :: !(FileInfo ByteString) 176 { -- | Single file info.
177 liFile :: !(FileInfo ByteString)
158 } 178 }
159 | MultiFile 179 | MultiFile
160 { -- | List of the all files that torrent contains. 180 { -- | List of the all files that torrent contains.
@@ -212,16 +232,14 @@ contentLength :: LayoutInfo -> FileSize
212contentLength SingleFile { liFile = FileInfo {..} } = fiLength 232contentLength SingleFile { liFile = FileInfo {..} } = fiLength
213contentLength MultiFile { liFiles = tfs } = sum (L.map fiLength tfs) 233contentLength MultiFile { liFiles = tfs } = sum (L.map fiLength tfs)
214 234
215-- | Get count of all files in torrent. 235-- | Get number of all files in torrent.
216fileNumber :: LayoutInfo -> Int 236fileCount :: LayoutInfo -> Int
217fileNumber SingleFile {..} = 1 237fileCount SingleFile {..} = 1
218fileNumber MultiFile {..} = L.length liFiles 238fileCount MultiFile {..} = L.length liFiles
219 239
220-- | Find number of blocks of the specified size. If torrent size is 240-- | Find number of blocks of the specified size. If torrent size is
221-- not a multiple of block size then the count is rounded up. 241-- not a multiple of block size then the count is rounded up.
222blockCount :: Int -- ^ Block size. 242blockCount :: BlockSize -> LayoutInfo -> Int
223 -> LayoutInfo -- ^ Torrent content info.
224 -> Int -- ^ Number of blocks.
225blockCount blkSize ci = contentLength ci `sizeInBase` blkSize 243blockCount blkSize ci = contentLength ci `sizeInBase` blkSize
226 244
227{----------------------------------------------------------------------- 245{-----------------------------------------------------------------------
@@ -249,6 +267,7 @@ flatLayout prefixPath MultiFile {..} = L.map mkPath liFiles
249 path = prefixPath </> BC.unpack liDirName 267 path = prefixPath </> BC.unpack liDirName
250 </> joinPath (L.map BC.unpack fiName) 268 </> joinPath (L.map BC.unpack fiName)
251 269
270-- | Calculate offset of each file based on its length, incrementally.
252accumOffsets :: Layout FileSize -> Layout FileOffset 271accumOffsets :: Layout FileSize -> Layout FileOffset
253accumOffsets = go 0 272accumOffsets = go 0
254 where 273 where