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