-- 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.8.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.Generically.NonSum newtype GenericallyNonSum a GenericallyNonSum :: a -> GenericallyNonSum a [unGenericallyNonSum] :: GenericallyNonSum a -> a 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 -- | Error data type definitions (shared between parsers). module Binrep.Get.Error -- | 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 EMiddle -- | Parse error with no further context. EBase :: EBase -> EMiddle -- | Somehow, we got two parse errors. -- -- I have a feeling that seeing this indicates a problem in your code. EAnd :: E -> EBase -> EMiddle -- | Parse error decorated with generic info. -- -- Should not be set except by library code. EGeneric :: String -> EGeneric E -> EMiddle 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 instance GHC.Generics.Generic Binrep.Get.Error.EBase instance GHC.Show.Show Binrep.Get.Error.EBase instance GHC.Classes.Eq Binrep.Get.Error.EBase instance GHC.Generics.Generic (Binrep.Get.Error.EGenericSum e) instance GHC.Show.Show e => GHC.Show.Show (Binrep.Get.Error.EGenericSum e) instance GHC.Classes.Eq e => GHC.Classes.Eq (Binrep.Get.Error.EGenericSum e) instance GHC.Generics.Generic (Binrep.Get.Error.EGeneric e) instance GHC.Show.Show e => GHC.Show.Show (Binrep.Get.Error.EGeneric e) instance GHC.Classes.Eq e => GHC.Classes.Eq (Binrep.Get.Error.EGeneric e) instance GHC.Generics.Generic Binrep.Get.Error.E instance GHC.Show.Show Binrep.Get.Error.E instance GHC.Classes.Eq Binrep.Get.Error.E instance GHC.Generics.Generic Binrep.Get.Error.EMiddle instance GHC.Show.Show Binrep.Get.Error.EMiddle instance GHC.Classes.Eq Binrep.Get.Error.EMiddle 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 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 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# -- | Defunctionalization symbol for CBLen. -- -- This is required for parameterized type-level generics e.g. bytezap's -- GPokeBase. data CBLenSym a -- | Using this necessitates UndecidableInstances. type CBLenGenericSum (w :: Type) a = GCBLen w (Rep a) -- | Using this necessitates UndecidableInstances. type CBLenGenericNonSum a = GTFoldMapCAddition CBLenSym (Rep a) type family GCBLen w (gf :: k -> Type) :: Natural type family GCBLenSum (gf :: 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 instance GHC.Generics.Generic a => Binrep.CBLen.IsCBLen (Binrep.Common.Via.Generically.NonSum.GenericallyNonSum a) instance forall k1 k (pr :: k1) (pl :: k) a. Binrep.CBLen.IsCBLen (Refined.Unsafe.Type.Refined pr (Refined.Unsafe.Type.Refined pl a)) => Binrep.CBLen.IsCBLen (Refined.Unsafe.Type.Refined (Refined.And pl pr) a) instance (Binrep.CBLen.IsCBLen l, Binrep.CBLen.IsCBLen r) => Binrep.CBLen.IsCBLen (l, r) instance Binrep.CBLen.IsCBLen () 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), GAssertNotVoid a, GAssertNotSum 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 (GHC.Generics.Generic a, Bytezap.Struct.Generic.GPoke Binrep.Put.Struct.PutC (GHC.Generics.Rep a), Generic.Type.Assert.GAssertNotVoid a, Generic.Type.Assert.GAssertNotSum a) => Binrep.Put.Struct.PutC (GHC.Generics.Generically a) instance (GHC.Generics.Generic a, Bytezap.Struct.Generic.GPoke Binrep.Put.Struct.PutC (GHC.Generics.Rep a), Generic.Type.Assert.GAssertNotVoid a, Generic.Type.Assert.GAssertNotSum a) => Binrep.Put.Struct.PutC (Binrep.Common.Via.Generically.NonSum.GenericallyNonSum a) instance forall k1 k (pr :: k1) (pl :: k) a. Binrep.Put.Struct.PutC (Refined.Unsafe.Type.Refined pr (Refined.Unsafe.Type.Refined pl a)) => Binrep.Put.Struct.PutC (Refined.Unsafe.Type.Refined (Refined.And pl pr) a) 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) module Binrep.Get.Struct type GetterC = Parser E -- | constant size parser class GetC a getC :: GetC a => GetterC a runGetCBs :: forall a. (GetC a, KnownNat (CBLen a)) => ByteString -> Either E a -- | doesn't check len unsafeRunGetC' :: forall a buf. GetC a => (forall e. buf -> Parser e a -> Result e a) -> buf -> Either E a -- | doesn't check len unsafeRunGetCPtr :: forall a. GetC a => Ptr Word8 -> Either E a -- | Serialize a term of the struct-like type a via its -- Generic instance. getGenericStruct :: forall a. (Generic a, GParse GetC (Rep a), GAssertNotVoid a, GAssertNotSum a) => GetterC a eCBase :: EBase -> GetterC a getECBase :: GetterC a -> EBase -> GetterC a instance Binrep.Get.Struct.GetC GHC.Word.Word8 instance Binrep.Get.Struct.GetC GHC.Int.Int8 instance Binrep.Get.Struct.GetC (Raehik.Compat.Data.Primitive.Types.Endian.ByteOrdered end GHC.Word.Word8) instance Binrep.Get.Struct.GetC (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.Struct.GetC (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.Struct.GetC (Raehik.Compat.Data.Primitive.Types.Endian.ByteOrdered 'GHC.ByteOrder.BigEndian a) instance Bytezap.Parser.Struct.Generic.GParseBase Binrep.Get.Struct.GetC instance (GHC.Generics.Generic a, Bytezap.Parser.Struct.Generic.GParse Binrep.Get.Struct.GetC (GHC.Generics.Rep a), Generic.Type.Assert.GAssertNotVoid a, Generic.Type.Assert.GAssertNotSum a) => Binrep.Get.Struct.GetC (GHC.Generics.Generically a) instance (GHC.Generics.Generic a, Bytezap.Parser.Struct.Generic.GParse Binrep.Get.Struct.GetC (GHC.Generics.Rep a), Generic.Type.Assert.GAssertNotVoid a, Generic.Type.Assert.GAssertNotSum a) => Binrep.Get.Struct.GetC (Binrep.Common.Via.Generically.NonSum.GenericallyNonSum a) instance forall k1 k (pr :: k1) (pl :: k) a. Binrep.Get.Struct.GetC (Refined.Unsafe.Type.Refined pr (Refined.Unsafe.Type.Refined pl a)) => Binrep.Get.Struct.GetC (Refined.Unsafe.Type.Refined (Refined.And pl pr) a) instance Binrep.Get.Struct.GetC () instance Raehik.Compat.Data.Primitive.Types.Prim' a => Binrep.Get.Struct.GetC (Binrep.Common.Via.Prim.ViaPrim a) instance Binrep.Get.Struct.GetC a => Binrep.Get.Struct.GetC (Data.Functor.Identity.Identity a) module Binrep.Get class Get a -- | Parse from binary. get :: Get a => Getter a type Getter a = Parser E a newtype ViaGetC a ViaGetC :: a -> ViaGetC a [unViaGetC] :: ViaGetC a -> a runGet :: Get a => ByteString -> Either E (a, ByteString) runGetter :: Getter a -> ByteString -> Either E (a, ByteString) -- | Parse. On parse error, coat it in a generic context layer. getWrapGeneric :: Get a => String -> (E -> EGeneric E) -> 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 (Rep a), Get pt, GAssertNotVoid a, GAssertSum a) => PfxTagCfg pt -> Getter a eBase :: EBase -> Getter a getEBase :: Getter a -> EBase -> Getter a -- | Convert a bytezap struct parser to a flatparse parser. bzToFp :: forall a e st. KnownNat (CBLen a) => ParserT st e a -> ParserT st e a fpToBz :: ParserT st e a -> Int# -> (a -> Int# -> ParserT st e r) -> ParserT st e r getWrapGeneric' :: Getter a -> String -> (E -> EGeneric E) -> Getter a -- | Parse any Prim'. getPrim :: forall a. Prim' a => Getter a 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 (Binrep.Get.Struct.GetC a, GHC.TypeNats.KnownNat (Binrep.CBLen.CBLen a)) => Binrep.Get.Get (Binrep.Get.ViaGetC a) instance Generic.Data.Function.Traverse.Constructor.GenericTraverse Binrep.Get.Get instance Generic.Data.Function.Traverse.Sum.GenericTraverseSum Binrep.Get.Get instance (GHC.Generics.Generic a, Generic.Data.Function.Traverse.NonSum.GTraverseNonSum Binrep.Get.Get (GHC.Generics.Rep a), Generic.Type.Assert.GAssertNotVoid a, Generic.Type.Assert.GAssertNotSum a) => Binrep.Get.Get (Binrep.Common.Via.Generically.NonSum.GenericallyNonSum a) 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) instance forall k1 k (pr :: k1) (pl :: k) a. Binrep.Get.Get (Refined.Unsafe.Type.Refined pr (Refined.Unsafe.Type.Refined pl a)) => Binrep.Get.Get (Refined.Unsafe.Type.Refined (Refined.And pl pr) a) -- | 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 (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 forall k1 k (pr :: k1) (pl :: k) a. Binrep.BLen.BLen (Refined.Unsafe.Type.Refined pr (Refined.Unsafe.Type.Refined pl a)) => Binrep.BLen.BLen (Refined.Unsafe.Type.Refined (Refined.And pl pr) a) 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 (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 (GHC.Generics.Generic a, Generic.Data.Function.FoldMap.NonSum.GFoldMapNonSum Binrep.Put.Put (GHC.Generics.Rep a), Generic.Type.Assert.GAssertNotVoid a, Generic.Type.Assert.GAssertNotSum a) => Binrep.Put.Put (Binrep.Common.Via.Generically.NonSum.GenericallyNonSum a) 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 instance forall k1 k (pr :: k1) (pl :: k) a. Binrep.Put.Put (Refined.Unsafe.Type.Refined pr (Refined.Unsafe.Type.Refined pl a)) => Binrep.Put.Put (Refined.Unsafe.Type.Refined (Refined.And pl pr) a) -- | Top-level binrep module, exporting all classes, generics & -- runners. -- -- binrep helps you precisely model binary schemas by combining simple -- "building blocks" (e.g. NullTerminated a) in regular -- Haskell types. You can then receive high-performance serializers and -- parsers for free via generics. -- -- binrep is not a general-purpose parsing/serializing library. -- For that, see -- --
-- 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. 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.Put 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 (GHC.TypeNats.KnownNat n, Binrep.Get.Get a) => Binrep.Get.Struct.GetC (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 -- | Null-terminated, then null-padded data. -- -- This is defined using the composition of existing NullTerminate -- and NullPad predicates, plus the re-associating binrep -- instances for the And predicate combinator. It kind of just -- magically works. module Binrep.Type.Derived.NullTermPadded -- | Predicate for null-terminated, then null-padded data. type NullTermPad n = NullTerminate `And` NullPad n -- | Null-terminated data, which is then null-padded to the given length. -- -- Instantiate with ByteString for a null-padded C string. type NullTermPadded n = Refined (NullTermPad n) -- | 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: -- --