-- 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.5.0 module Binrep.CBLen class IsCBLen a where { type CBLen a :: Natural; } 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 -- | Pretty bytestrings via printing each byte as two hex digits. -- -- This is primarily for aeson and when we want better showing of -- non-textual bytestrings. It's not really binrep-related, but it needs -- _somewhere_ to go and my projects that need it usually also touch -- binrep, so here it is. -- -- Sadly, we can't use it to make aeson print integers as hex literals. -- It only deals in Scientifics, and if we tried printing them as -- strings, it would quote them. I need a YAML-like with better -- literals... module Binrep.Extra.HexByteString newtype Hex a Hex :: a -> Hex a [unHex] :: Hex a -> a type HexByteString = Hex ByteString -- | A hex bytestring looks like this: 00 01 89 8a FEff. You can -- mix and match capitalization and spacing, but I prefer to space each -- byte, full caps. parseHexByteString :: (MonadParsec e s m, Token s ~ Char) => ([Word8] -> a) -> m a -- | Parse a byte formatted as two hex digits e.g. EF. You _must_ provide -- both nibbles e.g. 0F, not F. They cannot be spaced -- e.g. E F is invalid. -- -- Returns a value 0-255, so can fit in any Num type that can store that. parseHexByte :: (MonadParsec e s m, Token s ~ Char, Num a) => m a -- | Pretty print to default format 00 12 AB FF: space between -- each byte, all caps. -- -- This format I consider most human readable. I prefer caps to draw -- attention to this being data instead of text (you don't see that many -- capital letters packed together in prose). prettyHexByteString :: (a -> [Word8]) -> a -> Text prettyHexByte :: (Char -> Char) -> Word8 -> (Char, Char) -- | Pretty print to "compact" format 0012abff (often output by -- hashers). prettyHexByteStringCompact :: (a -> [Word8]) -> a -> Text instance GHC.Classes.Eq a => GHC.Classes.Eq (Binrep.Extra.HexByteString.Hex a) instance Data.Data.Data a => Data.Data.Data (Binrep.Extra.HexByteString.Hex a) instance GHC.Generics.Generic (Binrep.Extra.HexByteString.Hex a) instance GHC.Show.Show (Binrep.Extra.HexByteString.Hex Data.ByteString.Internal.Type.ByteString) instance Data.Aeson.Types.FromJSON.FromJSON (Binrep.Extra.HexByteString.Hex Data.ByteString.Internal.Type.ByteString) instance Data.Aeson.Types.ToJSON.ToJSON (Binrep.Extra.HexByteString.Hex Data.ByteString.Internal.Type.ByteString) instance GHC.Show.Show (Binrep.Extra.HexByteString.Hex Data.ByteString.Short.Internal.ShortByteString) instance Data.Aeson.Types.FromJSON.FromJSON (Binrep.Extra.HexByteString.Hex Data.ByteString.Short.Internal.ShortByteString) instance Data.Aeson.Types.ToJSON.ToJSON (Binrep.Extra.HexByteString.Hex Data.ByteString.Short.Internal.ShortByteString) module Binrep.Put.Mason type Builder = BuilderFor StrictByteStringBackend class Put a -- | Serialize to binary. put :: Put a => a -> Builder -- | Run the serializer. runPut :: Put a => a -> ByteString runBuilder :: Builder -> ByteString -- | Serialize a term of the non-sum type a via its Generic -- instance. putGenericNonSum :: forall {cd} {f} {asserts} a. (Generic a, Rep a ~ D1 cd f, GFoldMapNonSum Builder f, asserts ~ '[ 'NoEmpty, 'NoSum], ApplyGCAsserts asserts f) => a -> Builder -- | 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 {cd} {f} {asserts} a. (Generic a, Rep a ~ D1 cd f, GFoldMapSum 'SumOnly Builder f, asserts ~ '[ 'NoEmpty, 'NeedSum], ApplyGCAsserts asserts f) => (String -> Builder) -> a -> Builder -- | Put with inlined checks via an environment. class PutWith r a -- | Attempt to serialize to binary with the given environment. putWith :: PutWith r a => r -> a -> Either String Builder -- | Attempt to serialize to binary with the given environment. putWith :: (PutWith r a, Put a) => r -> a -> Either String Builder -- | Helper for wrapping a BinRep into a BinRepWith (for -- encoding). putWithout :: Put a => a -> Either String Builder -- | Run the serializer with the given environment. runPutWith :: PutWith r a => r -> a -> Either String ByteString instance Binrep.Put.Mason.Put a => Binrep.Put.Mason.PutWith r [a] instance Generic.Data.Function.FoldMap.Constructor.GenericFoldMap Binrep.Put.Mason.Builder instance Binrep.Put.Mason.Put Data.Void.Void instance Binrep.Put.Mason.Put a => Binrep.Put.Mason.Put [a] instance (Binrep.Put.Mason.Put a, Binrep.Put.Mason.Put b) => Binrep.Put.Mason.Put (a, b) instance Binrep.Put.Mason.Put Data.ByteString.Internal.Type.ByteString instance Binrep.Put.Mason.Put GHC.Word.Word8 instance Binrep.Put.Mason.Put GHC.Int.Int8 module Binrep.Type.Common -- | Byte order. data Endianness -- | little endian, MSB last. e.g. most processor architectures LE :: Endianness -- | big endian, MSB first. e.g. most network protocols BE :: Endianness instance GHC.Classes.Eq Binrep.Type.Common.Endianness instance GHC.Show.Show Binrep.Type.Common.Endianness instance Data.Data.Data Binrep.Type.Common.Endianness instance GHC.Generics.Generic Binrep.Type.Common.Endianness 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.Utf32 data Utf32 (end :: Endianness) instance Binrep.Type.Text.Internal.Encode (Binrep.Type.Text.Encoding.Utf32.Utf32 'Binrep.Type.Common.BE) instance Binrep.Type.Text.Internal.Encode (Binrep.Type.Text.Encoding.Utf32.Utf32 'Binrep.Type.Common.LE) instance Binrep.Type.Text.Internal.Decode (Binrep.Type.Text.Encoding.Utf32.Utf32 'Binrep.Type.Common.BE) instance Binrep.Type.Text.Internal.Decode (Binrep.Type.Text.Encoding.Utf32.Utf32 'Binrep.Type.Common.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 :: Endianness) instance Binrep.Type.Text.Internal.Encode (Binrep.Type.Text.Encoding.Utf16.Utf16 'Binrep.Type.Common.BE) instance Binrep.Type.Text.Internal.Encode (Binrep.Type.Text.Encoding.Utf16.Utf16 'Binrep.Type.Common.LE) instance Binrep.Type.Text.Internal.Decode (Binrep.Type.Text.Encoding.Utf16.Utf16 'Binrep.Type.Common.BE) instance Binrep.Type.Text.Internal.Decode (Binrep.Type.Text.Encoding.Utf16.Utf16 'Binrep.Type.Common.LE) instance Data.Typeable.Internal.Typeable end => Refined.Predicate (Binrep.Type.Text.Encoding.Utf16.Utf16 end) 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.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 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.Class -- | 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" -- | _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 BLen 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 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 Bytezap -- | TODO inner poke type -- -- TODO can I change this to -- --
--   Ptr Word8 -> IO (Ptr Word8)
--   
-- -- without any performance loss? it's the same underneath newtypes and -- datas. Ptr is a data rather than a newtype, but IO is just a -- newtype. -- -- I originally did this to beat ptr-poker, but idk. Now doubtful. type Poke# = Addr# -> State# RealWorld -> (# State# RealWorld, Addr# #) -- | Unboxed poke operation. -- -- A newtype allows us a monoidal interface. newtype Poke Poke :: Poke# -> Poke -- | Write at an offset from an address and return the next offset. -- -- The returned offset must be after the argument offset. -- -- TODO I use that output order because it matches IO. Probs doesn't -- matter. [unPoke] :: Poke -> Poke# -- | Construct a Poke. poke :: Poke# -> Poke -- | Allocate a buffer of the given size and run a Poke over it. -- -- The Poke must fill the buffer exactly. If it goes under, you -- should get some random garbage at the end. If it goes over, your -- computer will probably explode. runPoke :: Int -> Poke -> ByteString wrapPoke :: Poke -> Ptr Word8 -> IO () -- | Instructions on how to perform a sized write. -- -- The Poke in writePoke must write the _exact_ number of -- bytes specified in writeSize. Otherwise, your computer -- explodes. data Write Write :: {-# UNPACK #-} !Int -> !Poke -> Write [writeSize] :: Write -> {-# UNPACK #-} !Int [writePoke] :: Write -> !Poke -- | Construct a Write. write :: Int -> Poke# -> Write runWrite :: Write -> ByteString instance GHC.Base.Semigroup Bytezap.Write instance GHC.Base.Monoid Bytezap.Write instance GHC.Show.Show Bytezap.Write instance GHC.Base.Semigroup Bytezap.Poke instance GHC.Base.Monoid Bytezap.Poke -- | ByteStrings and primitive byte arrays. module Bytezap.Bytes byteString :: ByteString -> Write pokeForeignPtr :: ForeignPtr Word8 -> Int -> Poke memcpyForeignPtr :: Ptr Word8 -> ForeignPtr Word8 -> Int -> IO () pokeByteArray# :: ByteArray# -> Int# -> Int# -> Poke pokeByteReplicate :: Int -> Word8 -> Poke module Binrep.Get.Flatparse 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 getGenericNonSum :: forall {cd} {f} {asserts} a. (Generic a, Rep a ~ D1 cd f, GTraverseNonSum cd (Parser E) f, asserts ~ '[ 'NoEmpty, 'NoSum], ApplyGCAsserts asserts f) => Getter a getGenericSum :: forall {cd} {f} {asserts} pt a. (Generic a, Rep a ~ D1 cd f, GTraverseSum 'SumOnly cd (Parser E) f, Get pt, asserts ~ '[ 'NoEmpty, 'NeedSum], ApplyGCAsserts asserts f) => PfxTagCfg pt -> Getter a instance GHC.Generics.Generic Binrep.Get.Flatparse.EBase instance GHC.Show.Show Binrep.Get.Flatparse.EBase instance GHC.Classes.Eq Binrep.Get.Flatparse.EBase instance GHC.Generics.Generic (Binrep.Get.Flatparse.EGenericSum e) instance GHC.Show.Show e => GHC.Show.Show (Binrep.Get.Flatparse.EGenericSum e) instance GHC.Classes.Eq e => GHC.Classes.Eq (Binrep.Get.Flatparse.EGenericSum e) instance GHC.Generics.Generic (Binrep.Get.Flatparse.EGeneric e) instance GHC.Show.Show e => GHC.Show.Show (Binrep.Get.Flatparse.EGeneric e) instance GHC.Classes.Eq e => GHC.Classes.Eq (Binrep.Get.Flatparse.EGeneric e) instance GHC.Generics.Generic Binrep.Get.Flatparse.E instance GHC.Show.Show Binrep.Get.Flatparse.E instance GHC.Classes.Eq Binrep.Get.Flatparse.E instance GHC.Generics.Generic Binrep.Get.Flatparse.EMiddle instance GHC.Show.Show Binrep.Get.Flatparse.EMiddle instance GHC.Classes.Eq Binrep.Get.Flatparse.EMiddle instance Generic.Data.Function.Traverse.Constructor.GenericTraverse (FlatParse.Basic.Parser.Parser Binrep.Get.Flatparse.E) instance (TypeError ...) => Binrep.Get.Flatparse.Get Data.Void.Void instance (TypeError ...) => Binrep.Get.Flatparse.Get (Data.Either.Either a b) instance Binrep.Get.Flatparse.Get Bytezap.Write instance Binrep.Get.Flatparse.Get () instance (Binrep.Get.Flatparse.Get l, Binrep.Get.Flatparse.Get r) => Binrep.Get.Flatparse.Get (l, r) instance Binrep.Get.Flatparse.Get a => Binrep.Get.Flatparse.Get [a] instance Binrep.Get.Flatparse.Get Data.ByteString.Internal.Type.ByteString instance Binrep.Get.Flatparse.Get GHC.Word.Word8 instance Binrep.Get.Flatparse.Get GHC.Int.Int8 instance Generic.Data.Function.Traverse.Sum.GenericTraverseSum (FlatParse.Basic.Parser.Parser Binrep.Get.Flatparse.E) -- | Sized machine integers. module Bytezap.Int w8 :: Word8 -> Write w16 :: Word16 -> Write w32 :: Word32 -> Write w64 :: Word64 -> Write w16le :: Word16 -> Write w16be :: Word16 -> Write w32le :: Word32 -> Write w32be :: Word32 -> Write w64le :: Word64 -> Write w64be :: Word64 -> Write i8 :: Int8 -> Write i16 :: Int16 -> Write i32 :: Int32 -> Write i64 :: Int64 -> Write byteSwapI16 :: Int16 -> Int16 byteSwapI32 :: Int32 -> Int32 byteSwapI64 :: Int64 -> Int64 i16le :: Int16 -> Write i16be :: Int16 -> Write i32le :: Int32 -> Write i32be :: Int32 -> Write i64le :: Int64 -> Write i64be :: Int64 -> Write int# :: Int# -> Write module Bytezap.Class class Put a put :: Put a => a -> Write instance Bytezap.Class.Put Bytezap.Write instance Bytezap.Class.Put Data.ByteString.Internal.Type.ByteString instance Bytezap.Class.Put GHC.Word.Word8 instance Bytezap.Class.Put GHC.Word.Word16 instance Bytezap.Class.Put GHC.Word.Word32 instance Bytezap.Class.Put GHC.Word.Word64 instance Bytezap.Class.Put GHC.Int.Int8 instance Bytezap.Class.Put GHC.Int.Int16 instance Bytezap.Class.Put GHC.Int.Int32 instance Bytezap.Class.Put GHC.Int.Int64 module Bytezap.Poke.Bytes byteString :: ByteString -> Poke pokeForeignPtr :: ForeignPtr Word8 -> Int -> Poke memcpyForeignPtr :: Ptr Word8 -> ForeignPtr Word8 -> Int -> IO () pokeByteArray# :: ByteArray# -> Int# -> Int# -> Poke module Bytezap.Poke.Int w8 :: Word8 -> Poke w16 :: Word16 -> Poke w32 :: Word32 -> Poke w64 :: Word64 -> Poke w16le :: Word16 -> Poke w16be :: Word16 -> Poke w32le :: Word32 -> Poke w32be :: Word32 -> Poke w64le :: Word64 -> Poke w64be :: Word64 -> Poke i8 :: Int8 -> Poke i16 :: Int16 -> Poke i32 :: Int32 -> Poke i64 :: Int64 -> Poke byteSwapI16 :: Int16 -> Int16 byteSwapI32 :: Int32 -> Int32 byteSwapI64 :: Int64 -> Int64 i16le :: Int16 -> Poke i16be :: Int16 -> Poke i32le :: Int32 -> Poke i32be :: Int32 -> Poke i64le :: Int64 -> Poke i64be :: Int64 -> Poke int# :: Int# -> Poke -- | Safe, if silly, byte representation for use at the type level. -- -- Word8 is a special type that GHC doesn't (and I think can't) -- promote to the type level. We only have Naturals, which are -- unbounded. So we define a safe, promotable representation, to allow us -- to prove well-sizedness at compile time. Then we provide a bunch of -- type families and reifying typeclasses to enable going between -- "similar" kinds (Natural) and types (Word8, -- ByteString) respectively. -- -- Type-level functionality is stored in TypeLevel because the -- definitions are even sillier than the ones here. -- -- Do not use this on the term level. That would be _extremely_ silly. module Binrep.Type.Byte -- | Efficiently reify a list of type-level Natural bytes to to a -- bytestring builder. -- -- Attempting to reify a Natural larger than 255 results in a type -- error. -- -- This is about as far as one should go for pointless performance here, -- I should think. class ReifyBytes (ns :: [Natural]) reifyBytes :: ReifyBytes ns => Poke class ByteVal (n :: Natural) byteVal :: ByteVal n => Word8 instance (Binrep.Type.Byte.ByteVal n, Binrep.Type.Byte.ReifyBytes ns) => Binrep.Type.Byte.ReifyBytes (n : ns) instance Binrep.Type.Byte.ByteVal 0 instance Binrep.Type.Byte.ByteVal 1 instance Binrep.Type.Byte.ByteVal 2 instance Binrep.Type.Byte.ByteVal 3 instance Binrep.Type.Byte.ByteVal 4 instance Binrep.Type.Byte.ByteVal 5 instance Binrep.Type.Byte.ByteVal 6 instance Binrep.Type.Byte.ByteVal 7 instance Binrep.Type.Byte.ByteVal 8 instance Binrep.Type.Byte.ByteVal 9 instance Binrep.Type.Byte.ByteVal 10 instance Binrep.Type.Byte.ByteVal 11 instance Binrep.Type.Byte.ByteVal 12 instance Binrep.Type.Byte.ByteVal 13 instance Binrep.Type.Byte.ByteVal 14 instance Binrep.Type.Byte.ByteVal 15 instance Binrep.Type.Byte.ByteVal 16 instance Binrep.Type.Byte.ByteVal 17 instance Binrep.Type.Byte.ByteVal 18 instance Binrep.Type.Byte.ByteVal 19 instance Binrep.Type.Byte.ByteVal 20 instance Binrep.Type.Byte.ByteVal 21 instance Binrep.Type.Byte.ByteVal 22 instance Binrep.Type.Byte.ByteVal 23 instance Binrep.Type.Byte.ByteVal 24 instance Binrep.Type.Byte.ByteVal 25 instance Binrep.Type.Byte.ByteVal 26 instance Binrep.Type.Byte.ByteVal 27 instance Binrep.Type.Byte.ByteVal 28 instance Binrep.Type.Byte.ByteVal 29 instance Binrep.Type.Byte.ByteVal 30 instance Binrep.Type.Byte.ByteVal 31 instance Binrep.Type.Byte.ByteVal 32 instance Binrep.Type.Byte.ByteVal 33 instance Binrep.Type.Byte.ByteVal 34 instance Binrep.Type.Byte.ByteVal 35 instance Binrep.Type.Byte.ByteVal 36 instance Binrep.Type.Byte.ByteVal 37 instance Binrep.Type.Byte.ByteVal 38 instance Binrep.Type.Byte.ByteVal 39 instance Binrep.Type.Byte.ByteVal 40 instance Binrep.Type.Byte.ByteVal 41 instance Binrep.Type.Byte.ByteVal 42 instance Binrep.Type.Byte.ByteVal 43 instance Binrep.Type.Byte.ByteVal 44 instance Binrep.Type.Byte.ByteVal 45 instance Binrep.Type.Byte.ByteVal 46 instance Binrep.Type.Byte.ByteVal 47 instance Binrep.Type.Byte.ByteVal 48 instance Binrep.Type.Byte.ByteVal 49 instance Binrep.Type.Byte.ByteVal 50 instance Binrep.Type.Byte.ByteVal 51 instance Binrep.Type.Byte.ByteVal 52 instance Binrep.Type.Byte.ByteVal 53 instance Binrep.Type.Byte.ByteVal 54 instance Binrep.Type.Byte.ByteVal 55 instance Binrep.Type.Byte.ByteVal 56 instance Binrep.Type.Byte.ByteVal 57 instance Binrep.Type.Byte.ByteVal 58 instance Binrep.Type.Byte.ByteVal 59 instance Binrep.Type.Byte.ByteVal 60 instance Binrep.Type.Byte.ByteVal 61 instance Binrep.Type.Byte.ByteVal 62 instance Binrep.Type.Byte.ByteVal 63 instance Binrep.Type.Byte.ByteVal 64 instance Binrep.Type.Byte.ByteVal 65 instance Binrep.Type.Byte.ByteVal 66 instance Binrep.Type.Byte.ByteVal 67 instance Binrep.Type.Byte.ByteVal 68 instance Binrep.Type.Byte.ByteVal 69 instance Binrep.Type.Byte.ByteVal 70 instance Binrep.Type.Byte.ByteVal 71 instance Binrep.Type.Byte.ByteVal 72 instance Binrep.Type.Byte.ByteVal 73 instance Binrep.Type.Byte.ByteVal 74 instance Binrep.Type.Byte.ByteVal 75 instance Binrep.Type.Byte.ByteVal 76 instance Binrep.Type.Byte.ByteVal 77 instance Binrep.Type.Byte.ByteVal 78 instance Binrep.Type.Byte.ByteVal 79 instance Binrep.Type.Byte.ByteVal 80 instance Binrep.Type.Byte.ByteVal 81 instance Binrep.Type.Byte.ByteVal 82 instance Binrep.Type.Byte.ByteVal 83 instance Binrep.Type.Byte.ByteVal 84 instance Binrep.Type.Byte.ByteVal 85 instance Binrep.Type.Byte.ByteVal 86 instance Binrep.Type.Byte.ByteVal 87 instance Binrep.Type.Byte.ByteVal 88 instance Binrep.Type.Byte.ByteVal 89 instance Binrep.Type.Byte.ByteVal 90 instance Binrep.Type.Byte.ByteVal 91 instance Binrep.Type.Byte.ByteVal 92 instance Binrep.Type.Byte.ByteVal 93 instance Binrep.Type.Byte.ByteVal 94 instance Binrep.Type.Byte.ByteVal 95 instance Binrep.Type.Byte.ByteVal 96 instance Binrep.Type.Byte.ByteVal 97 instance Binrep.Type.Byte.ByteVal 98 instance Binrep.Type.Byte.ByteVal 99 instance Binrep.Type.Byte.ByteVal 100 instance Binrep.Type.Byte.ByteVal 101 instance Binrep.Type.Byte.ByteVal 102 instance Binrep.Type.Byte.ByteVal 103 instance Binrep.Type.Byte.ByteVal 104 instance Binrep.Type.Byte.ByteVal 105 instance Binrep.Type.Byte.ByteVal 106 instance Binrep.Type.Byte.ByteVal 107 instance Binrep.Type.Byte.ByteVal 108 instance Binrep.Type.Byte.ByteVal 109 instance Binrep.Type.Byte.ByteVal 110 instance Binrep.Type.Byte.ByteVal 111 instance Binrep.Type.Byte.ByteVal 112 instance Binrep.Type.Byte.ByteVal 113 instance Binrep.Type.Byte.ByteVal 114 instance Binrep.Type.Byte.ByteVal 115 instance Binrep.Type.Byte.ByteVal 116 instance Binrep.Type.Byte.ByteVal 117 instance Binrep.Type.Byte.ByteVal 118 instance Binrep.Type.Byte.ByteVal 119 instance Binrep.Type.Byte.ByteVal 120 instance Binrep.Type.Byte.ByteVal 121 instance Binrep.Type.Byte.ByteVal 122 instance Binrep.Type.Byte.ByteVal 123 instance Binrep.Type.Byte.ByteVal 124 instance Binrep.Type.Byte.ByteVal 125 instance Binrep.Type.Byte.ByteVal 126 instance Binrep.Type.Byte.ByteVal 127 instance Binrep.Type.Byte.ByteVal 128 instance Binrep.Type.Byte.ByteVal 129 instance Binrep.Type.Byte.ByteVal 130 instance Binrep.Type.Byte.ByteVal 131 instance Binrep.Type.Byte.ByteVal 132 instance Binrep.Type.Byte.ByteVal 133 instance Binrep.Type.Byte.ByteVal 134 instance Binrep.Type.Byte.ByteVal 135 instance Binrep.Type.Byte.ByteVal 136 instance Binrep.Type.Byte.ByteVal 137 instance Binrep.Type.Byte.ByteVal 138 instance Binrep.Type.Byte.ByteVal 139 instance Binrep.Type.Byte.ByteVal 140 instance Binrep.Type.Byte.ByteVal 141 instance Binrep.Type.Byte.ByteVal 142 instance Binrep.Type.Byte.ByteVal 143 instance Binrep.Type.Byte.ByteVal 144 instance Binrep.Type.Byte.ByteVal 145 instance Binrep.Type.Byte.ByteVal 146 instance Binrep.Type.Byte.ByteVal 147 instance Binrep.Type.Byte.ByteVal 148 instance Binrep.Type.Byte.ByteVal 149 instance Binrep.Type.Byte.ByteVal 150 instance Binrep.Type.Byte.ByteVal 151 instance Binrep.Type.Byte.ByteVal 152 instance Binrep.Type.Byte.ByteVal 153 instance Binrep.Type.Byte.ByteVal 154 instance Binrep.Type.Byte.ByteVal 155 instance Binrep.Type.Byte.ByteVal 156 instance Binrep.Type.Byte.ByteVal 157 instance Binrep.Type.Byte.ByteVal 158 instance Binrep.Type.Byte.ByteVal 159 instance Binrep.Type.Byte.ByteVal 160 instance Binrep.Type.Byte.ByteVal 161 instance Binrep.Type.Byte.ByteVal 162 instance Binrep.Type.Byte.ByteVal 163 instance Binrep.Type.Byte.ByteVal 164 instance Binrep.Type.Byte.ByteVal 165 instance Binrep.Type.Byte.ByteVal 166 instance Binrep.Type.Byte.ByteVal 167 instance Binrep.Type.Byte.ByteVal 168 instance Binrep.Type.Byte.ByteVal 169 instance Binrep.Type.Byte.ByteVal 170 instance Binrep.Type.Byte.ByteVal 171 instance Binrep.Type.Byte.ByteVal 172 instance Binrep.Type.Byte.ByteVal 173 instance Binrep.Type.Byte.ByteVal 174 instance Binrep.Type.Byte.ByteVal 175 instance Binrep.Type.Byte.ByteVal 176 instance Binrep.Type.Byte.ByteVal 177 instance Binrep.Type.Byte.ByteVal 178 instance Binrep.Type.Byte.ByteVal 179 instance Binrep.Type.Byte.ByteVal 180 instance Binrep.Type.Byte.ByteVal 181 instance Binrep.Type.Byte.ByteVal 182 instance Binrep.Type.Byte.ByteVal 183 instance Binrep.Type.Byte.ByteVal 184 instance Binrep.Type.Byte.ByteVal 185 instance Binrep.Type.Byte.ByteVal 186 instance Binrep.Type.Byte.ByteVal 187 instance Binrep.Type.Byte.ByteVal 188 instance Binrep.Type.Byte.ByteVal 189 instance Binrep.Type.Byte.ByteVal 190 instance Binrep.Type.Byte.ByteVal 191 instance Binrep.Type.Byte.ByteVal 192 instance Binrep.Type.Byte.ByteVal 193 instance Binrep.Type.Byte.ByteVal 194 instance Binrep.Type.Byte.ByteVal 195 instance Binrep.Type.Byte.ByteVal 196 instance Binrep.Type.Byte.ByteVal 197 instance Binrep.Type.Byte.ByteVal 198 instance Binrep.Type.Byte.ByteVal 199 instance Binrep.Type.Byte.ByteVal 200 instance Binrep.Type.Byte.ByteVal 201 instance Binrep.Type.Byte.ByteVal 202 instance Binrep.Type.Byte.ByteVal 203 instance Binrep.Type.Byte.ByteVal 204 instance Binrep.Type.Byte.ByteVal 205 instance Binrep.Type.Byte.ByteVal 206 instance Binrep.Type.Byte.ByteVal 207 instance Binrep.Type.Byte.ByteVal 208 instance Binrep.Type.Byte.ByteVal 209 instance Binrep.Type.Byte.ByteVal 210 instance Binrep.Type.Byte.ByteVal 211 instance Binrep.Type.Byte.ByteVal 212 instance Binrep.Type.Byte.ByteVal 213 instance Binrep.Type.Byte.ByteVal 214 instance Binrep.Type.Byte.ByteVal 215 instance Binrep.Type.Byte.ByteVal 216 instance Binrep.Type.Byte.ByteVal 217 instance Binrep.Type.Byte.ByteVal 218 instance Binrep.Type.Byte.ByteVal 219 instance Binrep.Type.Byte.ByteVal 220 instance Binrep.Type.Byte.ByteVal 221 instance Binrep.Type.Byte.ByteVal 222 instance Binrep.Type.Byte.ByteVal 223 instance Binrep.Type.Byte.ByteVal 224 instance Binrep.Type.Byte.ByteVal 225 instance Binrep.Type.Byte.ByteVal 226 instance Binrep.Type.Byte.ByteVal 227 instance Binrep.Type.Byte.ByteVal 228 instance Binrep.Type.Byte.ByteVal 229 instance Binrep.Type.Byte.ByteVal 230 instance Binrep.Type.Byte.ByteVal 231 instance Binrep.Type.Byte.ByteVal 232 instance Binrep.Type.Byte.ByteVal 233 instance Binrep.Type.Byte.ByteVal 234 instance Binrep.Type.Byte.ByteVal 235 instance Binrep.Type.Byte.ByteVal 236 instance Binrep.Type.Byte.ByteVal 237 instance Binrep.Type.Byte.ByteVal 238 instance Binrep.Type.Byte.ByteVal 239 instance Binrep.Type.Byte.ByteVal 240 instance Binrep.Type.Byte.ByteVal 241 instance Binrep.Type.Byte.ByteVal 242 instance Binrep.Type.Byte.ByteVal 243 instance Binrep.Type.Byte.ByteVal 244 instance Binrep.Type.Byte.ByteVal 245 instance Binrep.Type.Byte.ByteVal 246 instance Binrep.Type.Byte.ByteVal 247 instance Binrep.Type.Byte.ByteVal 248 instance Binrep.Type.Byte.ByteVal 249 instance Binrep.Type.Byte.ByteVal 250 instance Binrep.Type.Byte.ByteVal 251 instance Binrep.Type.Byte.ByteVal 252 instance Binrep.Type.Byte.ByteVal 253 instance Binrep.Type.Byte.ByteVal 254 instance Binrep.Type.Byte.ByteVal 255 instance Binrep.Type.Byte.ReifyBytes '[] module Bytezap.Text textUtf8 :: Text -> Write charUtf8 :: Char -> Write -- | TODO -- -- In a perfect world, functions like this would not exist. But this is -- not a perfect world. Strings suck for a number of reasons. One -- big one is that they are horrendous to serialize. Worse, as of GHC -- 9.6, type-level strings only reflect to String. This function -- does the best it can to efficiently serialize Strings. It would -- be much easier and probably similarly fast to go through Text -- instead, but who doesn't like a little challenge? stringUtf8 :: String -> Write module Data.Aeson.Extra.SizedVector instance Data.Aeson.Types.ToJSON.ToJSON (v a) => Data.Aeson.Types.ToJSON.ToJSON (Data.Vector.Generic.Sized.Internal.Vector v n a) instance (Data.Aeson.Types.FromJSON.FromJSON (v a), GHC.TypeNats.KnownNat n, Data.Vector.Generic.Base.Vector v a) => Data.Aeson.Types.FromJSON.FromJSON (Data.Vector.Generic.Sized.Internal.Vector v n a) -- | Handy typenat utils. module Util.TypeNats natVal'' :: forall n. KnownNat n => Natural natValInt :: forall n. KnownNat n => Int -- | 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. module Binrep.BLen.Simple class BLen a blen :: BLen a => a -> Int newtype BLen' a BLen' :: a -> BLen' a [getBLen'] :: BLen' a -> a -- | Measure the byte length of a term of the non-sum type a via -- its Generic instance. blenGenericNonSum :: forall {cd} {f} {asserts} a. (Generic a, Rep a ~ D1 cd f, GFoldMapNonSum (BLen' Int) f, asserts ~ '[ 'NoEmpty, 'NoSum], ApplyGCAsserts asserts f) => 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 {cd} {f} {asserts} a. (Generic a, Rep a ~ D1 cd f, GFoldMapSum 'SumOnly (BLen' Int) f, asserts ~ '[ 'NoEmpty, 'NeedSum], ApplyGCAsserts asserts f) => (String -> Int) -> a -> Int -- | Deriving via wrapper for types which may derive a BLen instance -- through an existing IsCBLen instance. -- -- Examples of such types include machine integers, and explicitly-sized -- types (e.g. Binrep.Type.Sized). newtype CBLenly a CBLenly :: a -> CBLenly a [unCBLenly] :: CBLenly a -> a -- | Reify a type's constant byte length to the term level. cblen :: forall a n. (n ~ CBLen a, KnownNat n) => Int instance GHC.Num.Num a => GHC.Base.Monoid (Binrep.BLen.Simple.BLen' a) instance GHC.Num.Num a => GHC.Base.Semigroup (Binrep.BLen.Simple.BLen' a) instance Binrep.BLen.Simple.BLen GHC.Word.Word8 instance Binrep.BLen.Simple.BLen GHC.Int.Int8 instance Binrep.BLen.Simple.BLen GHC.Word.Word16 instance Binrep.BLen.Simple.BLen GHC.Int.Int16 instance Binrep.BLen.Simple.BLen GHC.Word.Word32 instance Binrep.BLen.Simple.BLen GHC.Int.Int32 instance Binrep.BLen.Simple.BLen GHC.Word.Word64 instance Binrep.BLen.Simple.BLen GHC.Int.Int64 instance GHC.TypeNats.KnownNat (Binrep.CBLen.CBLen a) => Binrep.BLen.Simple.BLen (Binrep.BLen.Simple.CBLenly a) instance Generic.Data.Function.FoldMap.Constructor.GenericFoldMap (Binrep.BLen.Simple.BLen' GHC.Types.Int) instance (TypeError ...) => Binrep.BLen.Simple.BLen Data.Void.Void instance (TypeError ...) => Binrep.BLen.Simple.BLen (Data.Either.Either a b) instance Binrep.BLen.Simple.BLen Bytezap.Write instance Binrep.BLen.Simple.BLen () instance (Binrep.BLen.Simple.BLen l, Binrep.BLen.Simple.BLen r) => Binrep.BLen.Simple.BLen (l, r) instance Binrep.BLen.Simple.BLen a => Binrep.BLen.Simple.BLen [a] instance Binrep.BLen.Simple.BLen Data.ByteString.Internal.Type.ByteString -- | Serialization using the bytezap library. -- -- bytezap serializers ("pokes") work by writing bytes into a pointer, -- which is assumed to have _precisely_ the space required. The user must -- determine the post-serialize length before the fact. For that reason, -- this module requires that types to be serialized have a BLen -- instance. In general, we are happy about this, because a binrep type -- should always have an efficient and preferably simple BLen -- instance (and if not, it shouldn't be a binrep type). module Binrep.Put.Bytezap class Put a put :: Put a => a -> Poke runPut :: (BLen a, Put a) => a -> ByteString -- | Serialize a term of the non-sum type a via its Generic -- instance. putGenericNonSum :: forall {cd} {f} {asserts} a. (Generic a, Rep a ~ D1 cd f, GFoldMapNonSum Poke f, asserts ~ '[ 'NoEmpty, 'NoSum], ApplyGCAsserts asserts f) => a -> Poke -- | 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 {cd} {f} {asserts} a. (Generic a, Rep a ~ D1 cd f, GFoldMapSum 'SumOnly Poke f, asserts ~ '[ 'NoEmpty, 'NeedSum], ApplyGCAsserts asserts f) => (String -> Poke) -> a -> Poke instance Generic.Data.Function.FoldMap.Constructor.GenericFoldMap Bytezap.Poke instance (TypeError ...) => Binrep.Put.Bytezap.Put Data.Void.Void instance (TypeError ...) => Binrep.Put.Bytezap.Put (Data.Either.Either a b) instance Binrep.Put.Bytezap.Put Bytezap.Write instance Binrep.Put.Bytezap.Put Bytezap.Poke instance Binrep.Put.Bytezap.Put () instance (Binrep.Put.Bytezap.Put l, Binrep.Put.Bytezap.Put r) => Binrep.Put.Bytezap.Put (l, r) instance Binrep.Put.Bytezap.Put a => Binrep.Put.Bytezap.Put [a] instance Binrep.Put.Bytezap.Put Data.ByteString.Internal.Type.ByteString instance Binrep.Put.Bytezap.Put GHC.Word.Word8 instance Binrep.Put.Bytezap.Put GHC.Int.Int8 module Binrep.Via -- | Identity newtype for using with DerivingVia. newtype Binreply a Binreply :: a -> Binreply a [unBinreply] :: Binreply a -> a instance Binrep.Get.Flatparse.Get a => Binrep.Get.Flatparse.Get (Binrep.Via.Binreply a) instance Binrep.Put.Bytezap.Put a => Binrep.Put.Bytezap.Put (Binrep.Via.Binreply a) instance Binrep.Put.Mason.Put a => Binrep.Put.Mason.Put (Binrep.Via.Binreply a) instance Binrep.BLen.Simple.BLen a => Binrep.BLen.Simple.BLen (Binrep.Via.Binreply a) instance Binrep.CBLen.IsCBLen (Binrep.Via.Binreply a) instance GHC.Show.Show a => GHC.Show.Show (Binrep.Via.Binreply a) -- | Machine integers: sized integers & naturals with explicit -- endianness type tags for serialization. module Binrep.Type.Int -- | Machine integer sign. -- -- Signed integers use two's complement for representation. data ISign -- | unsigned U :: ISign -- | signed (two's complement) I :: ISign -- | A type tagged with the endianness (byte order) to use when -- serializing. -- -- Intended to be used to wrap existing types which do not otherwise -- expose endianness, namely the machine integers Int32, -- Word64 etc. As such, it derives various relevant type classes -- using the wrapped type. -- -- May be considered a restricted Tagged (from the tagged -- package). newtype Endian (end :: Endianness) a Endian :: a -> Endian (end :: Endianness) a -- | Discard endianness information. [unEndian] :: Endian (end :: Endianness) a -> a -- | Ask for a minimum length before running the given parser and wrapping -- the result in Endian. flatparseParseEndianMin :: Getter a -> Int -> Getter (Endian end a) -- | Grouping for matching a signedness and size to a Haskell integer data -- type. type family IRep (isign :: ISign) (isize :: Natural) -- | Largest representable value for a machine integer made of n -- bits. -- -- If signed 'I, twos complement is used, so negative range has 1 -- extra value. type family IMax (isign :: ISign) (n :: Natural) :: Natural instance GHC.Classes.Eq Binrep.Type.Int.ISign instance GHC.Show.Show Binrep.Type.Int.ISign instance Data.Data.Data Binrep.Type.Int.ISign instance GHC.Generics.Generic Binrep.Type.Int.ISign instance Data.Aeson.Types.FromJSON.FromJSON a => Data.Aeson.Types.FromJSON.FromJSON (Binrep.Type.Int.Endian end a) instance Data.Aeson.Types.ToJSON.ToJSON a => Data.Aeson.Types.ToJSON.ToJSON (Binrep.Type.Int.Endian end a) instance Strongweak.Strengthen.Strengthen a => Strongweak.Strengthen.Strengthen (Binrep.Type.Int.Endian end a) instance Strongweak.Weaken.Weaken a => Strongweak.Weaken.Weaken (Binrep.Type.Int.Endian end a) instance Binrep.BLen.Simple.BLen a => Binrep.BLen.Simple.BLen (Binrep.Type.Int.Endian end a) instance Binrep.CBLen.IsCBLen (Binrep.Type.Int.Endian end a) instance GHC.Real.Integral a => GHC.Real.Integral (Binrep.Type.Int.Endian end a) instance GHC.Real.Real a => GHC.Real.Real (Binrep.Type.Int.Endian end a) instance GHC.Enum.Enum a => GHC.Enum.Enum (Binrep.Type.Int.Endian end a) instance GHC.Num.Num a => GHC.Num.Num (Binrep.Type.Int.Endian end a) instance GHC.Enum.Bounded a => GHC.Enum.Bounded (Binrep.Type.Int.Endian end a) instance GHC.Classes.Ord a => GHC.Classes.Ord (Binrep.Type.Int.Endian end a) instance GHC.Classes.Eq a => GHC.Classes.Eq (Binrep.Type.Int.Endian end a) instance GHC.Show.Show a => GHC.Show.Show (Binrep.Type.Int.Endian end a) instance (Data.Typeable.Internal.Typeable end, Data.Data.Data a) => Data.Data.Data (Binrep.Type.Int.Endian end a) instance GHC.Generics.Generic (Binrep.Type.Int.Endian end a) instance Binrep.Put.Mason.Put (Binrep.Type.Int.Endian end GHC.Word.Word8) instance Binrep.Get.Flatparse.Get (Binrep.Type.Int.Endian end GHC.Word.Word8) instance Binrep.Put.Mason.Put (Binrep.Type.Int.Endian end GHC.Int.Int8) instance Binrep.Get.Flatparse.Get (Binrep.Type.Int.Endian end GHC.Int.Int8) instance Binrep.Put.Bytezap.Put (Binrep.Type.Int.Endian 'Binrep.Type.Common.LE GHC.Word.Word16) instance Binrep.Get.Flatparse.Get (Binrep.Type.Int.Endian 'Binrep.Type.Common.LE GHC.Word.Word16) instance Binrep.Put.Bytezap.Put (Binrep.Type.Int.Endian 'Binrep.Type.Common.BE GHC.Word.Word16) instance Binrep.Get.Flatparse.Get (Binrep.Type.Int.Endian 'Binrep.Type.Common.BE GHC.Word.Word16) instance Binrep.Put.Bytezap.Put (Binrep.Type.Int.Endian 'Binrep.Type.Common.LE GHC.Word.Word32) instance Binrep.Get.Flatparse.Get (Binrep.Type.Int.Endian 'Binrep.Type.Common.LE GHC.Word.Word32) instance Binrep.Put.Bytezap.Put (Binrep.Type.Int.Endian 'Binrep.Type.Common.BE GHC.Word.Word32) instance Binrep.Get.Flatparse.Get (Binrep.Type.Int.Endian 'Binrep.Type.Common.BE GHC.Word.Word32) instance Binrep.Put.Bytezap.Put (Binrep.Type.Int.Endian 'Binrep.Type.Common.LE GHC.Word.Word64) instance Binrep.Get.Flatparse.Get (Binrep.Type.Int.Endian 'Binrep.Type.Common.LE GHC.Word.Word64) instance Binrep.Put.Bytezap.Put (Binrep.Type.Int.Endian 'Binrep.Type.Common.BE GHC.Word.Word64) instance Binrep.Get.Flatparse.Get (Binrep.Type.Int.Endian 'Binrep.Type.Common.BE GHC.Word.Word64) instance Binrep.Put.Bytezap.Put (Binrep.Type.Int.Endian 'Binrep.Type.Common.LE GHC.Int.Int16) instance Binrep.Get.Flatparse.Get (Binrep.Type.Int.Endian 'Binrep.Type.Common.LE GHC.Int.Int16) instance Binrep.Put.Bytezap.Put (Binrep.Type.Int.Endian 'Binrep.Type.Common.BE GHC.Int.Int16) instance Binrep.Get.Flatparse.Get (Binrep.Type.Int.Endian 'Binrep.Type.Common.BE GHC.Int.Int16) instance Binrep.Put.Bytezap.Put (Binrep.Type.Int.Endian 'Binrep.Type.Common.LE GHC.Int.Int32) instance Binrep.Get.Flatparse.Get (Binrep.Type.Int.Endian 'Binrep.Type.Common.LE GHC.Int.Int32) instance Binrep.Put.Bytezap.Put (Binrep.Type.Int.Endian 'Binrep.Type.Common.BE GHC.Int.Int32) instance Binrep.Get.Flatparse.Get (Binrep.Type.Int.Endian 'Binrep.Type.Common.BE GHC.Int.Int32) instance Binrep.Put.Bytezap.Put (Binrep.Type.Int.Endian 'Binrep.Type.Common.LE GHC.Int.Int64) instance Binrep.Get.Flatparse.Get (Binrep.Type.Int.Endian 'Binrep.Type.Common.LE GHC.Int.Int64) instance Binrep.Put.Bytezap.Put (Binrep.Type.Int.Endian 'Binrep.Type.Common.BE GHC.Int.Int64) instance Binrep.Get.Flatparse.Get (Binrep.Type.Int.Endian 'Binrep.Type.Common.BE GHC.Int.Int64) module Binrep.Type.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. -- -- TODO oops can't use Ints everywhere because of overflow :'( -- that's OK 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.Type.Prefix.Prefix a => Binrep.Type.Prefix.Prefix (Binrep.Type.Int.Endian end a) instance Binrep.Type.Prefix.Prefix () instance Binrep.Type.Prefix.Prefix GHC.Word.Word8 instance Binrep.Type.Prefix.Prefix GHC.Word.Word16 instance Binrep.Type.Prefix.Prefix GHC.Word.Word32 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.Bytezap.Put a => Binrep.Put.Bytezap.Put (Binrep.Type.Thin.Thin a) instance Binrep.BLen.Simple.BLen a => Binrep.BLen.Simple.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.Flatparse.Get (Binrep.Type.Thin.Thin Data.ByteString.Internal.Type.ByteString) instance Binrep.Get.Flatparse.Get (Binrep.Type.Thin.Thin Bytezap.Write) -- | Constant-size data. module Binrep.Type.Sized -- | Essentially reflects a BLen type to CBLen. data Size (n :: Natural) type Sized n = Refined (Size n) instance GHC.TypeNats.KnownNat n => Binrep.BLen.Simple.BLen (Binrep.Type.Sized.Sized n a) instance Binrep.CBLen.IsCBLen (Binrep.Type.Sized.Sized n a) instance Binrep.Put.Bytezap.Put a => Binrep.Put.Bytezap.Put (Binrep.Type.Sized.Sized n a) instance (Binrep.Get.Flatparse.Get a, GHC.TypeNats.KnownNat n) => Binrep.Get.Flatparse.Get (Binrep.Type.Sized.Sized n a) instance (Binrep.BLen.Simple.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.Type.Prefix.Prefix pfx, Binrep.Type.Prefix.Size.GetSize a, Binrep.Get.Flatparse.Get pfx) => Binrep.Get.Flatparse.Get (Binrep.Type.Prefix.Size.SizePrefixed pfx a) instance Binrep.CBLen.IsCBLen (Binrep.Type.Prefix.Size.SizePrefixed pfx a) instance (Binrep.Type.Prefix.Prefix pfx, Binrep.BLen.Simple.BLen a, Binrep.BLen.Simple.BLen pfx) => Binrep.BLen.Simple.BLen (Binrep.Type.Prefix.Size.SizePrefixed pfx a) instance (Binrep.Type.Prefix.Prefix pfx, Binrep.BLen.Simple.BLen a, Binrep.Put.Bytezap.Put pfx, Binrep.Put.Bytezap.Put a) => Binrep.Put.Bytezap.Put (Binrep.Type.Prefix.Size.SizePrefixed pfx a) instance (GHC.TypeNats.KnownNat (Binrep.Type.Prefix.Max pfx), Binrep.BLen.Simple.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.Type.Prefix.Prefix pfx, Binrep.Type.Prefix.Count.GetCount f, Binrep.Get.Flatparse.Get pfx, Binrep.Get.Flatparse.Get a) => Binrep.Get.Flatparse.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.Type.Prefix.Prefix pfx, Data.Foldable.Foldable f, Binrep.BLen.Simple.BLen pfx, Binrep.BLen.Simple.BLen (f a)) => Binrep.BLen.Simple.BLen (Binrep.Type.Prefix.Count.CountPrefixed pfx f a) instance (Binrep.Type.Prefix.Prefix pfx, Data.Foldable.Foldable f, Binrep.Put.Bytezap.Put pfx, Binrep.Put.Bytezap.Put (f a)) => Binrep.Put.Bytezap.Put (Binrep.Type.Prefix.Count.CountPrefixed pfx f a) instance (GHC.TypeNats.KnownNat (Binrep.Type.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.Type.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.Simple.BLen a => Binrep.BLen.Simple.BLen (Binrep.Type.NullTerminated.NullTerminated a) instance Binrep.Put.Bytezap.Put a => Binrep.Put.Bytezap.Put (Binrep.Type.NullTerminated.NullTerminated a) instance Binrep.Get.Flatparse.Get (Binrep.Type.NullTerminated.NullTerminated Data.ByteString.Internal.Type.ByteString) module Binrep.Generic -- | 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. -- -- The refine force is safe under the assumption that Haskell constructor -- names are UTF-8 with no null bytes allowed. Fairly certain that's -- true. nullTermCstrPfxTag :: String -> NullTerminated ByteString 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 (Binrep.BLen.Simple.BLen a, Binrep.Put.Bytezap.Put a, GHC.TypeNats.KnownNat n) => Binrep.Put.Bytezap.Put (Binrep.Type.NullPadded.NullPadded n a) instance (Binrep.BLen.Simple.BLen a, Binrep.Get.Flatparse.Get a, GHC.TypeNats.KnownNat n) => Binrep.Get.Flatparse.Get (Binrep.Type.NullPadded.NullPadded n a) instance (Binrep.BLen.Simple.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" (a constant -- bytestring) 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) 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.Simple.BLen (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, Binrep.Type.Byte.ReifyBytes bs) => Binrep.Put.Bytezap.Put (Binrep.Type.Magic.Magic a) instance forall k (bs :: [GHC.Num.Natural.Natural]) (a :: k). (bs GHC.Types.~ Binrep.Type.Magic.MagicBytes a, Binrep.Type.Byte.ReifyBytes bs, GHC.TypeNats.KnownNat (Binrep.Type.Magic.Length bs)) => Binrep.Get.Flatparse.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)