bytepatch-0.4.0: src/StreamPatch/Patch/Align.hs
module StreamPatch.Patch.Align where
import StreamPatch.Patch
import StreamPatch.HFunctorList ( hflStrip )
import GHC.Generics ( Generic )
import Data.Vinyl
import Data.Vinyl.TypeLevel
import Data.Functor.Const
data Meta st = Meta
{ mExpected :: Maybe st
-- ^ Absolute stream offset for edit. Used for checking against actual offset.
} deriving (Generic, Show, Eq)
data Error st
= ErrorAlignedToNegative Integer -- guaranteed negative
| ErrorDoesntMatchExpected st st
deriving (Generic, Show, Eq)
-- | Attempt to align the given patch to 0 using the given base.
--
-- The resulting seek is guaranteed to be non-negative, so you may use
-- natural-like types safely.
--
-- TODO Complicated.
align
:: forall sf st a ss is r rs
. ( Integral sf, Num st, Eq st
, r ~ Const (Meta st)
, rs ~ RDelete r ss
, RElem r ss (RIndex r ss)
, RSubset rs ss is )
=> Integer
-> Patch sf ss a
-> Either (Error st) (Patch st rs a)
align sBase (Patch a s ms)
| s' < 0 = Left $ ErrorAlignedToNegative s'
| otherwise =
case mExpected m of
Nothing -> Right $ Patch a s'' ms'
Just sExpected ->
if sExpected == s''
then Right $ Patch a s'' ms'
else Left $ ErrorDoesntMatchExpected sExpected s''
where
s' = sBase + toInteger s
s'' = fromInteger s'
(m, ms') = hflStrip getConst ms