{-# LANGUAGE OverloadedStrings #-}
module Binrep.Type.NullTerminated where
import Binrep
import FlatParse.Basic qualified as FP
import Rerefined.Predicate.Common
import Rerefined.Refine
import Data.ByteString qualified as B
import Data.Word ( Word8 )
data NullTerminate
instance Predicate NullTerminate where
type PredicateName d NullTerminate = "NullTerminate"
type NullTerminated = Refined NullTerminate
instance Refine NullTerminate B.ByteString where
validate :: Proxy# NullTerminate -> ByteString -> Maybe RefineFailure
validate Proxy# NullTerminate
p ByteString
a = Proxy# NullTerminate -> Bool -> Builder -> Maybe RefineFailure
forall {k} (p :: k).
(Predicate p, KnownPredicateName p) =>
Proxy# p -> Bool -> Builder -> Maybe RefineFailure
validateBool Proxy# NullTerminate
p (Bool -> Bool
not ((Word8 -> Bool) -> ByteString -> Bool
B.any (Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x00) ByteString
a)) (Builder -> Maybe RefineFailure) -> Builder -> Maybe RefineFailure
forall a b. (a -> b) -> a -> b
$
Builder
"null byte not permitted in null-terminated data"
instance BLen a => BLen (NullTerminated a) where
blen :: NullTerminated a -> Int
blen NullTerminated a
ra = Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a -> Int
forall a. BLen a => a -> Int
blen (NullTerminated a -> a
forall {k} (p :: k) a. Refined p a -> a
unrefine NullTerminated a
ra)
{-# INLINE blen #-}
instance Put a => Put (NullTerminated a) where
{-# INLINE put #-}
put :: NullTerminated a -> Putter
put NullTerminated a
a = a -> Putter
forall a. Put a => a -> Putter
put (NullTerminated a -> a
forall {k} (p :: k) a. Refined p a -> a
unrefine NullTerminated a
a) Putter -> Putter -> Putter
forall a. Semigroup a => a -> a -> a
<> forall a. Put a => a -> Putter
put @Word8 Word8
0x00
instance Get a => Get (NullTerminated a) where
{-# INLINE get #-}
get :: Getter (NullTerminated a)
get = a -> NullTerminated a
forall {k} a (p :: k). a -> Refined p a
unsafeRefine (a -> NullTerminated a)
-> ParserT PureMode (ParseError Pos Builder) a
-> Getter (NullTerminated a)
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> ParserT PureMode (ParseError Pos Builder) a
-> [Builder] -> ParserT PureMode (ParseError Pos Builder) a
forall (st :: ZeroBitType) text a.
ParserT st (ParseError Pos text) a
-> [text] -> ParserT st (ParseError Pos text) a
cut1 (ParserT PureMode (ParseError Pos Builder) a
-> ParserT PureMode (ParseError Pos Builder) a
forall (st :: ZeroBitType) e a. ParserT st e a -> ParserT st e a
FP.isolateToNextNull ParserT PureMode (ParseError Pos Builder) a
forall a. Get a => Getter a
get) [Builder]
e
where e :: [Builder]
e = [ Builder
"while isolating to next null"
, Builder
"either there was no next null in the input,"
, Builder
"or the inner parser didn't fully consume its input" ]