diff options
Diffstat (limited to 'src/Data/Torrent/Layout.hs')
-rw-r--r-- | src/Data/Torrent/Layout.hs | 47 |
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 #-} |
15 | module Data.Torrent.Layout | 17 | module 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 | |||
60 | import System.FilePath | 70 | import System.FilePath |
61 | import System.Posix.Types | 71 | import System.Posix.Types |
62 | 72 | ||
73 | import 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. | ||
68 | type FileSize = FileOffset | 81 | type FileSize = FileOffset |
69 | 82 | ||
70 | deriving instance FromJSON FileOffset | 83 | deriving 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. |
79 | data FileInfo a = FileInfo { | 92 | data 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 | -- | ||
155 | data LayoutInfo | 174 | data 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 | |||
212 | contentLength SingleFile { liFile = FileInfo {..} } = fiLength | 232 | contentLength SingleFile { liFile = FileInfo {..} } = fiLength |
213 | contentLength MultiFile { liFiles = tfs } = sum (L.map fiLength tfs) | 233 | contentLength 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. |
216 | fileNumber :: LayoutInfo -> Int | 236 | fileCount :: LayoutInfo -> Int |
217 | fileNumber SingleFile {..} = 1 | 237 | fileCount SingleFile {..} = 1 |
218 | fileNumber MultiFile {..} = L.length liFiles | 238 | fileCount 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. |
222 | blockCount :: Int -- ^ Block size. | 242 | blockCount :: BlockSize -> LayoutInfo -> Int |
223 | -> LayoutInfo -- ^ Torrent content info. | ||
224 | -> Int -- ^ Number of blocks. | ||
225 | blockCount blkSize ci = contentLength ci `sizeInBase` blkSize | 243 | blockCount 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. | ||
252 | accumOffsets :: Layout FileSize -> Layout FileOffset | 271 | accumOffsets :: Layout FileSize -> Layout FileOffset |
253 | accumOffsets = go 0 | 272 | accumOffsets = go 0 |
254 | where | 273 | where |