-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Encode precise binary representations directly in types -- -- Please see README.md. @package binrep @version 0.6.0 module Binrep.Common.Class.TypeErrors -- | Common type error string for when you attempt to use a binrep instance -- at an empty data type (e.g. Void, V1). type ENoEmpty = 'Text "No binary representation for empty data type" -- | Common type error string for when you attempt to use a binrep instance -- at a sum data type GHC is asked to derive a non-sum instance, but the -- data type in question turns out to be a sum data type. -- -- No need to add the data type name here, since GHC's context includes -- the surrounding instance declaration. type ENoSum = 'Text "No binary representation for unannotated sum data type" :$$: 'Text "Consider defining a custom data type" :<>: 'Text " and deriving a generic instance with explicit sum handling" module Binrep.Common.Via.Prim -- | DerivingVia newtype for types which can borrow from Prim'. newtype ViaPrim a ViaPrim :: a -> ViaPrim a [unViaPrim] :: ViaPrim a -> a module Binrep.Type.Text.Internal type Bytes = ByteString -- | A string of a given encoding, stored in the Text type. -- -- Essentially Text carrying a proof that it can be successfully -- encoded into the given encoding. For example, AsText -- ASCII means the Text stored is pure ASCII. type AsText enc = Refined enc Text -- | Bytestring encoders for text validated for a given encoding. class Encode enc -- | Encode text to bytes. Internal function, use encode. encode' :: Encode enc => Text -> Bytes class Decode enc -- | Decode a ByteString to Text with an explicit encoding. -- -- This is intended to be used with visible type applications. decode :: Decode enc => Bytes -> Either String (AsText enc) -- | Helper for decoding a Bytes to a Text tagged with its -- encoding. decodeText :: forall enc e. (e -> String) -> (Bytes -> Either e Text) -> Bytes -> Either String (AsText enc) -- | Run an unsafe decoder safely. -- -- Copied from Data.Text.Encoding.decodeUtf8', so should be -- bulletproof? wrapUnsafeDecoder :: (Bytes -> Text) -> Bytes -> Either UnicodeException Text module Binrep.Type.Text.Encoding.Utf8 data Utf8 instance Binrep.Type.Text.Internal.Encode Binrep.Type.Text.Encoding.Utf8.Utf8 instance Binrep.Type.Text.Internal.Decode Binrep.Type.Text.Encoding.Utf8.Utf8 instance Refined.Predicate Binrep.Type.Text.Encoding.Utf8.Utf8 Data.Text.Internal.Text module Binrep.Type.Text.Encoding.ShiftJis data ShiftJis -- | Encode some Text to the given character set using text-icu. -- -- No guarantees about correctness. Encodings are weird. e.g. Shift JIS's -- yen/backslash problem is apparently to do with OSs treating it -- differently. -- -- Expects a Text that is confirmed valid for converting to the -- character set. -- -- The charset must be valid, or it's exception time. See text-icu. encodeViaTextICU :: String -> Text -> IO ByteString encodeViaTextICU' :: String -> Text -> ByteString decodeViaTextICU :: String -> ByteString -> IO (Either String Text) decodeViaTextICU' :: String -> ByteString -> Either String Text instance Refined.Predicate Binrep.Type.Text.Encoding.ShiftJis.ShiftJis Data.Text.Internal.Text instance Binrep.Type.Text.Internal.Encode Binrep.Type.Text.Encoding.ShiftJis.ShiftJis instance Binrep.Type.Text.Internal.Decode Binrep.Type.Text.Encoding.ShiftJis.ShiftJis module Binrep.Type.Text.Encoding.Ascii -- | 7-bit data Ascii catchErrorCall :: (a -> b) -> a -> Either String b instance Binrep.Type.Text.Internal.Encode Binrep.Type.Text.Encoding.Ascii.Ascii instance Binrep.Type.Text.Internal.Decode Binrep.Type.Text.Encoding.Ascii.Ascii instance Refined.Predicate Binrep.Type.Text.Encoding.Ascii.Ascii Data.Text.Internal.Text module Binrep.Util tshow :: Show a => a -> Text -- | Convert some Int i where i >= 0 to a -- Natural. -- -- This is intended for wrapping the output of length functions. -- -- underflows if you call it with a negative Int :) posIntToNat :: Int -> Natural natVal'' :: forall a. KnownNat a => Natural module Binrep.Util.ByteOrder -- | Byte ordering. data () => ByteOrder -- | most-significant-byte occurs in lowest address. BigEndian :: ByteOrder -- | least-significant-byte occurs in lowest address. LittleEndian :: ByteOrder newtype () => ByteOrdered (end :: ByteOrder) a ByteOrdered :: a -> ByteOrdered (end :: ByteOrder) a [unByteOrdered] :: ByteOrdered (end :: ByteOrder) a -> a type LE = 'LittleEndian type BE = 'BigEndian type Endian = ByteOrdered instance Strongweak.Weaken.Weaken a => Strongweak.Weaken.Weaken (Raehik.Compat.Data.Primitive.Types.Endian.ByteOrdered end a) instance Strongweak.Strengthen.Strengthen a => Strongweak.Strengthen.Strengthen (Raehik.Compat.Data.Primitive.Types.Endian.ByteOrdered end a) module Binrep.Type.Text.Encoding.Utf32 data Utf32 (end :: ByteOrder) instance Binrep.Type.Text.Internal.Encode (Binrep.Type.Text.Encoding.Utf32.Utf32 Binrep.Util.ByteOrder.BE) instance Binrep.Type.Text.Internal.Encode (Binrep.Type.Text.Encoding.Utf32.Utf32 Binrep.Util.ByteOrder.LE) instance Binrep.Type.Text.Internal.Decode (Binrep.Type.Text.Encoding.Utf32.Utf32 Binrep.Util.ByteOrder.BE) instance Binrep.Type.Text.Internal.Decode (Binrep.Type.Text.Encoding.Utf32.Utf32 Binrep.Util.ByteOrder.LE) instance Data.Typeable.Internal.Typeable end => Refined.Predicate (Binrep.Type.Text.Encoding.Utf32.Utf32 end) Data.Text.Internal.Text module Binrep.Type.Text.Encoding.Utf16 data Utf16 (end :: ByteOrder) instance Binrep.Type.Text.Internal.Encode (Binrep.Type.Text.Encoding.Utf16.Utf16 Binrep.Util.ByteOrder.BE) instance Binrep.Type.Text.Internal.Encode (Binrep.Type.Text.Encoding.Utf16.Utf16 Binrep.Util.ByteOrder.LE) instance Binrep.Type.Text.Internal.Decode (Binrep.Type.Text.Encoding.Utf16.Utf16 Binrep.Util.ByteOrder.BE) instance Binrep.Type.Text.Internal.Decode (Binrep.Type.Text.Encoding.Utf16.Utf16 Binrep.Util.ByteOrder.LE) instance Data.Typeable.Internal.Typeable end => Refined.Predicate (Binrep.Type.Text.Encoding.Utf16.Utf16 end) Data.Text.Internal.Text module Binrep.Type.Text -- | A string of a given encoding, stored in the Text type. -- -- Essentially Text carrying a proof that it can be successfully -- encoded into the given encoding. For example, AsText -- ASCII means the Text stored is pure ASCII. type AsText enc = Refined enc Text -- | Bytestring encoders for text validated for a given encoding. class Encode enc -- | Encode text to bytes. Internal function, use encode. encode' :: Encode enc => Text -> Bytes -- | Encode some validated text. encode :: forall enc. Encode enc => AsText enc -> Bytes -- | Encode some text to a bytestring, asserting that the resulting value -- is valid for the requested bytestring representation. -- -- This is intended to be used with visible type applications: -- --
--   >>> let Right t = refine @UTF8 (Text.pack "hi")
--   
--   >>> :t t
--   t :: AsText UTF8
--   
--   >>> let Right bs = encodeToRep @'C t
--   
--   >>> :t bs
--   bs :: Refined 'C Bytes
--   
encodeToRep :: forall rep enc. (Encode enc, Predicate rep Bytes) => AsText enc -> Either RefineException (Refined rep Bytes) class Decode enc -- | Decode a ByteString to Text with an explicit encoding. -- -- This is intended to be used with visible type applications. decode :: Decode enc => Bytes -> Either String (AsText enc) module Binrep.Util.Generic -- | Common type error string for when GHC is asked to derive a non-sum -- instance, but the data type in question turns out to be a sum data -- type. -- -- No need to add the data type name here, since GHC's context includes -- the surrounding instance declaration. type EUnexpectedSum = 'Text "Cannot derive non-sum binary representation instance for sum data type" -- | Common type error string for when GHC is asked to derive a sum -- instance, but the data type in question turns out to be a non-sum data -- type. -- -- No need to add the data type name here, since GHC's context includes -- the surrounding instance declaration. type EUnexpectedNonSum = 'Text "Refusing to derive sum binary representation instance for non-sum data type" module Binrep.Util.Prefix -- | Types which may be used as prefixes. -- -- Generally, these will be integer types. -- -- Note that this is separate to binary representation, so endianness is -- irrelevant. -- -- Note that we are also limited by the host architecture's Int -- type. We don't try to work around this, because most types are indexed -- with Ints, so I think other things will break before we do. class Prefix a where { type Max a :: Natural; } -- | used by put. guaranteed that it fits from refined. that is, lenToPfx -- <= Max. lenToPfx :: Prefix a => Int -> a -- | used by get. better not lie. pfxToLen :: Prefix a => a -> Int instance Binrep.Util.Prefix.Prefix a => Binrep.Util.Prefix.Prefix (Raehik.Compat.Data.Primitive.Types.Endian.ByteOrdered end a) instance Binrep.Util.Prefix.Prefix () instance Binrep.Util.Prefix.Prefix GHC.Word.Word8 instance Binrep.Util.Prefix.Prefix GHC.Word.Word16 instance Binrep.Util.Prefix.Prefix GHC.Word.Word32 instance Binrep.Util.Prefix.Prefix GHC.Word.Word64 module Raehik.Compat.FlatParse.Basic.Prim anyPrim :: forall a e st. Prim' a => ParserT st e a module Binrep.Get type Getter a = Parser E a class Get a -- | Parse from binary. get :: Get a => Getter a runGet :: Get a => ByteString -> Either E (a, ByteString) runGetter :: Getter a -> ByteString -> Either E (a, ByteString) -- | Structured parse error. data E E :: Int -> EMiddle -> E -- | Unhandled parse error. -- -- You get this if you don't change a flatparse fail to an error. -- -- Should not be set except by library code. EFail :: E data EBase -- | expected first, got second EExpectedByte :: Word8 -> Word8 -> EBase -- | expected first, got second EOverlong :: Int -> Int -> EBase -- | expected first, got second EExpected :: ByteString -> ByteString -> EBase -- | known fail EFailNamed :: String -> EBase -- | parse fail (where you parse a larger object, then a smaller one in it) EFailParse :: String -> ByteString -> Word8 -> EBase -- | ran out of input, needed precisely n bytes for this part (n -- > 0) -- -- Actually a Natural, but we use Int because that's what -- flatparse uses internally. ERanOut :: Int -> EBase -- | A generic context layer for a parse error of type e. -- -- Recursive: parse errors occurring in fields are wrapped up here. -- (Those errors may also have a generic context layer.) -- -- Making this explicitly recursive may seem strange, but it clarifies -- that this data type is to be seen as a layer over a top-level type. data EGeneric e -- | Parse error relating to sum types (constructors). EGenericSum :: EGenericSum e -> EGeneric e -- | Parse error in a constructor field. EGenericField :: String -> Maybe String -> Natural -> e -> EGeneric e data EGenericSum e -- | Parse error parsing prefix tag. EGenericSumTag :: e -> EGenericSum e -- | Unable to match a constructor to the parsed prefix tag. EGenericSumTagNoMatch :: [String] -> Text -> EGenericSum e eBase :: EBase -> Getter a getEBase :: Getter a -> EBase -> Getter a -- | Parse any Prim'. getPrim :: forall a. Prim' a => Getter a getGenericNonSum :: forall a. (Generic a, GTraverseNonSum Get (Rep a), GAssertNotVoid a, GAssertNotSum a) => Getter a getGenericSum :: forall pt a. (Generic a, GTraverseSum Get 'SumOnly (Rep a), Get pt, GAssertNotVoid a, GAssertSum a) => PfxTagCfg pt -> Getter a instance GHC.Generics.Generic Binrep.Get.EBase instance GHC.Show.Show Binrep.Get.EBase instance GHC.Classes.Eq Binrep.Get.EBase instance GHC.Generics.Generic (Binrep.Get.EGenericSum e) instance GHC.Show.Show e => GHC.Show.Show (Binrep.Get.EGenericSum e) instance GHC.Classes.Eq e => GHC.Classes.Eq (Binrep.Get.EGenericSum e) instance GHC.Generics.Generic (Binrep.Get.EGeneric e) instance GHC.Show.Show e => GHC.Show.Show (Binrep.Get.EGeneric e) instance GHC.Classes.Eq e => GHC.Classes.Eq (Binrep.Get.EGeneric e) instance GHC.Generics.Generic Binrep.Get.E instance GHC.Show.Show Binrep.Get.E instance GHC.Classes.Eq Binrep.Get.E instance GHC.Generics.Generic Binrep.Get.EMiddle instance GHC.Show.Show Binrep.Get.EMiddle instance GHC.Classes.Eq Binrep.Get.EMiddle instance Binrep.Get.Get GHC.Word.Word8 instance Binrep.Get.Get GHC.Int.Int8 instance Binrep.Get.Get (Raehik.Compat.Data.Primitive.Types.Endian.ByteOrdered end GHC.Word.Word8) instance Binrep.Get.Get (Raehik.Compat.Data.Primitive.Types.Endian.ByteOrdered end GHC.Int.Int8) instance (Raehik.Compat.Data.Primitive.Types.Prim' a, Raehik.Compat.Data.Primitive.Types.Endian.ByteSwap a) => Binrep.Get.Get (Raehik.Compat.Data.Primitive.Types.Endian.ByteOrdered 'GHC.ByteOrder.LittleEndian a) instance (Raehik.Compat.Data.Primitive.Types.Prim' a, Raehik.Compat.Data.Primitive.Types.Endian.ByteSwap a) => Binrep.Get.Get (Raehik.Compat.Data.Primitive.Types.Endian.ByteOrdered 'GHC.ByteOrder.BigEndian a) instance Generic.Data.Function.Traverse.Constructor.GenericTraverse Binrep.Get.Get instance Generic.Data.Function.Traverse.Sum.GenericTraverseSum Binrep.Get.Get instance (TypeError ...) => Binrep.Get.Get GHC.Base.Void instance (TypeError ...) => Binrep.Get.Get (Data.Either.Either a b) instance Binrep.Get.Get a => Binrep.Get.Get (Data.Functor.Identity.Identity a) instance Binrep.Get.Get () instance (Binrep.Get.Get l, Binrep.Get.Get r) => Binrep.Get.Get (l, r) instance Binrep.Get.Get a => Binrep.Get.Get [a] instance Binrep.Get.Get Data.ByteString.Internal.Type.ByteString instance Raehik.Compat.Data.Primitive.Types.Prim' a => Binrep.Get.Get (Binrep.Common.Via.Prim.ViaPrim a) module Raehik.Compat.FlatParse.Basic.WithLength -- | Run a parser, and return the result as well as the number of bytes it -- consumed. parseWithLength :: ParserT st e a -> ParserT st e (a, Int) -- | Handy typenat utils. module Util.TypeNats natVal'' :: forall n. KnownNat n => Natural natValInt :: forall n. KnownNat n => Int -- | The length of a type-level list. type family Length (a :: [k]) :: Natural module Binrep.CBLen class IsCBLen a where { type CBLen a :: Natural; } -- | Reify a type's constant byte length to the term level. cblen :: forall a. KnownNat (CBLen a) => Int cblen# :: forall a. KnownNat (CBLen a) => Int# cblenProxy# :: forall a. KnownNat (CBLen a) => Proxy# a -> Int# instance Binrep.CBLen.IsCBLen () instance (Binrep.CBLen.IsCBLen l, Binrep.CBLen.IsCBLen r) => Binrep.CBLen.IsCBLen (l, r) instance Binrep.CBLen.IsCBLen GHC.Word.Word8 instance Binrep.CBLen.IsCBLen GHC.Int.Int8 instance Binrep.CBLen.IsCBLen GHC.Word.Word16 instance Binrep.CBLen.IsCBLen GHC.Int.Int16 instance Binrep.CBLen.IsCBLen GHC.Word.Word32 instance Binrep.CBLen.IsCBLen GHC.Int.Int32 instance Binrep.CBLen.IsCBLen GHC.Word.Word64 instance Binrep.CBLen.IsCBLen GHC.Int.Int64 instance Binrep.CBLen.IsCBLen a => Binrep.CBLen.IsCBLen (Raehik.Compat.Data.Primitive.Types.Endian.ByteOrdered end a) module Binrep.Put.Struct type PutterC = Poke RealWorld -- | constant size putter class PutC a putC :: PutC a => a -> PutterC runPutC :: forall a. (PutC a, KnownNat (CBLen a)) => a -> ByteString -- | Serialize a term of the struct-like type a via its -- Generic instance. putGenericStruct :: forall a. (Generic a, GPoke PutC (Rep a)) => a -> PutterC instance Binrep.Put.Struct.PutC GHC.Word.Word8 instance Binrep.Put.Struct.PutC GHC.Int.Int8 instance Binrep.Put.Struct.PutC (Raehik.Compat.Data.Primitive.Types.Endian.ByteOrdered end GHC.Word.Word8) instance Binrep.Put.Struct.PutC (Raehik.Compat.Data.Primitive.Types.Endian.ByteOrdered end GHC.Int.Int8) instance (Raehik.Compat.Data.Primitive.Types.Prim' a, Raehik.Compat.Data.Primitive.Types.Endian.ByteSwap a) => Binrep.Put.Struct.PutC (Raehik.Compat.Data.Primitive.Types.Endian.ByteOrdered 'GHC.ByteOrder.LittleEndian a) instance (Raehik.Compat.Data.Primitive.Types.Prim' a, Raehik.Compat.Data.Primitive.Types.Endian.ByteSwap a) => Binrep.Put.Struct.PutC (Raehik.Compat.Data.Primitive.Types.Endian.ByteOrdered 'GHC.ByteOrder.BigEndian a) instance Bytezap.Struct.Generic.GPokeBase Binrep.Put.Struct.PutC instance Raehik.Compat.Data.Primitive.Types.Prim' a => Binrep.Put.Struct.PutC (Binrep.Common.Via.Prim.ViaPrim a) instance (TypeError ...) => Binrep.Put.Struct.PutC GHC.Base.Void instance (TypeError ...) => Binrep.Put.Struct.PutC (Data.Either.Either a b) instance Binrep.Put.Struct.PutC a => Binrep.Put.Struct.PutC (Data.Functor.Identity.Identity a) instance Binrep.Put.Struct.PutC Binrep.Put.Struct.PutterC instance Binrep.Put.Struct.PutC () instance (Binrep.Put.Struct.PutC l, GHC.TypeNats.KnownNat (Binrep.CBLen.CBLen l), Binrep.Put.Struct.PutC r) => Binrep.Put.Struct.PutC (l, r) -- | _Experimental._ Generically derive CBLen type family instances. -- -- A type having a valid CBLen instance usually indicates one of -- the following: -- -- -- -- The first two cases must be handled manually. The third case is where -- Haskell generics excel, and the one this module targets. -- -- You can (attempt to) derive a CBLen type family instance -- generically for a type via -- -- instance IsCBLen a where type CBLen a = CBLenGeneric w a -- -- As with deriving BLen generically, you must provide the type -- used to store the sum tag for sum types. -- -- Then try using it. Hopefully it works, or you get a useful type error. -- If not, sorry. I don't have much faith in this code. module Binrep.CBLen.Generic type CBLenGeneric w a = GCBLen w (Rep a) type family GCBLen w (f :: k -> Type) :: Natural type family GCBLenSum w (f :: k -> Type) type family MaybeEq a b -- | I don't know how to pattern match in types without writing type -- families. type family GCBLenCaseMaybe a data JustX a b data NothingX -- | Byte length as a simple pure function, no bells or whistles. -- -- Non-reallocating serializers like store, bytezap or ptr-poker request -- the expected total byte length when serializing. Thus, they need some -- way to measure byte length *before* serializing. This is that. -- -- It should be very efficient to calculate serialized byte length for -- most binrep-compatible Haskell types. If it isn't, consider whether -- the representation is appropriate for binrep. -- -- Note that you _may_ encode this inside the serializer type (whatever -- the Put class stores). I went back and forth on this a couple -- times. But some binrep code seems to make more sense when byte length -- is standalone. And I don't mind the extra explicitness. So it's here -- to stay :) module Binrep.BLen -- | Class for types with easily-calculated length in bytes. -- -- If it appears hard to calculate byte length for a given type (e.g. -- without first serializing it, then measuring serialized byte length), -- consider whether this type is a good fit for binrep. class BLen a -- | Calculate the serialized byte length of the given value. blen :: BLen a => a -> Int -- | Measure the byte length of a term of the non-sum type a via -- its Generic instance. blenGenericNonSum :: forall a. (Generic a, GFoldMapNonSum BLen (Rep a), GAssertNotVoid a, GAssertNotSum a) => a -> Int -- | Measure the byte length of a term of the sum type a via its -- Generic instance. -- -- You must provide a function to obtain the byte length for the prefix -- tag, via inspecting the reified constructor names. This is regrettably -- inefficient. Alas. Do write your own instance if you want better -- performance! blenGenericSum :: forall a. (Generic a, GFoldMapSum BLen 'SumOnly (Rep a), GAssertNotVoid a, GAssertSum a) => (String -> Int) -> a -> Int -- | DerivingVia wrapper for types which may derive a BLen instance -- through an existing IsCBLen instance (i.e. it is known at -- compile time) -- -- Examples of such types include machine integers, and explicitly-sized -- types (e.g. Binrep.Type.Sized). newtype ViaCBLen a ViaCBLen :: a -> ViaCBLen a [unViaCBLen] :: ViaCBLen a -> a -- | Reify a type's constant byte length to the term level. cblen :: forall a. KnownNat (CBLen a) => Int instance Binrep.BLen.BLen GHC.Word.Word8 instance Binrep.BLen.BLen GHC.Int.Int8 instance Binrep.BLen.BLen GHC.Word.Word16 instance Binrep.BLen.BLen GHC.Int.Int16 instance Binrep.BLen.BLen GHC.Word.Word32 instance Binrep.BLen.BLen GHC.Int.Int32 instance Binrep.BLen.BLen GHC.Word.Word64 instance Binrep.BLen.BLen GHC.Int.Int64 instance GHC.TypeNats.KnownNat (Binrep.CBLen.CBLen a) => Binrep.BLen.BLen (Raehik.Compat.Data.Primitive.Types.Endian.ByteOrdered end a) instance GHC.TypeNats.KnownNat (Binrep.CBLen.CBLen a) => Binrep.BLen.BLen (Binrep.BLen.ViaCBLen a) instance Generic.Data.Function.FoldMap.Constructor.GenericFoldMap Binrep.BLen.BLen instance (TypeError ...) => Binrep.BLen.BLen GHC.Base.Void instance (TypeError ...) => Binrep.BLen.BLen (Data.Either.Either a b) instance Binrep.BLen.BLen () instance (Binrep.BLen.BLen l, Binrep.BLen.BLen r) => Binrep.BLen.BLen (l, r) instance Binrep.BLen.BLen a => Binrep.BLen.BLen [a] instance Binrep.BLen.BLen Data.ByteString.Internal.Type.ByteString module Binrep.Put type Putter = Poke RealWorld class Put a put :: Put a => a -> Putter runPut :: (BLen a, Put a) => a -> ByteString -- | Serialize a term of the non-sum type a via its Generic -- instance. putGenericNonSum :: forall a. (Generic a, GFoldMapNonSum Put (Rep a), GAssertNotVoid a, GAssertNotSum a) => a -> Putter -- | Serialize a term of the sum type a via its Generic -- instance. -- -- You must provide a serializer for a's constructors. This is -- regrettably inefficient due to having to use Strings. Alas. Do -- write your own instance if you want better performance! putGenericSum :: forall a. (Generic a, GFoldMapSum Put 'SumOnly (Rep a), GAssertNotVoid a, GAssertSum a) => (String -> Putter) -> a -> Putter newtype ViaPutC a ViaPutC :: a -> ViaPutC a [unViaPutC] :: ViaPutC a -> a instance Binrep.Put.Put GHC.Word.Word8 instance Binrep.Put.Put GHC.Int.Int8 instance Binrep.Put.Put (Raehik.Compat.Data.Primitive.Types.Endian.ByteOrdered end GHC.Word.Word8) instance Binrep.Put.Put (Raehik.Compat.Data.Primitive.Types.Endian.ByteOrdered end GHC.Int.Int8) instance (Raehik.Compat.Data.Primitive.Types.Prim' a, Raehik.Compat.Data.Primitive.Types.Endian.ByteSwap a) => Binrep.Put.Put (Raehik.Compat.Data.Primitive.Types.Endian.ByteOrdered 'GHC.ByteOrder.LittleEndian a) instance (Raehik.Compat.Data.Primitive.Types.Prim' a, Raehik.Compat.Data.Primitive.Types.Endian.ByteSwap a) => Binrep.Put.Put (Raehik.Compat.Data.Primitive.Types.Endian.ByteOrdered 'GHC.ByteOrder.BigEndian a) instance (Binrep.Put.Struct.PutC a, GHC.TypeNats.KnownNat (Binrep.CBLen.CBLen a)) => Binrep.Put.Put (Binrep.Put.ViaPutC a) instance Generic.Data.Function.FoldMap.Constructor.GenericFoldMap Binrep.Put.Put instance Raehik.Compat.Data.Primitive.Types.Prim' a => Binrep.Put.Put (Binrep.Common.Via.Prim.ViaPrim a) instance (TypeError ...) => Binrep.Put.Put GHC.Base.Void instance (TypeError ...) => Binrep.Put.Put (Data.Either.Either a b) instance Binrep.Put.Put a => Binrep.Put.Put (Data.Functor.Identity.Identity a) instance Binrep.Put.Put Binrep.Put.Putter instance Binrep.Put.Put () instance (Binrep.Put.Put l, Binrep.Put.Put r) => Binrep.Put.Put (l, r) instance Binrep.Put.Put a => Binrep.Put.Put [a] instance Binrep.Put.Put Data.ByteString.Internal.Type.ByteString module Binrep -- | Thin types which reference the parser input when gotten via -- Get. -- -- flatparse's take family perform no copying-- instead, a -- bytestring is manually constructed with the finalizer from the input -- bytestring. I'm not sure I want this -- it sounds like a memory leak -- waiting to happen -- so I default to copying to a new bytestring. This -- type allows recovering the efficient no-copy behaviour. -- -- TODO doing this the other way around would be simpler, and fit -- flatparse better. All we need is such a class: -- --
--   class Copy a where copy :: a -> a
--   instance Copy B.ByteString where copy = B.copy
--   
-- -- But this just doesn't fly, because it would invert the behaviour. module Binrep.Type.Thin newtype Thin a Thin :: a -> Thin a [unThin] :: Thin a -> a instance Strongweak.Strengthen.Strengthen (Binrep.Type.Thin.Thin a) instance Strongweak.Weaken.Weaken (Binrep.Type.Thin.Thin a) instance Binrep.Put.Put a => Binrep.Put.Put (Binrep.Type.Thin.Thin a) instance Binrep.BLen.BLen a => Binrep.BLen.BLen (Binrep.Type.Thin.Thin a) instance GHC.IsList.IsList a => GHC.IsList.IsList (Binrep.Type.Thin.Thin a) instance Data.String.IsString a => Data.String.IsString (Binrep.Type.Thin.Thin a) instance Control.DeepSeq.NFData a => Control.DeepSeq.NFData (Binrep.Type.Thin.Thin a) instance GHC.Base.Monoid a => GHC.Base.Monoid (Binrep.Type.Thin.Thin a) instance GHC.Base.Semigroup a => GHC.Base.Semigroup (Binrep.Type.Thin.Thin a) instance GHC.Classes.Ord a => GHC.Classes.Ord (Binrep.Type.Thin.Thin a) instance GHC.Classes.Eq a => GHC.Classes.Eq (Binrep.Type.Thin.Thin a) instance GHC.Read.Read a => GHC.Read.Read (Binrep.Type.Thin.Thin a) instance GHC.Show.Show a => GHC.Show.Show (Binrep.Type.Thin.Thin a) instance Data.Data.Data a => Data.Data.Data (Binrep.Type.Thin.Thin a) instance GHC.Generics.Generic (Binrep.Type.Thin.Thin a) instance Binrep.Get.Get (Binrep.Type.Thin.Thin Data.ByteString.Internal.Type.ByteString) -- | Constant-size data. module Binrep.Type.Sized -- | Essentially runtime reflection of a BLen type to CBLen. data Size (n :: Natural) type Sized n = Refined (Size n) instance GHC.TypeNats.KnownNat n => Binrep.BLen.BLen (Binrep.Type.Sized.Sized n a) instance Binrep.CBLen.IsCBLen (Binrep.Type.Sized.Sized n a) instance Binrep.Put.Struct.PutC a => Binrep.Put.Struct.PutC (Binrep.Type.Sized.Sized n a) instance Binrep.Put.Put a => Binrep.Put.Put (Binrep.Type.Sized.Sized n a) instance (Binrep.Get.Get a, GHC.TypeNats.KnownNat n) => Binrep.Get.Get (Binrep.Type.Sized.Sized n a) instance (Binrep.BLen.BLen a, GHC.TypeNats.KnownNat n) => Refined.Predicate (Binrep.Type.Sized.Size n) a module Binrep.Type.Prefix.Size data SizePrefix (pfx :: Type) type SizePrefixed pfx = Refined (SizePrefix pfx) class GetSize a getSize :: GetSize a => Int -> Getter a instance Binrep.Type.Prefix.Size.GetSize Data.ByteString.Internal.Type.ByteString instance Binrep.Type.Prefix.Size.GetSize (Binrep.Type.Thin.Thin Data.ByteString.Internal.Type.ByteString) instance (Binrep.Util.Prefix.Prefix pfx, Binrep.Type.Prefix.Size.GetSize a, Binrep.Get.Get pfx) => Binrep.Get.Get (Binrep.Type.Prefix.Size.SizePrefixed pfx a) instance Binrep.CBLen.IsCBLen (Binrep.Type.Prefix.Size.SizePrefixed pfx a) instance (Binrep.Util.Prefix.Prefix pfx, Binrep.BLen.BLen a, Binrep.BLen.BLen pfx) => Binrep.BLen.BLen (Binrep.Type.Prefix.Size.SizePrefixed pfx a) instance (Binrep.Util.Prefix.Prefix pfx, Binrep.BLen.BLen a, Binrep.Put.Put pfx, Binrep.Put.Put a) => Binrep.Put.Put (Binrep.Type.Prefix.Size.SizePrefixed pfx a) instance (GHC.TypeNats.KnownNat (Binrep.Util.Prefix.Max pfx), Binrep.BLen.BLen a, Data.Typeable.Internal.Typeable pfx) => Refined.Predicate (Binrep.Type.Prefix.Size.SizePrefix pfx) a module Binrep.Type.Prefix.Count data CountPrefix (pfx :: Type) type CountPrefixed pfx = Refined1 (CountPrefix pfx) class GetCount f getCount :: (GetCount f, Get a) => Int -> Getter (f a) instance Binrep.Type.Prefix.Count.GetCount [] instance (Binrep.Util.Prefix.Prefix pfx, Binrep.Type.Prefix.Count.GetCount f, Binrep.Get.Get pfx, Binrep.Get.Get a) => Binrep.Get.Get (Binrep.Type.Prefix.Count.CountPrefixed pfx f a) instance forall k pfx (f :: k -> GHC.Types.Type) (a :: k). Binrep.CBLen.IsCBLen (Binrep.Type.Prefix.Count.CountPrefixed pfx f a) instance (Binrep.Util.Prefix.Prefix pfx, Data.Foldable.Foldable f, Binrep.BLen.BLen pfx, Binrep.BLen.BLen (f a)) => Binrep.BLen.BLen (Binrep.Type.Prefix.Count.CountPrefixed pfx f a) instance (Binrep.Util.Prefix.Prefix pfx, Data.Foldable.Foldable f, Binrep.Put.Put pfx, Binrep.Put.Put (f a)) => Binrep.Put.Put (Binrep.Type.Prefix.Count.CountPrefixed pfx f a) instance (GHC.TypeNats.KnownNat (Binrep.Util.Prefix.Max pfx), Data.Foldable.Foldable f, Data.Typeable.Internal.Typeable pfx) => Refined.Predicate1 (Binrep.Type.Prefix.Count.CountPrefix pfx) f instance (GHC.TypeNats.KnownNat (Binrep.Util.Prefix.Max pfx), Data.Foldable.Foldable f, Data.Typeable.Internal.Typeable pfx) => Refined.Predicate (Binrep.Type.Prefix.Count.CountPrefix pfx) (f a) -- | C-style null-terminated data. -- -- I mix string and bytestring terminology here, due to bad C influences. -- This module is specifically interested in bytestrings and their -- encoding. String/text encoding is handled in Text. module Binrep.Type.NullTerminated -- | Null-terminated data. Arbitrary length terminated with a null byte. -- Permits no null bytes inside the data. data NullTerminate type NullTerminated = Refined NullTerminate class NullCheck a hasNoNulls :: NullCheck a => a -> Bool instance Binrep.Type.NullTerminated.NullCheck a => Refined.Predicate Binrep.Type.NullTerminated.NullTerminate a instance Binrep.Type.NullTerminated.NullCheck Data.ByteString.Internal.Type.ByteString instance Binrep.BLen.BLen a => Binrep.BLen.BLen (Binrep.Type.NullTerminated.NullTerminated a) instance Binrep.Put.Put a => Binrep.Put.Put (Binrep.Type.NullTerminated.NullTerminated a) instance Binrep.Get.Get a => Binrep.Get.Get (Binrep.Type.NullTerminated.NullTerminated a) module Binrep.Generic -- | reallyUnsafeRefine : safe assuming Haskell constructor names are UTF-8 -- with no null bytes allowed -- -- Turn a constructor name into a prefix tag by adding a null terminator. -- -- Not common in binary data representations, but safe and useful for -- debugging. nullTermCstrPfxTag :: String -> NullTerminated ByteString -- | Data null-padded to a given length. module Binrep.Type.NullPadded data NullPad (n :: Natural) -- | A type which is to be null-padded to a given total length. -- -- Given some a :: NullPadded n a, it is guaranteed that -- --
--   blen a <= natValInt @n
--   
-- -- thus -- --
--   natValInt @n - blen a >= 0
--   
-- -- That is, the serialized stored data will not be longer than the total -- length. -- -- The binrep instances are careful not to construct bytestrings -- unnecessarily. type NullPadded n a = Refined (NullPad n) a instance GHC.TypeNats.KnownNat n => Binrep.BLen.BLen (Binrep.Type.NullPadded.NullPadded n a) instance Binrep.CBLen.IsCBLen (Binrep.Type.NullPadded.NullPadded n a) instance (Binrep.BLen.BLen a, GHC.TypeNats.KnownNat n, Binrep.Put.Struct.PutC a) => Binrep.Put.Struct.PutC (Binrep.Type.NullPadded.NullPadded n a) instance (Binrep.BLen.BLen a, GHC.TypeNats.KnownNat n, Binrep.Put.Put a) => Binrep.Put.Put (Binrep.Type.NullPadded.NullPadded n a) instance (Binrep.Get.Get a, GHC.TypeNats.KnownNat n) => Binrep.Get.Get (Binrep.Type.NullPadded.NullPadded n a) instance (Binrep.BLen.BLen a, GHC.TypeNats.KnownNat n) => Refined.Predicate (Binrep.Type.NullPadded.NullPad n) a -- | Magic numbers (also just magic): short constant bytestrings usually -- found at the top of a file, often used as an early sanity check. -- -- There are two main flavors of magics: -- -- -- -- For bytewise magics, use type-level Natural lists. For ASCII -- magics, use Symbols (type-level strings). -- -- Previously, I squashed these into a representationally-safe type. Now -- the check only occurs during reification. So you are able to define -- invalid magics now (bytes over 255, non-ASCII characters), and -- potentially use them, but you'll get a clear type error like "no -- instance for ByteVal 256" when attempting to reify. -- -- String magics are restricted to ASCII, and will type error during -- reification otherwise. If you really want UTF-8, please read -- UTF8. module Binrep.Type.Magic -- | A singleton data type representing a "magic number" via a phantom -- type. -- -- The phantom type variable unambiguously defines a constant bytestring. -- A handful of types are supported for using magics conveniently, e.g. -- for pure ASCII magics, you may use a Symbol type-level string. data Magic (a :: k) Magic :: Magic (a :: k) -- | The length of a type-level list. type family Length (a :: [k]) :: Natural type family SymbolUnicodeCodepoints (a :: Symbol) :: [Natural] type family CharListUnicodeCodepoints (a :: [Char]) :: [Natural] type family SymbolAsCharList (a :: Symbol) :: [Char] type family SymbolAsCharList' (a :: Maybe (Char, Symbol)) :: [Char] -- | Types which define a magic value. class Magical (a :: k) where { -- | How to turn the type into a list of bytes. type MagicBytes a :: [Natural]; } instance forall k (a :: k). GHC.Classes.Eq (Binrep.Type.Magic.Magic a) instance forall k (a :: k). GHC.Show.Show (Binrep.Type.Magic.Magic a) instance forall k (a :: k). (Data.Typeable.Internal.Typeable a, Data.Typeable.Internal.Typeable k) => Data.Data.Data (Binrep.Type.Magic.Magic a) instance forall k (a :: k). GHC.Generics.Generic (Binrep.Type.Magic.Magic a) instance forall k (a :: k). GHC.TypeNats.KnownNat (Binrep.Type.Magic.Length (Binrep.Type.Magic.MagicBytes a)) => Binrep.BLen.BLen (Binrep.Type.Magic.Magic a) instance forall (bs :: [GHC.Num.Natural.Natural]) k (a :: k). (bs GHC.Types.~ Binrep.Type.Magic.MagicBytes a, Bytezap.Struct.TypeLits.ReifyBytesW64 bs, GHC.TypeNats.KnownNat (Binrep.Type.Magic.Length bs)) => Binrep.Put.Put (Binrep.Type.Magic.Magic a) instance forall k (a :: k). Binrep.CBLen.IsCBLen (Binrep.Type.Magic.Magic a) instance forall k (bs :: [GHC.Num.Natural.Natural]) (a :: k). (bs GHC.Types.~ Binrep.Type.Magic.MagicBytes a, Bytezap.Struct.TypeLits.ReifyBytesW64 bs) => Binrep.Put.Struct.PutC (Binrep.Type.Magic.Magic a) instance forall k (bs :: [GHC.Num.Natural.Natural]) (a :: k). (bs GHC.Types.~ Binrep.Type.Magic.MagicBytes a, Bytezap.Struct.TypeLits.ReifyBytesW64 bs, GHC.TypeNats.KnownNat (Binrep.Type.Magic.Length bs)) => Binrep.Get.Get (Binrep.Type.Magic.Magic a) instance Binrep.Type.Magic.Magical ns instance Binrep.Type.Magic.Magical sym instance forall k (a :: k). Strongweak.Weaken.Weaken (Binrep.Type.Magic.Magic a) instance forall k (a :: k). Strongweak.Strengthen.Strengthen (Binrep.Type.Magic.Magic a) module Binrep.Test data DMagic DMagic :: Magic '[0xFF, 0, 1, 0, 1, 0, 1, 0xFF] -> DMagic [dMagic1_8b] :: DMagic -> Magic '[0xFF, 0, 1, 0, 1, 0, 1, 0xFF] instance GHC.Generics.Generic Binrep.Test.DMagic instance Binrep.CBLen.IsCBLen Binrep.Test.DMagic instance Binrep.Put.Struct.PutC Binrep.Test.DMagic