{-# LANGUAGE DeriveGeneric #-} -- | Ring buffers. module Game.LambdaHack.Common.RingBuffer ( RingBuffer(rbLength) , empty, cons, uncons, toList ) where import Data.Binary import qualified Data.Vector as V import Data.Vector.Binary () import GHC.Generics (Generic) data RingBuffer a = RingBuffer { rbCarrier :: !(V.Vector a) , rbNext :: !Int , rbLength :: !Int } deriving (Show, Generic) instance Binary a => Binary (RingBuffer a) empty :: Int -> a -> RingBuffer a empty size dummy = RingBuffer (V.replicate size dummy) 0 0 cons :: a -> RingBuffer a -> RingBuffer a cons a RingBuffer{..} = let size = V.length rbCarrier incNext = (rbNext + 1) `mod` size incLength = min size $ rbLength + 1 in RingBuffer (rbCarrier V.// [(rbNext, a)]) incNext incLength uncons :: RingBuffer a -> Maybe (a, RingBuffer a) uncons RingBuffer{..} = let size = V.length rbCarrier decNext = (rbNext - 1) `mod` size in if rbLength == 0 then Nothing else Just ( rbCarrier V.! decNext , RingBuffer rbCarrier decNext (rbLength - 1) ) toList :: RingBuffer a -> [a] toList RingBuffer{..} = let l = V.toList rbCarrier size = V.length rbCarrier start = (rbNext + size - rbLength) `mod` size in take rbLength $ drop start $ l ++ l