module Codec.Goat.Fluid
( Fluid(..)
, fluidAppend
, fluidDump
, fluidFirst
, fluidHeads
, fluidNew
, fluidSelect
, fluidShift
) where
import Safe
import Codec.Goat.Frame
import Codec.Goat.Util
data Fluid r c = Fluid (Int, Int) [[r]] [c]
instance Show (Fluid r c) where
show (Fluid (l1, l2) rs cs) = unwords
[ "Fluid"
, "l1max=" ++ show l1
, "l2max=" ++ show l2
, "l1cur=" ++ show (length rs)
, "l2cur=" ++ show (length cs) ]
fluidNew :: (Int, Int)
-> Fluid r c
fluidNew ls = Fluid ls [[]] []
fluidFirst :: Fluid r c
-> Maybe r
fluidFirst (Fluid _ [] _) = Nothing
fluidFirst (Fluid _ (x:_) _) = headMay x
fluidHeads :: Frame r c
=> Fluid r c
-> [Maybe r]
fluidHeads (Fluid _ rs cs) = map headMay rs ++ map frameHead cs
fluidSelect :: Frame r c
=> Fluid r c
-> [Bool]
-> [r]
fluidSelect (Fluid _ rs cs) presence = rvalues ++ cvalues
where
(rpres, cpres) = splitAt (length rs) presence
rvalues = concat $ select rs rpres
cvalues = concatMap frameDecode (select cs cpres)
fluidShift :: Frame r c
=> Fluid r c
-> Fluid r c
fluidShift (Fluid ls@(l1, l2) rs cs)
| (null . last) rs || (length rs < l1) = Fluid ls newRs cs
| otherwise = Fluid ls newRs newCs
where
newRs = [] : bool rs (init rs) (length rs < l1)
newCs = frameEncode (last rs) : bool cs (init cs) (length cs < l2)
fluidAppend :: Fluid r c
-> r
-> Fluid r c
fluidAppend (Fluid ls [] cs) val = Fluid ls [[val]] cs
fluidAppend (Fluid ls (r:rs) cs) val = Fluid ls ((val:r):rs) cs
fluidDump :: Frame r c
=> Fluid r c
-> [r]
fluidDump (Fluid _ rs cs) = concat rs ++ concatMap frameDecode cs