@@ -32,7 +32,8 @@ import qualified Data.List as L
3232import qualified Data.ByteString as B
3333import Data.Sequence (Seq )
3434import qualified Data.Sequence as Seq
35- import Data.Monoid ((<>) )
35+ -- import Data.Monoid ((<>))
36+ import Data.Semigroup (Semigroup , (<>) )
3637import Control.Monad.Fix
3738
3839import GHC.Stack (HasCallStack )
@@ -109,7 +110,40 @@ data Streams f a = Streams
109110deriving instance Eq (f Word8 ) => Eq (Streams f a )
110111deriving instance Ord (f Word8 ) => Ord (Streams f a )
111112
112- instance ( Monoid (f Word8 )
113+ instance ( Semigroup (f Word8 )
114+ , Foldable f
115+ , Traversable f
116+ , Applicative f ) => Semigroup (Stream f a ) where
117+ lhs <> (S _ _ 0 ) = lhs
118+ (S _ _ 0 ) <> rhs = rhs
119+ (S w b p) <> (S w' b' p') =
120+ let r =
121+ case b of
122+ -- there are no bits in the buffer. We can simply
123+ -- concatinate lhs and rhs
124+ Buff 0 _ -> S (w <> w') b' (p+ p')
125+ -- there are already @n@ bites in the buffer. We will
126+ -- need to shift all the bits in the RHS left by 8-n.
127+ Buff n c | null w' -> case addBuff b b' of
128+ (Just w'', b'') -> S (w <> pure w'') b'' (p+ p')
129+ (Nothing , b'') -> S w b'' (p+ p')
130+ | otherwise -> let (l, w'') = L. mapAccumL (go' n) c w'
131+ in case addBuff (Buff n l) b' of
132+ (Just w''', b'') -> S (w <> w'' <> pure w''') b'' (p + p')
133+ (Nothing , b'') -> S (w <> w'') b'' (p + p')
134+ where go' :: Int -- ^ shift
135+ -> Word8 -- ^ buff
136+ -> Word8 -- ^ input
137+ -> ( Word8 -- ^ new buff
138+ , Word8 ) -- ^ output
139+ go' ! n ! b ! w = (shift w (n- 8 ), b .|. shift w n)
140+ in r
141+
142+ -- {-# SPECIALIZE instance Monoid (Stream Seq a) #-}
143+ -- {-# SPECIALIZE instance Monoid (Stream [] a) #-}
144+
145+ instance ( Semigroup (f Word8 )
146+ , Monoid (f Word8 )
113147 , Foldable f
114148 , Traversable f
115149 , Applicative f ) => Monoid (Stream f a ) where
@@ -139,16 +173,20 @@ instance ( Monoid (f Word8)
139173 go' ! n ! b ! w = (shift w (n- 8 ), b .|. shift w n)
140174 in r
141175
142- -- {-# SPECIALIZE instance Monoid (Stream Seq a) #-}
143- -- {-# SPECIALIZE instance Monoid (Stream [] a) #-}
176+
177+
178+ instance Semigroup (Streams f a ) where
179+ lhs <> (Streams _ 0 ) = lhs
180+ (Streams _ 0 ) <> rhs = rhs
181+ (Streams ss1 p1) <> (Streams ss2 p2) = Streams (ss1 <> ss2) (p1 + p2)
182+ -- {-# SPECIALIZE instance Monoid (Streams Seq a) #-}
183+ -- {-# SPECIALIZE instance Monoid (Streams [] a) #-}
144184
145185instance Monoid (Streams f a ) where
146- mempty = Streams mempty 0
147186 lhs `mappend` (Streams _ 0 ) = lhs
148187 (Streams _ 0 ) `mappend` rhs = rhs
149188 (Streams ss1 p1) `mappend` (Streams ss2 p2) = Streams (ss1 <> ss2) (p1 + p2)
150- -- {-# SPECIALIZE instance Monoid (Streams Seq a) #-}
151- -- {-# SPECIALIZE instance Monoid (Streams [] a) #-}
189+ mempty = Streams mempty 0
152190
153191-- mappend is not cheap here.
154192type ListStream = Stream [] Word8
0 commit comments