summaryrefslogtreecommitdiff
path: root/src/Network/BitTorrent/PeerWire/Bitfield.hs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Network/BitTorrent/PeerWire/Bitfield.hs')
-rw-r--r--src/Network/BitTorrent/PeerWire/Bitfield.hs88
1 files changed, 82 insertions, 6 deletions
diff --git a/src/Network/BitTorrent/PeerWire/Bitfield.hs b/src/Network/BitTorrent/PeerWire/Bitfield.hs
index c9357a25..5cbd4e86 100644
--- a/src/Network/BitTorrent/PeerWire/Bitfield.hs
+++ b/src/Network/BitTorrent/PeerWire/Bitfield.hs
@@ -12,23 +12,95 @@
12-- 12--
13module Network.BitTorrent.PeerWire.Bitfield 13module Network.BitTorrent.PeerWire.Bitfield
14 ( Bitfield(..) 14 ( Bitfield(..)
15
16 -- * Construction
17 , empty, full
18 , fromByteString, toByteString
19
20 -- * Query
21 , findMin, findMax, difference
22
23 -- * Serialization
15 , getBitfield, putBitfield, bitfieldByteCount 24 , getBitfield, putBitfield, bitfieldByteCount
16 ) where 25 ) where
17 26
18import Control.Applicative 27import Control.Applicative hiding (empty)
28import Data.Array.Unboxed
29import Data.Bits
19import Data.ByteString (ByteString) 30import Data.ByteString (ByteString)
20import qualified Data.ByteString as B 31import qualified Data.ByteString as B
21 32import Data.List as L
33import Data.Maybe
22import Data.Serialize 34import Data.Serialize
35import Data.Word
23 36
37import Network.BitTorrent.PeerWire.Block
38import Data.Torrent
24 39
25newtype Bitfield = MkBitfield { 40newtype Bitfield = MkBitfield {
26 bfBits :: ByteString 41 bfBits :: ByteString
42-- , bfSize :: Int
27 } deriving (Show, Eq, Ord) 43 } deriving (Show, Eq, Ord)
28 44
29bitfieldByteCount :: Bitfield -> Int 45
30bitfieldByteCount = B.length . bfBits 46empty :: Int -> Bitfield
31{-# INLINE bitfieldByteCount #-} 47empty n = MkBitfield $ B.replicate (sizeInBase n 8) 0
48
49full :: Int -> Bitfield
50full n = MkBitfield $ B.replicate (sizeInBase n 8) (complement 0)
51
52fromByteString :: ByteString -> Bitfield
53fromByteString = MkBitfield
54{-# INLINE fromByteString #-}
55
56toByteString :: Bitfield -> ByteString
57toByteString = bfBits
58{-# INLINE toByteString #-}
59
60combine :: [ByteString] -> Maybe ByteString
61combine [] = Nothing
62combine as@(a : _) = return $ foldr andBS empty as
63 where
64 andBS x acc = B.pack (B.zipWith (.&.) x acc)
65 empty = B.replicate (B.length a) 0
66
67frequencies :: [Bitfield] -> UArray PieceIx Int
68frequencies = undefined
69
70diffWord8 :: Word8 -> Word8 -> Word8
71diffWord8 a b = a .&. (a `xor` b)
72{-# INLINE diffWord8 #-}
73
74difference :: Bitfield -> Bitfield -> Bitfield
75difference a b = MkBitfield $ B.pack $ B.zipWith diffWord8 (bfBits a) (bfBits b)
76{-# INLINE difference #-}
77
78difference' :: ByteString -> ByteString -> ByteString
79difference' a b = undefined
80 where
81 go i = undefined
82
83
84-- TODO: bit tricks
85findMinWord8 :: Word8 -> Maybe Int
86findMinWord8 b = L.findIndex (testBit b) [0..bitSize (undefined :: Word8) - 1]
87{-# INLINE findMinWord8 #-}
88
89-- | Get min index of piece that the peer have.
90findMin :: Bitfield -> Maybe PieceIx
91findMin (MkBitfield b) = do
92 byteIx <- B.findIndex (0 /=) b
93 bitIx <- findMinWord8 (B.index b byteIx)
94 return $ byteIx * bitSize (undefined :: Word8) + bitIx
95{-# INLINE findMin #-}
96
97findMaxWord8 :: Word8 -> Maybe Int
98findMaxWord8 = error "bitfield: findMaxWord8"
99
100findMax :: Bitfield -> Maybe PieceIx
101findMax = error "bitfield: findMax"
102{-# INLINE findMax #-}
103
32 104
33getBitfield :: Int -> Get Bitfield 105getBitfield :: Int -> Get Bitfield
34getBitfield n = MkBitfield <$> getBytes n 106getBitfield n = MkBitfield <$> getBytes n
@@ -36,4 +108,8 @@ getBitfield n = MkBitfield <$> getBytes n
36 108
37putBitfield :: Bitfield -> Put 109putBitfield :: Bitfield -> Put
38putBitfield = putByteString . bfBits 110putBitfield = putByteString . bfBits
39{-# INLINE putBitfield #-} \ No newline at end of file 111{-# INLINE putBitfield #-}
112
113bitfieldByteCount :: Bitfield -> Int
114bitfieldByteCount = B.length . bfBits
115{-# INLINE bitfieldByteCount #-}