packed-0.1.0: src/Packed/Bytes.hs
{-# LANGUAGE BangPatterns #-}
{-# OPTIONS_GHC
-Weverything
-fno-warn-unsafe
-fno-warn-implicit-prelude
-fno-warn-missing-import-lists
-O2
#-}
module Packed.Bytes
( Bytes(..)
, pack
, unpack
, drop
, dropEnd
, replicate
, length
, foldl'
, take
, empty
, findByte
-- * Characters
, isAscii
) where
import Prelude hiding (take,length,replicate,drop)
import Packed.Bytes.Small (ByteArray(..))
import Data.Word (Word8)
import qualified Packed.Bytes.Window as BAW
import qualified Packed.Bytes.Small as BA
data Bytes = Bytes
{-# UNPACK #-} !ByteArray -- payload
{-# UNPACK #-} !Int -- offset
{-# UNPACK #-} !Int -- length
instance Eq Bytes where
Bytes arrA offA lenA == Bytes arrB offB lenB =
if lenA == lenB
then BAW.equality offA offB lenA arrA arrB
else False
pack :: [Word8] -> Bytes
pack bs = let arr = BA.pack bs in Bytes arr 0 (BA.length arr)
unpack :: Bytes -> [Word8]
unpack (Bytes arr off len) = go off
where
go :: Int -> [Word8]
go !ix = if ix < len + off
then BA.unsafeIndex arr ix : go (ix + 1)
else []
drop :: Int -> Bytes -> Bytes
drop n (Bytes arr off len) = if len > n
then Bytes arr (off + n) (len - n)
else empty
dropEnd :: Int -> Bytes -> Bytes
dropEnd n (Bytes arr off len) = if len > n
then Bytes arr off (len - n)
else empty
replicate :: Int -> Word8 -> Bytes
replicate len w = fromByteArray (BA.replicate len w)
fromByteArray :: ByteArray -> Bytes
fromByteArray ba = Bytes ba 0 (BA.length ba)
length :: Bytes -> Int
length (Bytes _ _ len) = len
findByte :: Word8 -> Bytes -> Maybe Int
findByte !w (Bytes arr off len) = case BAW.findByte off len w arr of
Just ix -> Just (ix - off)
Nothing -> Nothing
foldl' :: (a -> Word8 -> a) -> a -> Bytes -> a
foldl' f !acc0 (Bytes arr off len) = BAW.foldl' off len f acc0 arr
take :: Int -> Bytes -> Bytes
take !n (Bytes arr off len) = if n < len
then Bytes arr off (len - n)
else empty
empty :: Bytes
empty = Bytes BA.empty 0 0
isAscii :: Bytes -> Bool
isAscii (Bytes arr off len) = BAW.isAscii off len arr
-- In this implementation, we overallocate on each side to
-- make things line up with machine word boundaries. This
-- make the reversal eight times faster.
-- reverse :: Bytes -> Bytes
-- reverse (Bytes arr off len) =
-- let !leftWordIx = quot off (PM.sizeOf (undefined :: Word))
-- !rightWordIx = quot (off + len) (PM.sizeOf (undefined :: Word))