diff --git a/CHANGELOG.md b/CHANGELOG.md index ddbd24f..ba12082 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ * Add big-endian and little-endian parsers for `Word128`. This includes both the single and multiple element variants. * Export `reverseCommitsOntoChunks` from the `Unsafe` module. +* Add `Semigroup` and `Monoid` instances for `Chunks`. ## 0.3.0.0 -- 2019-10-17 diff --git a/src/Data/Bytes/Chunks.hs b/src/Data/Bytes/Chunks.hs index 983b541..64f3bb7 100644 --- a/src/Data/Bytes/Chunks.hs +++ b/src/Data/Bytes/Chunks.hs @@ -8,15 +8,17 @@ module Data.Bytes.Chunks ( Chunks(..) , concat + , reverse + , reverseOnto ) where -import Prelude hiding (length,concat) +import Prelude hiding (length,concat,reverse) import GHC.ST (ST(..)) import Data.Bytes.Types (Bytes(..)) import Data.Primitive (ByteArray(..),MutableByteArray(..)) import GHC.Exts (ByteArray#,MutableByteArray#) -import GHC.Exts (IsList,Int#,State#,Int(I#),(+#),(-#)) +import GHC.Exts (Int#,State#,Int(I#),(+#)) import Control.Monad.ST.Run (runByteArrayST) import qualified GHC.Exts as Exts @@ -26,6 +28,15 @@ data Chunks = ChunksCons {-# UNPACK #-} !Bytes !Chunks | ChunksNil +instance Semigroup Chunks where + ChunksNil <> a = a + cs@(ChunksCons _ _) <> ChunksNil = cs + as@(ChunksCons _ _) <> bs@(ChunksCons _ _) = + reverseOnto bs (reverse as) + +instance Monoid Chunks where + mempty = ChunksNil + concat :: Chunks -> ByteArray concat x = ByteArray (concat# x) @@ -69,6 +80,19 @@ copy# marr off (ChunksCons (Bytes{array,offset,length}) cs) s0 = case Exts.copyByteArray# (unBa array) (unI offset) marr off (unI length) s0 of s1 -> copy# marr (off +# unI length) cs s1 + +-- | Reverse chunks but not the bytes within each chunk. +reverse :: Chunks -> Chunks +reverse = reverseOnto ChunksNil + +-- | Variant of 'reverse' that allows the caller to provide +-- an initial list of chunks that the reversed chunks will +-- be pushed onto. +reverseOnto :: Chunks -> Chunks -> Chunks +reverseOnto !x ChunksNil = x +reverseOnto !x (ChunksCons y ys) = + reverseOnto (ChunksCons y x) ys + unI :: Int -> Int# unI (I# i) = i