module Database.Perdure.RootValidator (
RootValidator(..),
ValidationDigestWord(..),
module Database.Perdure.Validator
) where
import Data.Word
import Database.Perdure.Digest
import Cgm.Data.Maybe
import Cgm.Data.Len
import Database.Perdure.Validator
import Database.Perdure.CSerializer
import Database.Perdure.AllocCopy
class (AllocCopy w, Deserializable w, LgMultiple w Bool, LgMultiple w Word8, LgMultiple Word64 w, Persistent (ValidationDigest w),
Eq (ValidationDigest w), Show (ValidationDigest w)) => ValidationDigestWord w where
type ValidationDigest w
digest' :: (ImmArray r, PinnedArray r, ArrayElem r ~ w) => r -> ValidationDigest w
instance ValidationDigestWord Word32 where
type ValidationDigest Word32 = MD5Digest
digest' = digest
instance ValidationDigestWord Word64 where
type ValidationDigest Word64 = Skein512Digest Word128
digest' = digest
data RootValidator w = RootValidator deriving (Eq, Show)
type Header w = (Len w Word64, ValidationDigest w)
instance (ValidationDigestWord w, Show (ValidationDigest w)) => Validator (RootValidator w) where
type ValidatedElem (RootValidator w) = w
mkValidationInput b = (RootValidator, [serializeToArray persister ((fmap fromIntegral $ arrayLen b, digest' b) :: Header w), b])
validate RootValidator b =
let DeserOut ((len, h) :: Header w) u = deserializeFromArray (unsafeSeqDeserializer persister) b
payload = headArrayRange (fmap fromIntegral len) $ skipArrayRange (coarsenLen u) b
in payload `justIf` (digest' payload == h)
instance Persistent (RootValidator w) where persister = structureMap persister
deriveStructured ''RootValidator