summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Data/Torrent.hs1
-rw-r--r--src/Data/Torrent/Block.hs33
-rw-r--r--src/Data/Torrent/Layout.hs47
-rw-r--r--src/Data/Torrent/Piece.hs2
-rw-r--r--src/Data/Torrent/Tree.hs16
5 files changed, 58 insertions, 41 deletions
diff --git a/src/Data/Torrent.hs b/src/Data/Torrent.hs
index 90ec0cc4..36b9de50 100644
--- a/src/Data/Torrent.hs
+++ b/src/Data/Torrent.hs
@@ -23,7 +23,6 @@
23{-# LANGUAGE DeriveDataTypeable #-} 23{-# LANGUAGE DeriveDataTypeable #-}
24{-# LANGUAGE TemplateHaskell #-} 24{-# LANGUAGE TemplateHaskell #-}
25{-# OPTIONS -fno-warn-orphans #-} 25{-# OPTIONS -fno-warn-orphans #-}
26-- TODO refine interface
27module Data.Torrent 26module Data.Torrent
28 ( -- * Info dictionary 27 ( -- * Info dictionary
29 InfoDict (..) 28 InfoDict (..)
diff --git a/src/Data/Torrent/Block.hs b/src/Data/Torrent/Block.hs
index ca3bef45..17907a39 100644
--- a/src/Data/Torrent/Block.hs
+++ b/src/Data/Torrent/Block.hs
@@ -7,12 +7,14 @@
7-- 7--
8-- TODO 8-- TODO
9-- 9--
10{-# LANGUAGE TemplateHaskell #-} 10{-# LANGUAGE GeneralizedNewtypeDeriving #-}
11{-# LANGUAGE TemplateHaskell #-}
11module Data.Torrent.Block 12module Data.Torrent.Block
12 ( -- * Block attributes 13 ( -- * Block attributes
13 BlockLIx 14 BlockLIx
14 , PieceLIx 15 , PieceLIx
15 , BlockSize (..) 16 , BlockSize
17 , defaultTransferSize
16 18
17 -- * Block index 19 -- * Block index
18 , BlockIx(..) 20 , BlockIx(..)
@@ -50,17 +52,14 @@ import Text.PrettyPrint
50-- Block attributes 52-- Block attributes
51-----------------------------------------------------------------------} 53-----------------------------------------------------------------------}
52 54
53newtype BlockSize = BlockSize { unBlockSize :: Int } 55type BlockSize = Int
54 deriving (Show, Eq, Num, ToJSON, FromJSON)
55
56-- | Widely used semi-official block size.
57instance Default BlockSize where
58 def = 16 * 1024
59 {-# INLINE def #-}
60
61type BlockLIx = Int 56type BlockLIx = Int
62type PieceLIx = Int 57type PieceLIx = Int
63 58
59-- | Widely used semi-official block size.
60defaultTransferSize :: BlockSize
61defaultTransferSize = 16 * 1024
62
64{----------------------------------------------------------------------- 63{-----------------------------------------------------------------------
65 Block Index 64 Block Index
66-----------------------------------------------------------------------} 65-----------------------------------------------------------------------}
@@ -98,33 +97,33 @@ instance Serialize BlockIx where
98 {-# SPECIALIZE instance Serialize BlockIx #-} 97 {-# SPECIALIZE instance Serialize BlockIx #-}
99 get = BlockIx <$> getInt 98 get = BlockIx <$> getInt
100 <*> getInt 99 <*> getInt
101 <*> (BlockSize <$> getInt) 100 <*> getInt
102 {-# INLINE get #-} 101 {-# INLINE get #-}
103 102
104 put BlockIx {..} = do 103 put BlockIx {..} = do
105 putInt ixPiece 104 putInt ixPiece
106 putInt ixOffset 105 putInt ixOffset
107 putInt (unBlockSize ixLength) 106 putInt ixLength
108 {-# INLINE put #-} 107 {-# INLINE put #-}
109 108
110instance Binary BlockIx where 109instance Binary BlockIx where
111 {-# SPECIALIZE instance Binary BlockIx #-} 110 {-# SPECIALIZE instance Binary BlockIx #-}
112 get = BlockIx <$> getIntB 111 get = BlockIx <$> getIntB
113 <*> getIntB 112 <*> getIntB
114 <*> (BlockSize <$> getIntB) 113 <*> getIntB
115 {-# INLINE get #-} 114 {-# INLINE get #-}
116 115
117 put BlockIx {..} = do 116 put BlockIx {..} = do
118 putIntB ixPiece 117 putIntB ixPiece
119 putIntB ixOffset 118 putIntB ixOffset
120 putIntB (unBlockSize ixLength) 119 putIntB ixLength
121 120
122-- | Format block index in human readable form. 121-- | Format block index in human readable form.
123ppBlockIx :: BlockIx -> Doc 122ppBlockIx :: BlockIx -> Doc
124ppBlockIx BlockIx {..} = 123ppBlockIx BlockIx {..} =
125 "piece = " <> int ixPiece <> "," <+> 124 "piece = " <> int ixPiece <> "," <+>
126 "offset = " <> int ixOffset <> "," <+> 125 "offset = " <> int ixOffset <> "," <+>
127 "length = " <> int (unBlockSize ixLength) 126 "length = " <> int ixLength
128 127
129{----------------------------------------------------------------------- 128{-----------------------------------------------------------------------
130 Block 129 Block
@@ -158,7 +157,7 @@ isPiece pieceSize (Block i offset bs) =
158{-# INLINE isPiece #-} 157{-# INLINE isPiece #-}
159 158
160pieceIx :: Int -> Int -> BlockIx 159pieceIx :: Int -> Int -> BlockIx
161pieceIx i = BlockIx i 0 . BlockSize 160pieceIx i = BlockIx i 0
162{-# INLINE pieceIx #-} 161{-# INLINE pieceIx #-}
163 162
164blockIx :: Block Lazy.ByteString -> BlockIx 163blockIx :: Block Lazy.ByteString -> BlockIx
@@ -177,5 +176,5 @@ ixRange pieceSize i = (offset, offset + len)
177 where 176 where
178 offset = fromIntegral pieceSize * fromIntegral (ixPiece i) 177 offset = fromIntegral pieceSize * fromIntegral (ixPiece i)
179 + fromIntegral (ixOffset i) 178 + fromIntegral (ixOffset i)
180 len = fromIntegral (unBlockSize (ixLength i)) 179 len = fromIntegral (ixLength i)
181{-# INLINE ixRange #-} 180{-# INLINE ixRange #-}
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
diff --git a/src/Data/Torrent/Piece.hs b/src/Data/Torrent/Piece.hs
index 96624729..27bc4879 100644
--- a/src/Data/Torrent/Piece.hs
+++ b/src/Data/Torrent/Piece.hs
@@ -85,7 +85,7 @@ maxPieceSize = 4 * 1024 * 1024
85{-# INLINE maxPieceSize #-} 85{-# INLINE maxPieceSize #-}
86 86
87minPieceSize :: Int 87minPieceSize :: Int
88minPieceSize = unBlockSize def * 4 88minPieceSize = defaultTransferSize * 4
89{-# INLINE minPieceSize #-} 89{-# INLINE minPieceSize #-}
90 90
91-- | NOTE: Have max and min size constrained to wide used 91-- | NOTE: Have max and min size constrained to wide used
diff --git a/src/Data/Torrent/Tree.hs b/src/Data/Torrent/Tree.hs
index e9a337a1..8c18041a 100644
--- a/src/Data/Torrent/Tree.hs
+++ b/src/Data/Torrent/Tree.hs
@@ -15,8 +15,8 @@ module Data.Torrent.Tree
15 , Data.Torrent.Tree.lookup 15 , Data.Torrent.Tree.lookup
16 , lookupDir 16 , lookupDir
17 17
18 , fileCount 18 , fileNumber
19 , dirCount 19 , dirNumber
20 ) where 20 ) where
21 21
22import Control.Arrow 22import Control.Arrow
@@ -62,10 +62,10 @@ lookupDir ps d
62 File _ -> Nothing 62 File _ -> Nothing
63 Dir es -> Just $ M.toList es 63 Dir es -> Just $ M.toList es
64 64
65fileCount :: DirTree a -> Sum Int 65fileNumber :: DirTree a -> Sum Int
66fileCount File {..} = Sum 1 66fileNumber File {..} = Sum 1
67fileCount Dir {..} = foldMap fileCount children 67fileNumber Dir {..} = foldMap fileNumber children
68 68
69dirCount :: DirTree a -> Sum Int 69dirNumber :: DirTree a -> Sum Int
70dirCount File {..} = Sum 0 70dirNumber File {..} = Sum 0
71dirCount Dir {..} = Sum 1 <> foldMap dirCount children 71dirNumber Dir {..} = Sum 1 <> foldMap dirNumber children