@@ -60,6 +60,7 @@ module Data.Binary.Bits.Get
6060
6161 -- ** Get bytes
6262 , getBool
63+ , getBool#
6364 , getWord8
6465 , getWord16
6566 , getWord32
@@ -114,6 +115,8 @@ import Control.Applicative
114115import Control.Monad (when,foldM_)
115116
116117import Prelude as P
118+import GHC.Word
119+import GHC.Base (uncheckedShiftLWord8#, wordToWord8#, Int (..), andWord8#, Word8#, (-#), Int#, xorI#, eqWord8#, TYPE)
117120
118121-- $bitget
119122-- Parse bits using a monad.
@@ -182,6 +185,18 @@ readBool (S bs o bo) = case bo of
182185 LL -> testBit (unsafeHead bs) o
183186 LB -> testBit (unsafeHead bs) o
184187
188+-- | Read a single bit
189+readBool# :: S -> Int
190+readBool# (S bs (I# o) bo) = case bo of
191+ BB -> testBit# (7# -# o)
192+ BL -> testBit# (7# -# o)
193+ LL -> testBit# o
194+ LB -> testBit# o
195+ where
196+ !(W8# w) = unsafeHead bs
197+ testBit# n = I# (((w `andWord8#` (wordToWord8# 1## `uncheckedShiftLWord8#` n)) `eqWord8#` wordToWord8# 0##) `xorI#` 1#)
198+
199+
185200-- | Extract a range of bits from (ws :: ByteString)
186201--
187202-- Constraint: 8 * (length ws -1 ) < o+n <= 8 * length ws
@@ -363,6 +378,10 @@ isEmpty = B $ \ (S bs o bo) -> if B.null bs
363378getBool :: BitGet Bool
364379getBool = block bool
365380
381+-- | Get 1 bit as a 'Bool'.
382+getBool# :: BitGet Int
383+getBool# = block bool#
384+
366385-- | Get @n@ bits as a 'Word8'. @n@ must be within @[0..8]@.
367386getWord8 :: Int -> BitGet Word8
368387getWord8 n = block (word8 n)
@@ -438,6 +457,10 @@ block (Block i p) = do
438457bool :: Block Bool
439458bool = Block 1 readBool
440459
460+-- | Read a 1 bit 'Bool'.
461+bool# :: Block Int
462+bool# = Block 1 readBool#
463+
441464-- | Read @n@ bits as a 'Word8'. @n@ must be within @[0..8]@.
442465word8 :: Int -> Block Word8
443466word8 n = Block n (readWordChecked 8 n)