binrep 0.3.1 → 0.5.0
raw patch · 68 files changed
+2808/−2535 lines, 68 filesdep +deepseqdep +gaugedep +generic-data-functionsdep −eitherdep −refineddep ~aesondep ~bytestringdep ~flatparsePVP ok
version bump matches the API change (PVP)
Dependencies added: deepseq, gauge, generic-data-functions, parser-combinators, refined1
Dependencies removed: either, refined
Dependency ranges changed: aeson, bytestring, flatparse, hspec, megaparsec, strongweak, text, vector
API changes (from Hackage documentation)
- Binrep: blenViaPut :: Put a => a -> BLenT
- Binrep.BLen: --
- Binrep.BLen: -- Many binary representation primitives are constant, or may be designed
- Binrep.BLen: -- This is now an associated type family of the <a>BLen</a> type class in
- Binrep.BLen: -- about their length than just <a>blen</a>.
- Binrep.BLen: -- hopes of simplifying the binrep framework.
- Binrep.BLen: -- to "store" their size in their type. This is a stronger statement
- Binrep.BLen: -- | The length in bytes of any value of the given type is constant.
- Binrep.BLen: WithCBLen :: a -> WithCBLen a
- Binrep.BLen: [unWithCBLen] :: WithCBLen a -> a
- Binrep.BLen: blen :: (BLen a, KnownNat (CBLen a)) => a -> BLenT
- Binrep.BLen: cblen :: forall a n. (n ~ CBLen a, KnownNat n) => BLenT
- Binrep.BLen: class BLen a where {
- Binrep.BLen: instance (Binrep.BLen.BLen a, Binrep.BLen.BLen b) => Binrep.BLen.BLen (a, b)
- Binrep.BLen: instance Binrep.BLen.BLen Data.ByteString.Internal.ByteString
- Binrep.BLen: instance Binrep.BLen.BLen Data.Void.Void
- Binrep.BLen: instance Binrep.BLen.BLen GHC.Int.Int16
- Binrep.BLen: instance Binrep.BLen.BLen GHC.Int.Int32
- Binrep.BLen: instance Binrep.BLen.BLen GHC.Int.Int64
- Binrep.BLen: instance Binrep.BLen.BLen GHC.Int.Int8
- Binrep.BLen: instance Binrep.BLen.BLen GHC.Word.Word16
- Binrep.BLen: instance Binrep.BLen.BLen GHC.Word.Word32
- Binrep.BLen: instance Binrep.BLen.BLen GHC.Word.Word64
- Binrep.BLen: instance Binrep.BLen.BLen GHC.Word.Word8
- Binrep.BLen: instance Binrep.BLen.BLen a => Binrep.BLen.BLen [a]
- Binrep.BLen: instance GHC.TypeNats.KnownNat (Binrep.BLen.CBLen a GHC.TypeNats.+ Binrep.BLen.CBLen b) => Binrep.BLen.BLen (Binrep.BLen.WithCBLen (a, b))
- Binrep.BLen: instance GHC.TypeNats.KnownNat (Binrep.BLen.CBLen a) => Binrep.BLen.BLen (Binrep.BLen.WithCBLen [a])
- Binrep.BLen: newtype WithCBLen a
- Binrep.BLen: type BLenT = Int
- Binrep.BLen: type CBLen a = TypeError ('Text "No CBLen associated family instance defined for " :<>: 'ShowType a);
- Binrep.BLen: typeNatToBLen :: forall n. KnownNat n => BLenT
- Binrep.BLen: }
- Binrep.BLen.Internal.AsBLen: class AsBLen a
- Binrep.BLen.Internal.AsBLen: instance Binrep.BLen.Internal.AsBLen.AsBLen GHC.Num.Natural.Natural
- Binrep.BLen.Internal.AsBLen: instance Binrep.BLen.Internal.AsBLen.AsBLen GHC.Types.Int
- Binrep.BLen.Internal.AsBLen: natToBLen :: AsBLen a => Natural -> a
- Binrep.BLen.Internal.AsBLen: posIntToBLen :: AsBLen a => Int -> a
- Binrep.BLen.Internal.AsBLen: safeBLenSub :: AsBLen a => a -> a -> Maybe a
- Binrep.BLen.Internal.AsBLen: wordToBLen# :: AsBLen a => Word# -> a
- Binrep.Example: DCS1 :: DCS
- Binrep.Example: DCS2 :: DCS
- Binrep.Example: DCS3 :: DCS
- Binrep.Example: DCS4 :: DCS
- Binrep.Example: DCS5 :: DCS
- Binrep.Example: DSS :: I 'U 'I1 'LE -> I 'U 'I2 'LE -> I 'U 'I4 'LE -> I 'U 'I8 'LE -> I 'U 'I1 'LE -> DSS
- Binrep.Example: DU :: DU
- Binrep.Example: DX :: DU -> DX
- Binrep.Example: [dss1] :: DSS -> I 'U 'I1 'LE
- Binrep.Example: [dss2] :: DSS -> I 'U 'I2 'LE
- Binrep.Example: [dss3] :: DSS -> I 'U 'I4 'LE
- Binrep.Example: [dss4] :: DSS -> I 'U 'I8 'LE
- Binrep.Example: [dss5] :: DSS -> I 'U 'I1 'LE
- Binrep.Example: brCfgDCS :: Cfg BrSumDCS
- Binrep.Example: data DCS
- Binrep.Example: data DSS
- Binrep.Example: data DU
- Binrep.Example: data DV
- Binrep.Example: data DX
- Binrep.Example: instance Binrep.BLen.BLen Binrep.Example.DCS
- Binrep.Example: instance Binrep.BLen.BLen Binrep.Example.DSS
- Binrep.Example: instance Binrep.BLen.BLen Binrep.Example.DU
- Binrep.Example: instance Binrep.BLen.BLen Binrep.Example.DX
- Binrep.Example: instance Binrep.Get.Get Binrep.Example.DCS
- Binrep.Example: instance Binrep.Get.Get Binrep.Example.DSS
- Binrep.Example: instance Binrep.Get.Get Binrep.Example.DU
- Binrep.Example: instance Binrep.Get.Get Binrep.Example.DX
- Binrep.Example: instance Binrep.Put.Put Binrep.Example.DCS
- Binrep.Example: instance Binrep.Put.Put Binrep.Example.DSS
- Binrep.Example: instance Binrep.Put.Put Binrep.Example.DU
- Binrep.Example: instance Binrep.Put.Put Binrep.Example.DX
- Binrep.Example: instance Data.Data.Data Binrep.Example.DCS
- Binrep.Example: instance Data.Data.Data Binrep.Example.DSS
- Binrep.Example: instance Data.Data.Data Binrep.Example.DU
- Binrep.Example: instance Data.Data.Data Binrep.Example.DV
- Binrep.Example: instance Data.Data.Data Binrep.Example.DX
- Binrep.Example: instance GHC.Classes.Eq Binrep.Example.DCS
- Binrep.Example: instance GHC.Classes.Eq Binrep.Example.DSS
- Binrep.Example: instance GHC.Classes.Eq Binrep.Example.DU
- Binrep.Example: instance GHC.Classes.Eq Binrep.Example.DX
- Binrep.Example: instance GHC.Generics.Generic Binrep.Example.DCS
- Binrep.Example: instance GHC.Generics.Generic Binrep.Example.DSS
- Binrep.Example: instance GHC.Generics.Generic Binrep.Example.DU
- Binrep.Example: instance GHC.Generics.Generic Binrep.Example.DV
- Binrep.Example: instance GHC.Generics.Generic Binrep.Example.DX
- Binrep.Example: instance GHC.Show.Show Binrep.Example.DCS
- Binrep.Example: instance GHC.Show.Show Binrep.Example.DSS
- Binrep.Example: instance GHC.Show.Show Binrep.Example.DU
- Binrep.Example: instance GHC.Show.Show Binrep.Example.DX
- Binrep.Example: type BrSumDCS = I 'U 'I1 'LE
- Binrep.Example.FileTable: Entry :: a -> SW s (Refined (SizeLessThan (IMax 'U 'I1)) BS) -> Entry s a
- Binrep.Example.FileTable: Table :: SW s (LenPfx 'I1 'LE (Entry s a)) -> Table s a
- Binrep.Example.FileTable: [entryData] :: Entry s a -> SW s (Refined (SizeLessThan (IMax 'U 'I1)) BS)
- Binrep.Example.FileTable: [entryName] :: Entry s a -> a
- Binrep.Example.FileTable: [unTable] :: Table s a -> SW s (LenPfx 'I1 'LE (Entry s a))
- Binrep.Example.FileTable: data Entry s a
- Binrep.Example.FileTable: exBs :: BS
- Binrep.Example.FileTable: getEntry :: Get a => Addr# -> Getter (Entry 'Strong a)
- Binrep.Example.FileTable: getFileTable :: Get a => Getter (Table 'Strong a)
- Binrep.Example.FileTable: instance (Binrep.Put.Put a, Binrep.BLen.BLen a) => Binrep.Put.Put (Binrep.Example.FileTable.Table 'Strongweak.Weaken.Strong a)
- Binrep.Example.FileTable: instance Binrep.Get.Get a => Binrep.Get.Get (Binrep.Example.FileTable.Table 'Strongweak.Weaken.Strong a)
- Binrep.Example.FileTable: instance Binrep.Get.Get a => Binrep.Get.GetWith GHC.Prim.Addr# (Binrep.Example.FileTable.Entry 'Strongweak.Weaken.Strong a)
- Binrep.Example.FileTable: instance GHC.Classes.Eq a => GHC.Classes.Eq (Binrep.Example.FileTable.Entry 'Strongweak.Weaken.Strong a)
- Binrep.Example.FileTable: instance GHC.Classes.Eq a => GHC.Classes.Eq (Binrep.Example.FileTable.Entry 'Strongweak.Weaken.Weak a)
- Binrep.Example.FileTable: instance GHC.Generics.Generic (Binrep.Example.FileTable.Entry s a)
- Binrep.Example.FileTable: instance GHC.Show.Show a => GHC.Show.Show (Binrep.Example.FileTable.Entry 'Strongweak.Weaken.Strong a)
- Binrep.Example.FileTable: instance GHC.Show.Show a => GHC.Show.Show (Binrep.Example.FileTable.Entry 'Strongweak.Weaken.Weak a)
- Binrep.Example.FileTable: instance Strongweak.Strengthen.Strengthen (Binrep.Example.FileTable.Entry 'Strongweak.Weaken.Strong a)
- Binrep.Example.FileTable: instance Strongweak.Weaken.Weaken (Binrep.Example.FileTable.Entry 'Strongweak.Weaken.Strong a)
- Binrep.Example.FileTable: newtype Table s a
- Binrep.Example.FileTable: prepEntry :: (Put a, BLen a) => Entry 'Strong a -> (BLenT, Word8 -> Builder, BS)
- Binrep.Example.FileTable: putFileTable :: (Put a, BLen a) => Table 'Strong a -> Builder
- Binrep.Example.FileTable: type BS = ByteString
- Binrep.Example.FileTable: w8i# :: Word8# -> Int#
- Binrep.Example.Tar: Tar :: NullPadded 100 BS -> TarNat 8 -> TarNat 8 -> TarNat 8 -> TarNat 12 -> TarNat 12 -> Tar
- Binrep.Example.Tar: TarNat :: AsciiNat 8 -> TarNat n
- Binrep.Example.Tar: [getTarNat] :: TarNat n -> AsciiNat 8
- Binrep.Example.Tar: [tarFileFileSize] :: Tar -> TarNat 12
- Binrep.Example.Tar: [tarFileLastMod] :: Tar -> TarNat 12
- Binrep.Example.Tar: [tarFileMode] :: Tar -> TarNat 8
- Binrep.Example.Tar: [tarFileName] :: Tar -> NullPadded 100 BS
- Binrep.Example.Tar: [tarFileUIDGroup] :: Tar -> TarNat 8
- Binrep.Example.Tar: [tarFileUIDOwner] :: Tar -> TarNat 8
- Binrep.Example.Tar: data Tar
- Binrep.Example.Tar: instance Binrep.BLen.BLen Binrep.Example.Tar.Tar
- Binrep.Example.Tar: instance Binrep.Get.Get Binrep.Example.Tar.Tar
- Binrep.Example.Tar: instance Binrep.Put.Put Binrep.Example.Tar.Tar
- Binrep.Example.Tar: instance GHC.Classes.Eq Binrep.Example.Tar.Tar
- Binrep.Example.Tar: instance GHC.Generics.Generic Binrep.Example.Tar.Tar
- Binrep.Example.Tar: instance GHC.Show.Show Binrep.Example.Tar.Tar
- Binrep.Example.Tar: instance GHC.TypeNats.KnownNat n => Binrep.BLen.BLen (Binrep.Example.Tar.TarNat n)
- Binrep.Example.Tar: instance GHC.TypeNats.KnownNat n => Binrep.Get.Get (Binrep.Example.Tar.TarNat n)
- Binrep.Example.Tar: instance GHC.TypeNats.KnownNat n => Binrep.Put.Put (Binrep.Example.Tar.TarNat n)
- Binrep.Example.Tar: instance forall k (n :: k). GHC.Classes.Eq (Binrep.Example.Tar.TarNat n)
- Binrep.Example.Tar: instance forall k (n :: k). GHC.Generics.Generic (Binrep.Example.Tar.TarNat n)
- Binrep.Example.Tar: instance forall k (n :: k). GHC.Show.Show (Binrep.Example.Tar.TarNat n)
- Binrep.Example.Tar: newtype TarNat n
- Binrep.Example.Tar: type BS = ByteString
- Binrep.Example.Tiff: TiffBody :: Magic (TiffMagic end) -> I 'U 'I4 end -> TiffBody (end :: Endianness)
- Binrep.Example.Tiff: [Tiff] :: (Put (I 'U 'I4 end), bs ~ MagicBytes (TiffMagic end), ReifyBytes bs, KnownNat (Length bs)) => TiffBody end -> Tiff
- Binrep.Example.Tiff: [tiffBodyExInt] :: TiffBody (end :: Endianness) -> I 'U 'I4 end
- Binrep.Example.Tiff: [tiffBodyMagic] :: TiffBody (end :: Endianness) -> Magic (TiffMagic end)
- Binrep.Example.Tiff: data Tiff
- Binrep.Example.Tiff: data TiffBody (end :: Endianness)
- Binrep.Example.Tiff: instance (GHC.TypeLits.KnownSymbol (Binrep.Example.Tiff.TiffMagic end), Data.Typeable.Internal.Typeable end) => Data.Data.Data (Binrep.Example.Tiff.TiffBody end)
- Binrep.Example.Tiff: instance (bs GHC.Types.~ Binrep.Type.Magic.MagicBytes (Binrep.Example.Tiff.TiffMagic end), Binrep.Type.Byte.ReifyBytes bs, irep GHC.Types.~ Binrep.Type.Int.I 'Binrep.Type.Int.U 'Binrep.Type.Int.I4 end, Binrep.Get.Get irep) => Binrep.Get.Get (Binrep.Example.Tiff.TiffBody end)
- Binrep.Example.Tiff: instance (bs GHC.Types.~ Binrep.Type.Magic.MagicBytes (Binrep.Example.Tiff.TiffMagic end), Binrep.Type.Byte.ReifyBytes bs, irep GHC.Types.~ Binrep.Type.Int.I 'Binrep.Type.Int.U 'Binrep.Type.Int.I4 end, Binrep.Put.Put irep) => Binrep.Put.Put (Binrep.Example.Tiff.TiffBody end)
- Binrep.Example.Tiff: instance (bs GHC.Types.~ Binrep.Type.Magic.MagicBytes (Binrep.Example.Tiff.TiffMagic end), GHC.TypeNats.KnownNat (Binrep.Type.Byte.Length bs)) => Binrep.BLen.BLen (Binrep.Example.Tiff.TiffBody end)
- Binrep.Example.Tiff: instance Binrep.BLen.BLen Binrep.Example.Tiff.Tiff
- Binrep.Example.Tiff: instance Binrep.Get.Get Binrep.Example.Tiff.Tiff
- Binrep.Example.Tiff: instance Binrep.Put.Put Binrep.Example.Tiff.Tiff
- Binrep.Example.Tiff: instance GHC.Classes.Eq (Binrep.Example.Tiff.TiffBody end)
- Binrep.Example.Tiff: instance GHC.Generics.Generic (Binrep.Example.Tiff.TiffBody end)
- Binrep.Example.Tiff: instance GHC.Show.Show (Binrep.Example.Tiff.TiffBody end)
- Binrep.Example.Tiff: instance GHC.Show.Show Binrep.Example.Tiff.Tiff
- Binrep.Example.Tiff: tiffBEbs :: ByteString
- Binrep.Example.Tiff: tiffLEbs :: ByteString
- Binrep.Example.Tiff: type W8 = I 'U 'I1 'LE
- Binrep.Example.Tiff: type family TiffMagic (end :: Endianness) :: Symbol
- Binrep.Example.Wav: WavHeader :: Magic "RIFF" -> W32 -> Magic "WAVE" -> Magic "fmt " -> W16 -> W16 -> WavHeader
- Binrep.Example.Wav: [wavHeaderChannels] :: WavHeader -> W16
- Binrep.Example.Wav: [wavHeaderChunkSize] :: WavHeader -> W32
- Binrep.Example.Wav: [wavHeaderFmtChunkMarker] :: WavHeader -> Magic "fmt "
- Binrep.Example.Wav: [wavHeaderFmtType] :: WavHeader -> W16
- Binrep.Example.Wav: [wavHeaderFmt] :: WavHeader -> Magic "WAVE"
- Binrep.Example.Wav: [wavHeaderMagic] :: WavHeader -> Magic "RIFF"
- Binrep.Example.Wav: data WavHeader
- Binrep.Example.Wav: instance Binrep.BLen.BLen Binrep.Example.Wav.WavHeader
- Binrep.Example.Wav: instance Binrep.Get.Get Binrep.Example.Wav.WavHeader
- Binrep.Example.Wav: instance Binrep.Put.Put Binrep.Example.Wav.WavHeader
- Binrep.Example.Wav: instance Data.Data.Data Binrep.Example.Wav.WavHeader
- Binrep.Example.Wav: instance GHC.Classes.Eq Binrep.Example.Wav.WavHeader
- Binrep.Example.Wav: instance GHC.Generics.Generic Binrep.Example.Wav.WavHeader
- Binrep.Example.Wav: instance GHC.Show.Show Binrep.Example.Wav.WavHeader
- Binrep.Example.Wav: type End = 'LE
- Binrep.Example.Wav: type W16 = I 'U 'I2 End
- Binrep.Example.Wav: type W32 = I 'U 'I4 End
- Binrep.Extra.HexByteString: instance Data.Aeson.Types.FromJSON.FromJSON (Binrep.Extra.HexByteString.Hex Data.ByteString.Internal.ByteString)
- Binrep.Extra.HexByteString: instance Data.Aeson.Types.ToJSON.ToJSON (Binrep.Extra.HexByteString.Hex Data.ByteString.Internal.ByteString)
- Binrep.Extra.HexByteString: instance GHC.Show.Show (Binrep.Extra.HexByteString.Hex Data.ByteString.Internal.ByteString)
- Binrep.Generic: Cfg :: (String -> a) -> (a -> a -> Bool) -> (a -> Text) -> Cfg a
- Binrep.Generic: EDerivedSumInstanceWithNonSumCfg :: EDerivedSumInstanceWithNonSumCfg
- Binrep.Generic: [cSumTagEq] :: Cfg a -> a -> a -> Bool
- Binrep.Generic: [cSumTagShow] :: Cfg a -> a -> Text
- Binrep.Generic: [cSumTag] :: Cfg a -> String -> a
- Binrep.Generic: blenGeneric :: (Generic a, GBLen (Rep a), BLen w) => Cfg w -> a -> BLenT
- Binrep.Generic: cDef :: Cfg (AsByteString 'C)
- Binrep.Generic: cNoSum :: Cfg Void
- Binrep.Generic: cSumTagHex :: forall a. Integral a => (String -> String) -> String -> a
- Binrep.Generic: cSumTagNullTerm :: String -> AsByteString 'C
- Binrep.Generic: cfg :: (Eq a, Show a) => (String -> a) -> Cfg a
- Binrep.Generic: data Cfg a
- Binrep.Generic: data EDerivedSumInstanceWithNonSumCfg
- Binrep.Generic: getGeneric :: (Generic a, GGetD (Rep a), Get w) => Cfg w -> Getter a
- Binrep.Generic: instance GHC.Exception.Type.Exception Binrep.Generic.EDerivedSumInstanceWithNonSumCfg
- Binrep.Generic: instance GHC.Show.Show Binrep.Generic.EDerivedSumInstanceWithNonSumCfg
- Binrep.Generic: putGeneric :: (Generic a, GPut (Rep a), Put w) => Cfg w -> a -> Builder
- Binrep.Generic: type CBLenGeneric w a = GCBLen w (Rep a)
- Binrep.Generic.BLen: blenGeneric :: (Generic a, GBLen (Rep a), BLen w) => Cfg w -> a -> BLenT
- Binrep.Generic.BLen: class GBLen f
- Binrep.Generic.BLen: class GBLenSum f
- Binrep.Generic.BLen: gblen :: (GBLen f, BLen w) => Cfg w -> f p -> BLenT
- Binrep.Generic.BLen: gblensum :: (GBLenSum f, BLen w) => Cfg w -> f p -> BLenT
- Binrep.Generic.BLen: instance (TypeError ...) => Binrep.Generic.BLen.GBLen GHC.Generics.V1
- Binrep.Generic.BLen: instance Binrep.BLen.BLen c => Binrep.Generic.BLen.GBLen (GHC.Generics.K1 i c)
- Binrep.Generic.BLen: instance Binrep.Generic.BLen.GBLen GHC.Generics.U1
- Binrep.Generic.BLen: instance forall k (f :: k -> *) (c :: GHC.Generics.Meta). (Binrep.Generic.BLen.GBLen f, GHC.Generics.Constructor c) => Binrep.Generic.BLen.GBLenSum (GHC.Generics.C1 c f)
- Binrep.Generic.BLen: instance forall k (f :: k -> *) i (d :: GHC.Generics.Meta). Binrep.Generic.BLen.GBLen f => Binrep.Generic.BLen.GBLen (GHC.Generics.M1 i d f)
- Binrep.Generic.BLen: instance forall k (l :: k -> *) (r :: k -> *). (Binrep.Generic.BLen.GBLen l, Binrep.Generic.BLen.GBLen r) => Binrep.Generic.BLen.GBLen (l GHC.Generics.:*: r)
- Binrep.Generic.BLen: instance forall k (l :: k -> *) (r :: k -> *). (Binrep.Generic.BLen.GBLenSum l, Binrep.Generic.BLen.GBLenSum r) => Binrep.Generic.BLen.GBLenSum (l GHC.Generics.:+: r)
- Binrep.Generic.BLen: instance forall k (l :: k -> *) (r :: k -> *). Binrep.Generic.BLen.GBLenSum (l GHC.Generics.:+: r) => Binrep.Generic.BLen.GBLen (l GHC.Generics.:+: r)
- Binrep.Generic.CBLen: data JustX a b
- Binrep.Generic.CBLen: data NothingX
- Binrep.Generic.CBLen: type CBLenGeneric w a = GCBLen w (Rep a)
- Binrep.Generic.CBLen: type family GCBLenCaseMaybe a
- Binrep.Generic.Get: class GGetC f
- Binrep.Generic.Get: class GGetCSum f
- Binrep.Generic.Get: class GGetD f
- Binrep.Generic.Get: class GGetS f
- Binrep.Generic.Get: getGeneric :: (Generic a, GGetD (Rep a), Get w) => Cfg w -> Getter a
- Binrep.Generic.Get: ggetC :: (GGetC f, Get w) => Cfg w -> String -> Getter (f a)
- Binrep.Generic.Get: ggetCSum :: (GGetCSum f, Get w) => Cfg w -> String -> w -> Maybe (Getter (f a))
- Binrep.Generic.Get: ggetD :: (GGetD f, Get w) => Cfg w -> Getter (f a)
- Binrep.Generic.Get: ggetS :: (GGetS f, Get w) => Cfg w -> String -> String -> Natural -> Getter (Natural, f a)
- Binrep.Generic.Get: instance (Binrep.Get.Get a, GHC.Generics.Selector s) => Binrep.Generic.Get.GGetS (GHC.Generics.S1 s (GHC.Generics.Rec0 a))
- Binrep.Generic.Get: instance (TypeError ...) => Binrep.Generic.Get.GGetC GHC.Generics.V1
- Binrep.Generic.Get: instance Binrep.Generic.Get.GGetS GHC.Generics.U1
- Binrep.Generic.Get: instance forall k (f :: k -> *) (c :: GHC.Generics.Meta). (Binrep.Generic.Get.GGetS f, GHC.Generics.Constructor c) => Binrep.Generic.Get.GGetC (GHC.Generics.C1 c f)
- Binrep.Generic.Get: instance forall k (f :: k -> *) (c :: GHC.Generics.Meta). (Binrep.Generic.Get.GGetS f, GHC.Generics.Constructor c) => Binrep.Generic.Get.GGetCSum (GHC.Generics.C1 c f)
- Binrep.Generic.Get: instance forall k (f :: k -> *) (d :: GHC.Generics.Meta). (Binrep.Generic.Get.GGetC f, GHC.Generics.Datatype d) => Binrep.Generic.Get.GGetD (GHC.Generics.D1 d f)
- Binrep.Generic.Get: instance forall k (l :: k -> *) (r :: k -> *). (Binrep.Generic.Get.GGetCSum l, Binrep.Generic.Get.GGetCSum r) => Binrep.Generic.Get.GGetCSum (l GHC.Generics.:+: r)
- Binrep.Generic.Get: instance forall k (l :: k -> *) (r :: k -> *). (Binrep.Generic.Get.GGetS l, Binrep.Generic.Get.GGetS r) => Binrep.Generic.Get.GGetS (l GHC.Generics.:*: r)
- Binrep.Generic.Get: instance forall k (l :: k -> *) (r :: k -> *). Binrep.Generic.Get.GGetCSum (l GHC.Generics.:+: r) => Binrep.Generic.Get.GGetC (l GHC.Generics.:+: r)
- Binrep.Generic.Internal: Cfg :: (String -> a) -> (a -> a -> Bool) -> (a -> Text) -> Cfg a
- Binrep.Generic.Internal: [cSumTagEq] :: Cfg a -> a -> a -> Bool
- Binrep.Generic.Internal: [cSumTagShow] :: Cfg a -> a -> Text
- Binrep.Generic.Internal: [cSumTag] :: Cfg a -> String -> a
- Binrep.Generic.Internal: data Cfg a
- Binrep.Generic.Internal: type GErrRefuseVoid = 'Text "Refusing to derive binary representation for void datatype"
- Binrep.Generic.Put: class GPut f
- Binrep.Generic.Put: class GPutSum f
- Binrep.Generic.Put: class GetConName f
- Binrep.Generic.Put: getConName :: GetConName f => f a -> String
- Binrep.Generic.Put: gput :: (GPut f, Put w) => Cfg w -> f p -> Builder
- Binrep.Generic.Put: gputsum :: (GPutSum f, Put w) => Cfg w -> f a -> Builder
- Binrep.Generic.Put: instance (TypeError ...) => Binrep.Generic.Put.GPut GHC.Generics.V1
- Binrep.Generic.Put: instance Binrep.Generic.Put.GPut GHC.Generics.U1
- Binrep.Generic.Put: instance Binrep.Put.Put c => Binrep.Generic.Put.GPut (GHC.Generics.K1 i c)
- Binrep.Generic.Put: instance forall k (a :: k -> *) (b :: k -> *). (Binrep.Generic.Put.GetConName a, Binrep.Generic.Put.GetConName b) => Binrep.Generic.Put.GetConName (a GHC.Generics.:+: b)
- Binrep.Generic.Put: instance forall k (c :: GHC.Generics.Meta) (a :: k -> *). GHC.Generics.Constructor c => Binrep.Generic.Put.GetConName (GHC.Generics.C1 c a)
- Binrep.Generic.Put: instance forall k (f :: k -> *) i (d :: GHC.Generics.Meta). Binrep.Generic.Put.GPut f => Binrep.Generic.Put.GPut (GHC.Generics.M1 i d f)
- Binrep.Generic.Put: instance forall k (l :: k -> *) (r :: k -> *). (Binrep.Generic.Put.GPut l, Binrep.Generic.Put.GPut r) => Binrep.Generic.Put.GPut (l GHC.Generics.:*: r)
- Binrep.Generic.Put: instance forall k (l :: k -> *) (r :: k -> *). (Binrep.Generic.Put.GPutSum (l GHC.Generics.:+: r), Binrep.Generic.Put.GetConName (l GHC.Generics.:+: r)) => Binrep.Generic.Put.GPut (l GHC.Generics.:+: r)
- Binrep.Generic.Put: instance forall k (l :: k -> *) (r :: k -> *). (Binrep.Generic.Put.GPutSum l, Binrep.Generic.Put.GPutSum r) => Binrep.Generic.Put.GPutSum (l GHC.Generics.:+: r)
- Binrep.Generic.Put: instance forall k (r :: k -> *) (c :: GHC.Generics.Meta). (Binrep.Generic.Put.GPut r, GHC.Generics.Constructor c) => Binrep.Generic.Put.GPutSum (GHC.Generics.C1 c r)
- Binrep.Generic.Put: putGeneric :: (Generic a, GPut (Rep a), Put w) => Cfg w -> a -> Builder
- Binrep.Get: EBase :: EBase -> E
- Binrep.Get: EExpected :: ByteString -> ByteString -> EBase
- Binrep.Get: EExpectedByte :: Word8 -> Word8 -> EBase
- Binrep.Get: EFail :: EBase
- Binrep.Get: EFailNamed :: String -> EBase
- Binrep.Get: EFailParse :: String -> ByteString -> Word8 -> EBase
- Binrep.Get: EGeneric :: String -> EGeneric -> E
- Binrep.Get: EGenericField :: String -> Maybe String -> Natural -> E -> EGeneric
- Binrep.Get: EGenericSum :: EGenericSum -> EGeneric
- Binrep.Get: EGenericSumTag :: E -> EGenericSum
- Binrep.Get: EGenericSumTagNoMatch :: [String] -> Text -> EGenericSum
- Binrep.Get: ENoVoid :: EBase
- Binrep.Get: EOverlong :: BLenT -> BLenT -> EBase
- Binrep.Get: ERanOut :: Natural -> EBase
- Binrep.Get: class Get a
- Binrep.Get: class GetWith (r :: TYPE rep) a | a -> r
- Binrep.Get: cutEBase :: Getter a -> EBase -> Getter a
- Binrep.Get: data E
- Binrep.Get: data EBase
- Binrep.Get: data EGeneric
- Binrep.Get: data EGenericSum
- Binrep.Get: eBase :: EBase -> Getter a
- Binrep.Get: get :: Get a => Getter a
- Binrep.Get: getEBase :: Get a => EBase -> Getter a
- Binrep.Get: getEWrap :: Get a => (E -> E) -> Getter a
- Binrep.Get: getWith :: GetWith r a => r -> Getter a
- Binrep.Get: instance (Binrep.Get.Get a, Binrep.Get.Get b) => Binrep.Get.Get (a, b)
- Binrep.Get: instance Binrep.Get.Get Data.ByteString.Internal.ByteString
- Binrep.Get: instance Binrep.Get.Get Data.Void.Void
- Binrep.Get: instance Binrep.Get.Get GHC.Int.Int8
- Binrep.Get: instance Binrep.Get.Get GHC.Word.Word8
- Binrep.Get: instance Binrep.Get.Get a => Binrep.Get.Get [a]
- Binrep.Get: instance GHC.Classes.Eq Binrep.Get.E
- Binrep.Get: instance GHC.Classes.Eq Binrep.Get.EBase
- Binrep.Get: instance GHC.Classes.Eq Binrep.Get.EGeneric
- Binrep.Get: instance GHC.Classes.Eq Binrep.Get.EGenericSum
- Binrep.Get: instance GHC.Generics.Generic Binrep.Get.E
- Binrep.Get: instance GHC.Generics.Generic Binrep.Get.EBase
- Binrep.Get: instance GHC.Generics.Generic Binrep.Get.EGeneric
- Binrep.Get: instance GHC.Generics.Generic Binrep.Get.EGenericSum
- Binrep.Get: instance GHC.Show.Show Binrep.Get.E
- Binrep.Get: instance GHC.Show.Show Binrep.Get.EBase
- Binrep.Get: instance GHC.Show.Show Binrep.Get.EGeneric
- Binrep.Get: instance GHC.Show.Show Binrep.Get.EGenericSum
- Binrep.Get: runGet :: Get a => ByteString -> Either E (a, ByteString)
- Binrep.Get: runGetWith :: GetWith (r :: TYPE LiftedRep) a => r -> ByteString -> Either E (a, ByteString)
- Binrep.Get: runGetter :: Getter a -> ByteString -> Either E (a, ByteString)
- Binrep.Get: type Getter a = Parser E a
- Binrep.Put: class Put a
- Binrep.Put: class PutWith r a
- Binrep.Put: instance (Binrep.Put.Put a, Binrep.Put.Put b) => Binrep.Put.Put (a, b)
- Binrep.Put: instance Binrep.Put.Put Data.ByteString.Internal.ByteString
- Binrep.Put: instance Binrep.Put.Put Data.Void.Void
- Binrep.Put: instance Binrep.Put.Put GHC.Int.Int8
- Binrep.Put: instance Binrep.Put.Put GHC.Word.Word8
- Binrep.Put: instance Binrep.Put.Put a => Binrep.Put.Put [a]
- Binrep.Put: instance Binrep.Put.Put a => Binrep.Put.PutWith r [a]
- Binrep.Put: put :: Put a => a -> Builder
- Binrep.Put: putWith :: (PutWith r a, Put a) => r -> a -> Either String Builder
- Binrep.Put: putWithout :: Put a => a -> Either String Builder
- Binrep.Put: runBuilder :: Builder -> ByteString
- Binrep.Put: runPut :: Put a => a -> ByteString
- Binrep.Put: runPutWith :: PutWith r a => r -> a -> Either String ByteString
- Binrep.Put: type Builder = BuilderFor StrictByteStringBackend
- Binrep.Type.AsciiNat: AsciiNat :: Natural -> AsciiNat (base :: Natural)
- Binrep.Type.AsciiNat: [getAsciiNat] :: AsciiNat (base :: Natural) -> Natural
- Binrep.Type.AsciiNat: asciiBytesToNat :: (Word8 -> Maybe Word8) -> Natural -> ByteString -> Either Word8 Natural
- Binrep.Type.AsciiNat: asciiNatCompare :: AsciiNat b1 -> AsciiNat b2 -> Ordering
- Binrep.Type.AsciiNat: digits :: forall b a. (Integral a, Integral b) => a -> a -> NonEmpty b
- Binrep.Type.AsciiNat: instance Binrep.Get.Get (Binrep.Type.AsciiNat.AsciiNat 8)
- Binrep.Type.AsciiNat: instance Binrep.Put.Put (Binrep.Type.AsciiNat.AsciiNat 8)
- Binrep.Type.AsciiNat: instance GHC.Classes.Eq (Binrep.Type.AsciiNat.AsciiNat base)
- Binrep.Type.AsciiNat: instance GHC.Classes.Ord (Binrep.Type.AsciiNat.AsciiNat base)
- Binrep.Type.AsciiNat: instance GHC.Generics.Generic (Binrep.Type.AsciiNat.AsciiNat base)
- Binrep.Type.AsciiNat: instance GHC.Show.Show (Binrep.Type.AsciiNat.AsciiNat 10)
- Binrep.Type.AsciiNat: instance GHC.Show.Show (Binrep.Type.AsciiNat.AsciiNat 16)
- Binrep.Type.AsciiNat: instance GHC.Show.Show (Binrep.Type.AsciiNat.AsciiNat 2)
- Binrep.Type.AsciiNat: instance GHC.Show.Show (Binrep.Type.AsciiNat.AsciiNat 8)
- Binrep.Type.AsciiNat: instance GHC.TypeNats.KnownNat base => Binrep.BLen.BLen (Binrep.Type.AsciiNat.AsciiNat base)
- Binrep.Type.AsciiNat: instance GHC.TypeNats.KnownNat base => Data.Data.Data (Binrep.Type.AsciiNat.AsciiNat base)
- Binrep.Type.AsciiNat: natToAsciiBytes :: (Word8 -> Word8) -> Natural -> Natural -> Builder
- Binrep.Type.AsciiNat: newtype AsciiNat (base :: Natural)
- Binrep.Type.AsciiNat: octalFromAsciiDigit :: Word8 -> Maybe Word8
- Binrep.Type.Byte: class WriteReifiedBytes (ns :: [Natural])
- Binrep.Type.Byte: instance (Binrep.Type.Byte.ByteVal n, Binrep.Type.Byte.WriteReifiedBytes ns) => Binrep.Type.Byte.WriteReifiedBytes (n : ns)
- Binrep.Type.Byte: instance (n GHC.Types.~ Binrep.Type.Byte.Length ns, GHC.TypeNats.KnownNat n, Binrep.Type.Byte.WriteReifiedBytes ns) => Binrep.Type.Byte.ReifyBytes ns
- Binrep.Type.Byte: instance Binrep.Type.Byte.WriteReifiedBytes '[]
- Binrep.Type.Byte: type family Length (a :: [k]) :: Natural
- Binrep.Type.Byte: writeReifiedBytes :: WriteReifiedBytes ns => Addr# -> IO ()
- Binrep.Type.ByteString: C :: Rep
- Binrep.Type.ByteString: Pascal :: ISize -> Endianness -> Rep
- Binrep.Type.ByteString: data Rep
- Binrep.Type.ByteString: getCString :: Getter ByteString
- Binrep.Type.ByteString: instance (irep GHC.Types.~ Binrep.Type.Int.IRep 'Binrep.Type.Int.U size, GHC.Enum.Bounded irep, GHC.Real.Integral irep, GHC.Show.Show irep, Data.Typeable.Internal.Typeable size, Data.Typeable.Internal.Typeable e) => Refined.Predicate ('Binrep.Type.ByteString.Pascal size e) Data.ByteString.Internal.ByteString
- Binrep.Type.ByteString: instance (itype GHC.Types.~ Binrep.Type.Int.I 'Binrep.Type.Int.U size end, irep GHC.Types.~ Binrep.Type.Int.IRep 'Binrep.Type.Int.U size, Binrep.Put.Put itype, GHC.Num.Num irep) => Binrep.Put.Put (Binrep.Type.ByteString.AsByteString ('Binrep.Type.ByteString.Pascal size end))
- Binrep.Type.ByteString: instance (itype GHC.Types.~ Binrep.Type.Int.I 'Binrep.Type.Int.U size end, irep GHC.Types.~ Binrep.Type.Int.IRep 'Binrep.Type.Int.U size, GHC.Real.Integral irep, Binrep.Get.Get itype) => Binrep.Get.Get (Binrep.Type.ByteString.AsByteString ('Binrep.Type.ByteString.Pascal size end))
- Binrep.Type.ByteString: instance (itype GHC.Types.~ Binrep.Type.Int.I 'Binrep.Type.Int.U size end, irep GHC.Types.~ Binrep.Type.Int.IRep 'Binrep.Type.Int.U size, GHC.TypeNats.KnownNat (Binrep.BLen.CBLen irep)) => Binrep.BLen.BLen (Binrep.Type.ByteString.AsByteString ('Binrep.Type.ByteString.Pascal size end))
- Binrep.Type.ByteString: instance Binrep.BLen.BLen (Binrep.Type.ByteString.AsByteString 'Binrep.Type.ByteString.C)
- Binrep.Type.ByteString: instance Binrep.Get.Get (Binrep.Type.ByteString.AsByteString 'Binrep.Type.ByteString.C)
- Binrep.Type.ByteString: instance Binrep.Put.Put (Binrep.Type.ByteString.AsByteString 'Binrep.Type.ByteString.C)
- Binrep.Type.ByteString: instance Data.Data.Data Binrep.Type.ByteString.Rep
- Binrep.Type.ByteString: instance GHC.Classes.Eq Binrep.Type.ByteString.Rep
- Binrep.Type.ByteString: instance GHC.Generics.Generic Binrep.Type.ByteString.Rep
- Binrep.Type.ByteString: instance GHC.Show.Show Binrep.Type.ByteString.Rep
- Binrep.Type.ByteString: instance Refined.Predicate 'Binrep.Type.ByteString.C Data.ByteString.Internal.ByteString
- Binrep.Type.ByteString: putCString :: ByteString -> Builder
- Binrep.Type.ByteString: type AsByteString (rep :: Rep) = Refined rep ByteString
- Binrep.Type.Int: I1 :: ISize
- Binrep.Type.Int: I2 :: ISize
- Binrep.Type.Int: I4 :: ISize
- Binrep.Type.Int: I8 :: ISize
- Binrep.Type.Int: S :: ISign
- Binrep.Type.Int: [getI] :: I (sign :: ISign) (size :: ISize) (e :: Endianness) -> IRep sign size
- Binrep.Type.Int: data ISize
- Binrep.Type.Int: instance (Data.Data.Data (Binrep.Type.Int.IRep sign size), Data.Typeable.Internal.Typeable sign, Data.Typeable.Internal.Typeable size, Data.Typeable.Internal.Typeable e) => Data.Data.Data (Binrep.Type.Int.I sign size e)
- Binrep.Type.Int: instance (irep GHC.Types.~ Binrep.Type.Int.IRep 'Binrep.Type.Int.S size, GHC.Real.Integral irep) => Strongweak.Weaken.Weaken (Binrep.Type.Int.I 'Binrep.Type.Int.S size end)
- Binrep.Type.Int: instance (irep GHC.Types.~ Binrep.Type.Int.IRep 'Binrep.Type.Int.S size, GHC.Real.Integral irep, GHC.Enum.Bounded irep, GHC.Show.Show irep, Data.Typeable.Internal.Typeable size, Data.Typeable.Internal.Typeable end) => Strongweak.Strengthen.Strengthen (Binrep.Type.Int.I 'Binrep.Type.Int.S size end)
- Binrep.Type.Int: instance (irep GHC.Types.~ Binrep.Type.Int.IRep 'Binrep.Type.Int.U size, GHC.Real.Integral irep) => Strongweak.Weaken.Weaken (Binrep.Type.Int.I 'Binrep.Type.Int.U size end)
- Binrep.Type.Int: instance (irep GHC.Types.~ Binrep.Type.Int.IRep 'Binrep.Type.Int.U size, GHC.Real.Integral irep, GHC.Enum.Bounded irep, GHC.Show.Show irep, Data.Typeable.Internal.Typeable size, Data.Typeable.Internal.Typeable end) => Strongweak.Strengthen.Strengthen (Binrep.Type.Int.I 'Binrep.Type.Int.U size end)
- Binrep.Type.Int: instance Binrep.Get.Get (Binrep.Type.Int.I 'Binrep.Type.Int.S 'Binrep.Type.Int.I1 e)
- Binrep.Type.Int: instance Binrep.Get.Get (Binrep.Type.Int.I 'Binrep.Type.Int.S 'Binrep.Type.Int.I2 'Binrep.Type.Common.BE)
- Binrep.Type.Int: instance Binrep.Get.Get (Binrep.Type.Int.I 'Binrep.Type.Int.S 'Binrep.Type.Int.I2 'Binrep.Type.Common.LE)
- Binrep.Type.Int: instance Binrep.Get.Get (Binrep.Type.Int.I 'Binrep.Type.Int.S 'Binrep.Type.Int.I4 'Binrep.Type.Common.BE)
- Binrep.Type.Int: instance Binrep.Get.Get (Binrep.Type.Int.I 'Binrep.Type.Int.S 'Binrep.Type.Int.I4 'Binrep.Type.Common.LE)
- Binrep.Type.Int: instance Binrep.Get.Get (Binrep.Type.Int.I 'Binrep.Type.Int.S 'Binrep.Type.Int.I8 'Binrep.Type.Common.BE)
- Binrep.Type.Int: instance Binrep.Get.Get (Binrep.Type.Int.I 'Binrep.Type.Int.S 'Binrep.Type.Int.I8 'Binrep.Type.Common.LE)
- Binrep.Type.Int: instance Binrep.Get.Get (Binrep.Type.Int.I 'Binrep.Type.Int.U 'Binrep.Type.Int.I1 e)
- Binrep.Type.Int: instance Binrep.Get.Get (Binrep.Type.Int.I 'Binrep.Type.Int.U 'Binrep.Type.Int.I2 'Binrep.Type.Common.BE)
- Binrep.Type.Int: instance Binrep.Get.Get (Binrep.Type.Int.I 'Binrep.Type.Int.U 'Binrep.Type.Int.I2 'Binrep.Type.Common.LE)
- Binrep.Type.Int: instance Binrep.Get.Get (Binrep.Type.Int.I 'Binrep.Type.Int.U 'Binrep.Type.Int.I4 'Binrep.Type.Common.BE)
- Binrep.Type.Int: instance Binrep.Get.Get (Binrep.Type.Int.I 'Binrep.Type.Int.U 'Binrep.Type.Int.I4 'Binrep.Type.Common.LE)
- Binrep.Type.Int: instance Binrep.Get.Get (Binrep.Type.Int.I 'Binrep.Type.Int.U 'Binrep.Type.Int.I8 'Binrep.Type.Common.BE)
- Binrep.Type.Int: instance Binrep.Get.Get (Binrep.Type.Int.I 'Binrep.Type.Int.U 'Binrep.Type.Int.I8 'Binrep.Type.Common.LE)
- Binrep.Type.Int: instance Binrep.Put.Put (Binrep.Type.Int.I 'Binrep.Type.Int.S 'Binrep.Type.Int.I1 e)
- Binrep.Type.Int: instance Binrep.Put.Put (Binrep.Type.Int.I 'Binrep.Type.Int.S 'Binrep.Type.Int.I2 'Binrep.Type.Common.BE)
- Binrep.Type.Int: instance Binrep.Put.Put (Binrep.Type.Int.I 'Binrep.Type.Int.S 'Binrep.Type.Int.I2 'Binrep.Type.Common.LE)
- Binrep.Type.Int: instance Binrep.Put.Put (Binrep.Type.Int.I 'Binrep.Type.Int.S 'Binrep.Type.Int.I4 'Binrep.Type.Common.BE)
- Binrep.Type.Int: instance Binrep.Put.Put (Binrep.Type.Int.I 'Binrep.Type.Int.S 'Binrep.Type.Int.I4 'Binrep.Type.Common.LE)
- Binrep.Type.Int: instance Binrep.Put.Put (Binrep.Type.Int.I 'Binrep.Type.Int.S 'Binrep.Type.Int.I8 'Binrep.Type.Common.BE)
- Binrep.Type.Int: instance Binrep.Put.Put (Binrep.Type.Int.I 'Binrep.Type.Int.S 'Binrep.Type.Int.I8 'Binrep.Type.Common.LE)
- Binrep.Type.Int: instance Binrep.Put.Put (Binrep.Type.Int.I 'Binrep.Type.Int.U 'Binrep.Type.Int.I1 e)
- Binrep.Type.Int: instance Binrep.Put.Put (Binrep.Type.Int.I 'Binrep.Type.Int.U 'Binrep.Type.Int.I2 'Binrep.Type.Common.BE)
- Binrep.Type.Int: instance Binrep.Put.Put (Binrep.Type.Int.I 'Binrep.Type.Int.U 'Binrep.Type.Int.I2 'Binrep.Type.Common.LE)
- Binrep.Type.Int: instance Binrep.Put.Put (Binrep.Type.Int.I 'Binrep.Type.Int.U 'Binrep.Type.Int.I4 'Binrep.Type.Common.BE)
- Binrep.Type.Int: instance Binrep.Put.Put (Binrep.Type.Int.I 'Binrep.Type.Int.U 'Binrep.Type.Int.I4 'Binrep.Type.Common.LE)
- Binrep.Type.Int: instance Binrep.Put.Put (Binrep.Type.Int.I 'Binrep.Type.Int.U 'Binrep.Type.Int.I8 'Binrep.Type.Common.BE)
- Binrep.Type.Int: instance Binrep.Put.Put (Binrep.Type.Int.I 'Binrep.Type.Int.U 'Binrep.Type.Int.I8 'Binrep.Type.Common.LE)
- Binrep.Type.Int: instance Data.Aeson.Types.FromJSON.FromJSON (Binrep.Type.Int.IRep sign size) => Data.Aeson.Types.FromJSON.FromJSON (Binrep.Type.Int.I sign size e)
- Binrep.Type.Int: instance Data.Aeson.Types.ToJSON.ToJSON (Binrep.Type.Int.IRep sign size) => Data.Aeson.Types.ToJSON.ToJSON (Binrep.Type.Int.I sign size e)
- Binrep.Type.Int: instance Data.Data.Data Binrep.Type.Int.ISize
- Binrep.Type.Int: instance GHC.Classes.Eq (Binrep.Type.Int.IRep sign size) => GHC.Classes.Eq (Binrep.Type.Int.I sign size e)
- Binrep.Type.Int: instance GHC.Classes.Eq Binrep.Type.Int.ISize
- Binrep.Type.Int: instance GHC.Classes.Ord (Binrep.Type.Int.IRep sign size) => GHC.Classes.Ord (Binrep.Type.Int.I sign size e)
- Binrep.Type.Int: instance GHC.Enum.Bounded (Binrep.Type.Int.IRep sign size) => GHC.Enum.Bounded (Binrep.Type.Int.I sign size e)
- Binrep.Type.Int: instance GHC.Enum.Enum (Binrep.Type.Int.IRep sign size) => GHC.Enum.Enum (Binrep.Type.Int.I sign size e)
- Binrep.Type.Int: instance GHC.Generics.Generic (Binrep.Type.Int.I sign size e)
- Binrep.Type.Int: instance GHC.Generics.Generic Binrep.Type.Int.ISize
- Binrep.Type.Int: instance GHC.Num.Num (Binrep.Type.Int.IRep sign size) => GHC.Num.Num (Binrep.Type.Int.I sign size e)
- Binrep.Type.Int: instance GHC.Real.Integral (Binrep.Type.Int.IRep sign size) => GHC.Real.Integral (Binrep.Type.Int.I sign size e)
- Binrep.Type.Int: instance GHC.Real.Real (Binrep.Type.Int.IRep sign size) => GHC.Real.Real (Binrep.Type.Int.I sign size e)
- Binrep.Type.Int: instance GHC.Show.Show (Binrep.Type.Int.IRep sign size) => GHC.Show.Show (Binrep.Type.Int.I sign size e)
- Binrep.Type.Int: instance GHC.Show.Show Binrep.Type.Int.ISize
- Binrep.Type.Int: instance GHC.TypeNats.KnownNat (Binrep.BLen.CBLen (Binrep.Type.Int.I sign size end)) => Binrep.BLen.BLen (Binrep.Type.Int.I sign size end)
- Binrep.Type.Int: newtype I (sign :: ISign) (size :: ISize) (e :: Endianness)
- Binrep.Type.LenPfx: LenPfx :: Vector n a -> LenPfx (size :: ISize) (end :: Endianness) a
- Binrep.Type.LenPfx: [unLenPfx] :: LenPfx (size :: ISize) (end :: Endianness) a -> Vector n a
- Binrep.Type.LenPfx: asLenPfx :: forall size end n a irep. (irep ~ IRep 'U size, KnownNat n, KnownNat (MaxBound irep)) => Vector n a -> Maybe (LenPfx size end a)
- Binrep.Type.LenPfx: data LenPfx (size :: ISize) (end :: Endianness) a
- Binrep.Type.LenPfx: getLenPfx :: forall size end a itype irep. (itype ~ I 'U size end, irep ~ IRep 'U size, Get itype, Integral irep, KnownNat (MaxBound irep)) => Getter a -> Getter (LenPfx size end a)
- Binrep.Type.LenPfx: instance (Binrep.BLen.BLen a, itype GHC.Types.~ Binrep.Type.Int.I 'Binrep.Type.Int.U size end, GHC.TypeNats.KnownNat (Binrep.BLen.CBLen itype)) => Binrep.BLen.BLen (Binrep.Type.LenPfx.LenPfx size end a)
- Binrep.Type.LenPfx: instance (GHC.TypeNats.KnownNat (Binrep.Type.Int.MaxBound (Binrep.Type.Int.IRep 'Binrep.Type.Int.U size)), GHC.Show.Show a, Data.Typeable.Internal.Typeable a, Data.Typeable.Internal.Typeable size, Data.Typeable.Internal.Typeable end) => Strongweak.Strengthen.Strengthen (Binrep.Type.LenPfx.LenPfx size end a)
- Binrep.Type.LenPfx: instance (itype GHC.Types.~ Binrep.Type.Int.I 'Binrep.Type.Int.U size end, irep GHC.Types.~ Binrep.Type.Int.IRep 'Binrep.Type.Int.U size, Binrep.Get.Get itype, GHC.Real.Integral irep, Binrep.Get.Get a, GHC.TypeNats.KnownNat (Binrep.Type.Int.MaxBound irep)) => Binrep.Get.Get (Binrep.Type.LenPfx.LenPfx size end a)
- Binrep.Type.LenPfx: instance (itype GHC.Types.~ Binrep.Type.Int.I 'Binrep.Type.Int.U size end, irep GHC.Types.~ Binrep.Type.Int.IRep 'Binrep.Type.Int.U size, Binrep.Put.Put a, Binrep.Put.Put itype, GHC.Num.Num irep) => Binrep.Put.Put (Binrep.Type.LenPfx.LenPfx size end a)
- Binrep.Type.LenPfx: instance GHC.Classes.Eq a => GHC.Classes.Eq (Binrep.Type.LenPfx.LenPfx size end a)
- Binrep.Type.LenPfx: instance GHC.Generics.Generic (Binrep.Type.LenPfx.LenPfx size end a)
- Binrep.Type.LenPfx: instance GHC.Show.Show a => GHC.Show.Show (Binrep.Type.LenPfx.LenPfx size end a)
- Binrep.Type.LenPfx: instance Strongweak.Weaken.Weaken (Binrep.Type.LenPfx.LenPfx size end a)
- Binrep.Type.LenPfx: lenPfxFromList :: forall size end a irep. (irep ~ IRep 'U size, KnownNat (MaxBound irep)) => [a] -> Maybe (LenPfx size end a)
- Binrep.Type.LenPfx: lenPfxSize :: Num (IRep 'U size) => LenPfx size end a -> I 'U size end
- Binrep.Type.LenPfx: vsEq :: forall a n m. (Eq a, KnownNat n, KnownNat m) => Vector n a -> Vector m a -> Bool
- Binrep.Type.Magic: instance forall k (a :: k). GHC.TypeNats.KnownNat (Binrep.Type.Byte.Length (Binrep.Type.Magic.MagicBytes a)) => Binrep.BLen.BLen (Binrep.Type.Magic.Magic a)
- Binrep.Type.Magic: instance forall k (bs :: [GHC.Num.Natural.Natural]) (a :: k). (bs GHC.Types.~ Binrep.Type.Magic.MagicBytes a, Binrep.Type.Byte.ReifyBytes bs) => Binrep.Get.Get (Binrep.Type.Magic.Magic a)
- Binrep.Type.Magic: 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.Put (Binrep.Type.Magic.Magic a)
- Binrep.Type.Magic.UTF8: MagicUTF8 :: MagicUTF8 (str :: Symbol)
- Binrep.Type.Magic.UTF8: data MagicUTF8 (str :: Symbol)
- Binrep.Type.Magic.UTF8: encodeStringUtf8 :: String -> ByteString
- Binrep.Type.Magic.UTF8: instance GHC.Show.Show (Binrep.Type.Magic.UTF8.MagicUTF8 str)
- Binrep.Type.Magic.UTF8: instance GHC.TypeLits.KnownSymbol str => Binrep.BLen.BLen (Binrep.Type.Magic.UTF8.MagicUTF8 str)
- Binrep.Type.Magic.UTF8: instance GHC.TypeLits.KnownSymbol str => Binrep.Get.Get (Binrep.Type.Magic.UTF8.MagicUTF8 str)
- Binrep.Type.Magic.UTF8: instance GHC.TypeLits.KnownSymbol str => Binrep.Put.Put (Binrep.Type.Magic.UTF8.MagicUTF8 str)
- Binrep.Type.Magic.UTF8: symVal :: forall str. KnownSymbol str => String
- Binrep.Type.NullPadded: getNNulls :: BLenT -> Parser E ()
- Binrep.Type.NullPadded: instance (Binrep.BLen.BLen a, GHC.TypeNats.KnownNat n) => Refined.Predicate (Binrep.Type.NullPadded.NullPad n) a
- Binrep.Type.NullPadded: instance (Binrep.Get.Get a, Binrep.BLen.BLen a, GHC.TypeNats.KnownNat n) => Binrep.Get.Get (Binrep.Type.NullPadded.NullPadded n a)
- Binrep.Type.NullPadded: instance (Binrep.Put.Put a, Binrep.BLen.BLen a, GHC.TypeNats.KnownNat n) => Binrep.Put.Put (Binrep.Type.NullPadded.NullPadded n a)
- Binrep.Type.NullPadded: instance GHC.TypeNats.KnownNat n => Binrep.BLen.BLen (Binrep.Type.NullPadded.NullPadded n a)
- Binrep.Type.Sized: instance (Binrep.BLen.BLen a, GHC.TypeNats.KnownNat n) => Refined.Predicate (Binrep.Type.Sized.Size n) a
- Binrep.Type.Sized: instance (Binrep.Get.Get a, GHC.TypeNats.KnownNat n) => Binrep.Get.Get (Binrep.Type.Sized.Sized n a)
- Binrep.Type.Sized: instance Binrep.Put.Put a => Binrep.Put.Put (Binrep.Type.Sized.Sized n a)
- Binrep.Type.Sized: instance GHC.TypeNats.KnownNat n => Binrep.BLen.BLen (Binrep.Type.Sized.Sized n a)
- Binrep.Type.Text: ASCII :: Encoding
- Binrep.Type.Text: SJIS :: Encoding
- Binrep.Type.Text: UTF16 :: Endianness -> Encoding
- Binrep.Type.Text: UTF32 :: Endianness -> Encoding
- Binrep.Type.Text: UTF8 :: Encoding
- Binrep.Type.Text: data Encoding
- Binrep.Type.Text: decodeViaTextICU :: String -> ByteString -> IO (Either String Text)
- Binrep.Type.Text: instance Binrep.Type.Text.Decode 'Binrep.Type.Text.SJIS
- Binrep.Type.Text: instance Binrep.Type.Text.Decode 'Binrep.Type.Text.UTF8
- Binrep.Type.Text: instance Binrep.Type.Text.Decode ('Binrep.Type.Text.UTF16 'Binrep.Type.Common.BE)
- Binrep.Type.Text: instance Binrep.Type.Text.Decode ('Binrep.Type.Text.UTF16 'Binrep.Type.Common.LE)
- Binrep.Type.Text: instance Binrep.Type.Text.Decode ('Binrep.Type.Text.UTF32 'Binrep.Type.Common.BE)
- Binrep.Type.Text: instance Binrep.Type.Text.Decode ('Binrep.Type.Text.UTF32 'Binrep.Type.Common.LE)
- Binrep.Type.Text: instance Binrep.Type.Text.Encode 'Binrep.Type.Text.ASCII
- Binrep.Type.Text: instance Binrep.Type.Text.Encode 'Binrep.Type.Text.SJIS
- Binrep.Type.Text: instance Binrep.Type.Text.Encode 'Binrep.Type.Text.UTF8
- Binrep.Type.Text: instance Binrep.Type.Text.Encode ('Binrep.Type.Text.UTF16 'Binrep.Type.Common.BE)
- Binrep.Type.Text: instance Binrep.Type.Text.Encode ('Binrep.Type.Text.UTF16 'Binrep.Type.Common.LE)
- Binrep.Type.Text: instance Binrep.Type.Text.Encode ('Binrep.Type.Text.UTF32 'Binrep.Type.Common.BE)
- Binrep.Type.Text: instance Binrep.Type.Text.Encode ('Binrep.Type.Text.UTF32 'Binrep.Type.Common.LE)
- Binrep.Type.Text: instance Data.Data.Data Binrep.Type.Text.Encoding
- Binrep.Type.Text: instance Data.Typeable.Internal.Typeable e => Refined.Predicate ('Binrep.Type.Text.UTF16 e) Data.Text.Internal.Text
- Binrep.Type.Text: instance Data.Typeable.Internal.Typeable e => Refined.Predicate ('Binrep.Type.Text.UTF32 e) Data.Text.Internal.Text
- Binrep.Type.Text: instance GHC.Classes.Eq Binrep.Type.Text.Encoding
- Binrep.Type.Text: instance GHC.Generics.Generic Binrep.Type.Text.Encoding
- Binrep.Type.Text: instance GHC.Show.Show Binrep.Type.Text.Encoding
- Binrep.Type.Text: instance Refined.Predicate 'Binrep.Type.Text.ASCII Data.Text.Internal.Text
- Binrep.Type.Text: instance Refined.Predicate 'Binrep.Type.Text.SJIS Data.Text.Internal.Text
- Binrep.Type.Text: instance Refined.Predicate 'Binrep.Type.Text.UTF8 Data.Text.Internal.Text
- Binrep.Type.Varint: Bijective :: Encoding
- Binrep.Type.Varint: OffContinues :: ContinuationBitBehaviour
- Binrep.Type.Varint: OnContinues :: ContinuationBitBehaviour
- Binrep.Type.Varint: Redundant :: Encoding
- Binrep.Type.Varint: Varnat :: i -> Varnat (enc :: Encoding) (cont :: ContinuationBitBehaviour) (e :: Endianness) i
- Binrep.Type.Varint: [getVarnat] :: Varnat (enc :: Encoding) (cont :: ContinuationBitBehaviour) (e :: Endianness) i -> i
- Binrep.Type.Varint: class VarintContinuation (cont :: ContinuationBitBehaviour)
- Binrep.Type.Varint: data ContinuationBitBehaviour
- Binrep.Type.Varint: data Encoding
- Binrep.Type.Varint: instance (Binrep.Type.Varint.VarintContinuation cont, GHC.Real.Integral i, GHC.Bits.Bits i) => Binrep.Get.Get (Binrep.Type.Varint.Varnat 'Binrep.Type.Varint.Bijective cont 'Binrep.Type.Common.BE i)
- Binrep.Type.Varint: instance (Binrep.Type.Varint.VarintContinuation cont, GHC.Real.Integral i, GHC.Bits.Bits i) => Binrep.Get.Get (Binrep.Type.Varint.Varnat 'Binrep.Type.Varint.Bijective cont 'Binrep.Type.Common.LE i)
- Binrep.Type.Varint: instance (Binrep.Type.Varint.VarintContinuation cont, GHC.Real.Integral i, GHC.Bits.Bits i) => Binrep.Get.Get (Binrep.Type.Varint.Varnat 'Binrep.Type.Varint.Redundant cont 'Binrep.Type.Common.BE i)
- Binrep.Type.Varint: instance (Binrep.Type.Varint.VarintContinuation cont, GHC.Real.Integral i, GHC.Bits.Bits i) => Binrep.Get.Get (Binrep.Type.Varint.Varnat 'Binrep.Type.Varint.Redundant cont 'Binrep.Type.Common.LE i)
- Binrep.Type.Varint: instance (Binrep.Type.Varint.VarintContinuation cont, GHC.Real.Integral i, GHC.Bits.Bits i) => Binrep.Put.Put (Binrep.Type.Varint.Varnat 'Binrep.Type.Varint.Redundant cont 'Binrep.Type.Common.BE i)
- Binrep.Type.Varint: instance (Binrep.Type.Varint.VarintContinuation cont, GHC.Real.Integral i, GHC.Bits.Bits i) => Binrep.Put.Put (Binrep.Type.Varint.Varnat 'Binrep.Type.Varint.Redundant cont 'Binrep.Type.Common.LE i)
- Binrep.Type.Varint: instance Binrep.Type.Varint.VarintContinuation 'Binrep.Type.Varint.OffContinues
- Binrep.Type.Varint: instance Binrep.Type.Varint.VarintContinuation 'Binrep.Type.Varint.OnContinues
- Binrep.Type.Varint: instance GHC.Classes.Eq i => GHC.Classes.Eq (Binrep.Type.Varint.Varnat enc cont e i)
- Binrep.Type.Varint: instance GHC.Classes.Ord i => GHC.Classes.Ord (Binrep.Type.Varint.Varnat enc cont e i)
- Binrep.Type.Varint: instance GHC.Enum.Enum i => GHC.Enum.Enum (Binrep.Type.Varint.Varnat enc cont e i)
- Binrep.Type.Varint: instance GHC.Num.Num i => GHC.Num.Num (Binrep.Type.Varint.Varnat enc cont e i)
- Binrep.Type.Varint: instance GHC.Real.Integral i => GHC.Real.Integral (Binrep.Type.Varint.Varnat enc cont e i)
- Binrep.Type.Varint: instance GHC.Real.Real i => GHC.Real.Real (Binrep.Type.Varint.Varnat enc cont e i)
- Binrep.Type.Varint: instance GHC.Show.Show i => GHC.Show.Show (Binrep.Type.Varint.Varnat enc cont e i)
- Binrep.Type.Varint: newtype Varnat (enc :: Encoding) (cont :: ContinuationBitBehaviour) (e :: Endianness) i
- Binrep.Type.Varint: setVarintCont :: forall cont a. VarintContinuation cont => Bits a => a -> Int -> a
- Binrep.Type.Varint: testVarintCont :: forall cont a. VarintContinuation cont => Bits a => a -> Int -> Bool
- Binrep.Type.Varint: varintContinue :: VarintContinuation cont => Bool
- Binrep.Type.Vector: getVector :: KnownNat n => Getter a -> Getter (Vector n a)
- Binrep.Type.Vector: instance (Binrep.Get.Get a, GHC.TypeNats.KnownNat n) => Binrep.Get.Get (Data.Vector.Sized.Vector n a)
- Binrep.Type.Vector: instance Binrep.BLen.BLen a => Binrep.BLen.BLen (Data.Vector.Sized.Vector n a)
- Binrep.Type.Vector: instance Binrep.Put.Put a => Binrep.Put.Put (Data.Vector.Sized.Vector n a)
- Haskpatch.Format.Bps: Bps :: SW s (Magic "BPS1") -> SW s (BpsVarint i) -> SW s (BpsVarint i) -> BpsMeta a -> [BpsCommand] -> BpsFooter s -> Bps (s :: Strength) i a
- Haskpatch.Format.Bps: BpsCommandSourceCopy :: BpsCommand
- Haskpatch.Format.Bps: BpsCommandSourceRead :: BpsCommand
- Haskpatch.Format.Bps: BpsCommandTargetCopy :: BpsCommand
- Haskpatch.Format.Bps: BpsCommandTargetRead :: BpsCommand
- Haskpatch.Format.Bps: BpsFooter :: SW s (Sized 4 ByteString) -> SW s (Sized 4 ByteString) -> SW s (Sized 4 ByteString) -> BpsFooter (s :: Strength)
- Haskpatch.Format.Bps: [bpsCommands] :: Bps (s :: Strength) i a -> [BpsCommand]
- Haskpatch.Format.Bps: [bpsFooterPatchChecksum] :: BpsFooter (s :: Strength) -> SW s (Sized 4 ByteString)
- Haskpatch.Format.Bps: [bpsFooterSourceChecksum] :: BpsFooter (s :: Strength) -> SW s (Sized 4 ByteString)
- Haskpatch.Format.Bps: [bpsFooterTargetChecksum] :: BpsFooter (s :: Strength) -> SW s (Sized 4 ByteString)
- Haskpatch.Format.Bps: [bpsFooter] :: Bps (s :: Strength) i a -> BpsFooter s
- Haskpatch.Format.Bps: [bpsMagic] :: Bps (s :: Strength) i a -> SW s (Magic "BPS1")
- Haskpatch.Format.Bps: [bpsMetadata] :: Bps (s :: Strength) i a -> BpsMeta a
- Haskpatch.Format.Bps: [bpsSourceSize] :: Bps (s :: Strength) i a -> SW s (BpsVarint i)
- Haskpatch.Format.Bps: [bpsTargetSize] :: Bps (s :: Strength) i a -> SW s (BpsVarint i)
- Haskpatch.Format.Bps: data Bps (s :: Strength) i a
- Haskpatch.Format.Bps: data BpsCommand
- Haskpatch.Format.Bps: data BpsFooter (s :: Strength)
- Haskpatch.Format.Bps: data BpsMeta a
- Haskpatch.Format.Bps: type BpsVarint = Varnat 'Bijective 'OffContinues 'LE
- Haskpatch.Format.Vcdiff: Delta :: SW s (Magic '[0x00]) -> ByteString -> [InstrCode] -> ByteString -> Delta (s :: Strength)
- Haskpatch.Format.Vcdiff: Header :: SW s (Magic '[0xD6, 0xC3, 0xC4, 0x00]) -> SW s (Magic '[0x00]) -> Header (s :: Strength)
- Haskpatch.Format.Vcdiff: Instr0Noop :: Instr
- Haskpatch.Format.Vcdiff: Instr1Add :: Instr
- Haskpatch.Format.Vcdiff: Instr2Run :: Instr
- Haskpatch.Format.Vcdiff: Instr3Copy :: Instr
- Haskpatch.Format.Vcdiff: InstrCode :: InstrTriple -> InstrTriple -> InstrCode
- Haskpatch.Format.Vcdiff: InstrTriple :: Instr -> Word8 -> Word8 -> InstrTriple
- Haskpatch.Format.Vcdiff: Vcdiff :: Header s -> Vcdiff (s :: Strength)
- Haskpatch.Format.Vcdiff: Window :: SW s (Magic '[0x00]) -> Delta s -> Window (s :: Strength)
- Haskpatch.Format.Vcdiff: [deltaAddRun] :: Delta (s :: Strength) -> ByteString
- Haskpatch.Format.Vcdiff: [deltaCopy] :: Delta (s :: Strength) -> ByteString
- Haskpatch.Format.Vcdiff: [deltaIndicator] :: Delta (s :: Strength) -> SW s (Magic '[0x00])
- Haskpatch.Format.Vcdiff: [deltaInstrs] :: Delta (s :: Strength) -> [InstrCode]
- Haskpatch.Format.Vcdiff: [headerIndicator] :: Header (s :: Strength) -> SW s (Magic '[0x00])
- Haskpatch.Format.Vcdiff: [headerMagic] :: Header (s :: Strength) -> SW s (Magic '[0xD6, 0xC3, 0xC4, 0x00])
- Haskpatch.Format.Vcdiff: [instrCodeTriple1] :: InstrCode -> InstrTriple
- Haskpatch.Format.Vcdiff: [instrCodeTriple2] :: InstrCode -> InstrTriple
- Haskpatch.Format.Vcdiff: [instrTripleInstr] :: InstrTriple -> Instr
- Haskpatch.Format.Vcdiff: [instrTripleMode] :: InstrTriple -> Word8
- Haskpatch.Format.Vcdiff: [instrTripleSize] :: InstrTriple -> Word8
- Haskpatch.Format.Vcdiff: [vcdiffHeader] :: Vcdiff (s :: Strength) -> Header s
- Haskpatch.Format.Vcdiff: [windowDelta] :: Window (s :: Strength) -> Delta s
- Haskpatch.Format.Vcdiff: [windowIndicator] :: Window (s :: Strength) -> SW s (Magic '[0x00])
- Haskpatch.Format.Vcdiff: data Delta (s :: Strength)
- Haskpatch.Format.Vcdiff: data Header (s :: Strength)
- Haskpatch.Format.Vcdiff: data Instr
- Haskpatch.Format.Vcdiff: data InstrCode
- Haskpatch.Format.Vcdiff: data InstrTriple
- Haskpatch.Format.Vcdiff: data Vcdiff (s :: Strength)
- Haskpatch.Format.Vcdiff: data Window (s :: Strength)
- Haskpatch.Format.Vcdiff: type VcdiffVarint = Varnat 'Redundant 'OnContinues 'BE Natural
- Util.Generic: conName' :: forall c. Constructor c => String
- Util.Generic: datatypeName' :: forall d. Datatype d => String
- Util.Generic: selName' :: forall s. Selector s => String
- Util.Generic: selName'' :: forall s. Selector s => Maybe String
+ Binrep.BLen.Simple: BLen' :: a -> BLen' a
+ Binrep.BLen.Simple: CBLenly :: a -> CBLenly a
+ Binrep.BLen.Simple: [getBLen'] :: BLen' a -> a
+ Binrep.BLen.Simple: [unCBLenly] :: CBLenly a -> a
+ Binrep.BLen.Simple: blen :: BLen a => a -> Int
+ Binrep.BLen.Simple: 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
+ Binrep.BLen.Simple: 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
+ Binrep.BLen.Simple: cblen :: forall a n. (n ~ CBLen a, KnownNat n) => Int
+ Binrep.BLen.Simple: class BLen a
+ Binrep.BLen.Simple: instance (Binrep.BLen.Simple.BLen l, Binrep.BLen.Simple.BLen r) => Binrep.BLen.Simple.BLen (l, r)
+ Binrep.BLen.Simple: instance (TypeError ...) => Binrep.BLen.Simple.BLen (Data.Either.Either a b)
+ Binrep.BLen.Simple: instance (TypeError ...) => Binrep.BLen.Simple.BLen Data.Void.Void
+ Binrep.BLen.Simple: instance Binrep.BLen.Simple.BLen ()
+ Binrep.BLen.Simple: instance Binrep.BLen.Simple.BLen Bytezap.Write
+ Binrep.BLen.Simple: instance Binrep.BLen.Simple.BLen Data.ByteString.Internal.Type.ByteString
+ Binrep.BLen.Simple: instance Binrep.BLen.Simple.BLen GHC.Int.Int16
+ Binrep.BLen.Simple: instance Binrep.BLen.Simple.BLen GHC.Int.Int32
+ Binrep.BLen.Simple: instance Binrep.BLen.Simple.BLen GHC.Int.Int64
+ Binrep.BLen.Simple: instance Binrep.BLen.Simple.BLen GHC.Int.Int8
+ Binrep.BLen.Simple: instance Binrep.BLen.Simple.BLen GHC.Word.Word16
+ Binrep.BLen.Simple: instance Binrep.BLen.Simple.BLen GHC.Word.Word32
+ Binrep.BLen.Simple: instance Binrep.BLen.Simple.BLen GHC.Word.Word64
+ Binrep.BLen.Simple: instance Binrep.BLen.Simple.BLen GHC.Word.Word8
+ Binrep.BLen.Simple: instance Binrep.BLen.Simple.BLen a => Binrep.BLen.Simple.BLen [a]
+ Binrep.BLen.Simple: instance GHC.Num.Num a => GHC.Base.Monoid (Binrep.BLen.Simple.BLen' a)
+ Binrep.BLen.Simple: instance GHC.Num.Num a => GHC.Base.Semigroup (Binrep.BLen.Simple.BLen' a)
+ Binrep.BLen.Simple: instance GHC.TypeNats.KnownNat (Binrep.CBLen.CBLen a) => Binrep.BLen.Simple.BLen (Binrep.BLen.Simple.CBLenly a)
+ Binrep.BLen.Simple: instance Generic.Data.Function.FoldMap.Constructor.GenericFoldMap (Binrep.BLen.Simple.BLen' GHC.Types.Int)
+ Binrep.BLen.Simple: newtype BLen' a
+ Binrep.BLen.Simple: newtype CBLenly a
+ Binrep.CBLen: class IsCBLen a where {
+ Binrep.CBLen: instance (Binrep.CBLen.IsCBLen l, Binrep.CBLen.IsCBLen r) => Binrep.CBLen.IsCBLen (l, r)
+ Binrep.CBLen: instance Binrep.CBLen.IsCBLen ()
+ Binrep.CBLen: instance Binrep.CBLen.IsCBLen GHC.Int.Int16
+ Binrep.CBLen: instance Binrep.CBLen.IsCBLen GHC.Int.Int32
+ Binrep.CBLen: instance Binrep.CBLen.IsCBLen GHC.Int.Int64
+ Binrep.CBLen: instance Binrep.CBLen.IsCBLen GHC.Int.Int8
+ Binrep.CBLen: instance Binrep.CBLen.IsCBLen GHC.Word.Word16
+ Binrep.CBLen: instance Binrep.CBLen.IsCBLen GHC.Word.Word32
+ Binrep.CBLen: instance Binrep.CBLen.IsCBLen GHC.Word.Word64
+ Binrep.CBLen: instance Binrep.CBLen.IsCBLen GHC.Word.Word8
+ Binrep.CBLen: type CBLen a :: Natural;
+ Binrep.CBLen: }
+ Binrep.CBLen.Generic: data JustX a b
+ Binrep.CBLen.Generic: data NothingX
+ Binrep.CBLen.Generic: type CBLenGeneric w a = GCBLen w (Rep a)
+ Binrep.CBLen.Generic: type family GCBLenCaseMaybe a
+ Binrep.Extra.HexByteString: instance Data.Aeson.Types.FromJSON.FromJSON (Binrep.Extra.HexByteString.Hex Data.ByteString.Internal.Type.ByteString)
+ Binrep.Extra.HexByteString: instance Data.Aeson.Types.ToJSON.ToJSON (Binrep.Extra.HexByteString.Hex Data.ByteString.Internal.Type.ByteString)
+ Binrep.Extra.HexByteString: instance GHC.Show.Show (Binrep.Extra.HexByteString.Hex Data.ByteString.Internal.Type.ByteString)
+ Binrep.Generic: nullTermCstrPfxTag :: String -> NullTerminated ByteString
+ Binrep.Get.Flatparse: E :: Int -> EMiddle -> E
+ Binrep.Get.Flatparse: EExpected :: ByteString -> ByteString -> EBase
+ Binrep.Get.Flatparse: EExpectedByte :: Word8 -> Word8 -> EBase
+ Binrep.Get.Flatparse: EFail :: E
+ Binrep.Get.Flatparse: EFailNamed :: String -> EBase
+ Binrep.Get.Flatparse: EFailParse :: String -> ByteString -> Word8 -> EBase
+ Binrep.Get.Flatparse: EGenericField :: String -> Maybe String -> Natural -> e -> EGeneric e
+ Binrep.Get.Flatparse: EGenericSum :: EGenericSum e -> EGeneric e
+ Binrep.Get.Flatparse: EGenericSumTag :: e -> EGenericSum e
+ Binrep.Get.Flatparse: EGenericSumTagNoMatch :: [String] -> Text -> EGenericSum e
+ Binrep.Get.Flatparse: EOverlong :: Int -> Int -> EBase
+ Binrep.Get.Flatparse: ERanOut :: Int -> EBase
+ Binrep.Get.Flatparse: class Get a
+ Binrep.Get.Flatparse: data E
+ Binrep.Get.Flatparse: data EBase
+ Binrep.Get.Flatparse: data EGeneric e
+ Binrep.Get.Flatparse: data EGenericSum e
+ Binrep.Get.Flatparse: eBase :: EBase -> Getter a
+ Binrep.Get.Flatparse: get :: Get a => Getter a
+ Binrep.Get.Flatparse: getEBase :: Getter a -> EBase -> Getter a
+ Binrep.Get.Flatparse: 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
+ Binrep.Get.Flatparse: 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
+ Binrep.Get.Flatparse: instance (Binrep.Get.Flatparse.Get l, Binrep.Get.Flatparse.Get r) => Binrep.Get.Flatparse.Get (l, r)
+ Binrep.Get.Flatparse: instance (TypeError ...) => Binrep.Get.Flatparse.Get (Data.Either.Either a b)
+ Binrep.Get.Flatparse: instance (TypeError ...) => Binrep.Get.Flatparse.Get Data.Void.Void
+ Binrep.Get.Flatparse: instance Binrep.Get.Flatparse.Get ()
+ Binrep.Get.Flatparse: instance Binrep.Get.Flatparse.Get Bytezap.Write
+ Binrep.Get.Flatparse: instance Binrep.Get.Flatparse.Get Data.ByteString.Internal.Type.ByteString
+ Binrep.Get.Flatparse: instance Binrep.Get.Flatparse.Get GHC.Int.Int8
+ Binrep.Get.Flatparse: instance Binrep.Get.Flatparse.Get GHC.Word.Word8
+ Binrep.Get.Flatparse: instance Binrep.Get.Flatparse.Get a => Binrep.Get.Flatparse.Get [a]
+ Binrep.Get.Flatparse: instance GHC.Classes.Eq Binrep.Get.Flatparse.E
+ Binrep.Get.Flatparse: instance GHC.Classes.Eq Binrep.Get.Flatparse.EBase
+ Binrep.Get.Flatparse: instance GHC.Classes.Eq Binrep.Get.Flatparse.EMiddle
+ Binrep.Get.Flatparse: instance GHC.Classes.Eq e => GHC.Classes.Eq (Binrep.Get.Flatparse.EGeneric e)
+ Binrep.Get.Flatparse: instance GHC.Classes.Eq e => GHC.Classes.Eq (Binrep.Get.Flatparse.EGenericSum e)
+ Binrep.Get.Flatparse: instance GHC.Generics.Generic (Binrep.Get.Flatparse.EGeneric e)
+ Binrep.Get.Flatparse: instance GHC.Generics.Generic (Binrep.Get.Flatparse.EGenericSum e)
+ Binrep.Get.Flatparse: instance GHC.Generics.Generic Binrep.Get.Flatparse.E
+ Binrep.Get.Flatparse: instance GHC.Generics.Generic Binrep.Get.Flatparse.EBase
+ Binrep.Get.Flatparse: instance GHC.Generics.Generic Binrep.Get.Flatparse.EMiddle
+ Binrep.Get.Flatparse: instance GHC.Show.Show Binrep.Get.Flatparse.E
+ Binrep.Get.Flatparse: instance GHC.Show.Show Binrep.Get.Flatparse.EBase
+ Binrep.Get.Flatparse: instance GHC.Show.Show Binrep.Get.Flatparse.EMiddle
+ Binrep.Get.Flatparse: instance GHC.Show.Show e => GHC.Show.Show (Binrep.Get.Flatparse.EGeneric e)
+ Binrep.Get.Flatparse: instance GHC.Show.Show e => GHC.Show.Show (Binrep.Get.Flatparse.EGenericSum e)
+ Binrep.Get.Flatparse: instance Generic.Data.Function.Traverse.Constructor.GenericTraverse (FlatParse.Basic.Parser.Parser Binrep.Get.Flatparse.E)
+ Binrep.Get.Flatparse: instance Generic.Data.Function.Traverse.Sum.GenericTraverseSum (FlatParse.Basic.Parser.Parser Binrep.Get.Flatparse.E)
+ Binrep.Get.Flatparse: runGet :: Get a => ByteString -> Either E (a, ByteString)
+ Binrep.Get.Flatparse: runGetter :: Getter a -> ByteString -> Either E (a, ByteString)
+ Binrep.Get.Flatparse: type Getter a = Parser E a
+ Binrep.Put.Bytezap: class Put a
+ Binrep.Put.Bytezap: instance (Binrep.Put.Bytezap.Put l, Binrep.Put.Bytezap.Put r) => Binrep.Put.Bytezap.Put (l, r)
+ Binrep.Put.Bytezap: instance (TypeError ...) => Binrep.Put.Bytezap.Put (Data.Either.Either a b)
+ Binrep.Put.Bytezap: instance (TypeError ...) => Binrep.Put.Bytezap.Put Data.Void.Void
+ Binrep.Put.Bytezap: instance Binrep.Put.Bytezap.Put ()
+ Binrep.Put.Bytezap: instance Binrep.Put.Bytezap.Put Bytezap.Poke
+ Binrep.Put.Bytezap: instance Binrep.Put.Bytezap.Put Bytezap.Write
+ Binrep.Put.Bytezap: instance Binrep.Put.Bytezap.Put Data.ByteString.Internal.Type.ByteString
+ Binrep.Put.Bytezap: instance Binrep.Put.Bytezap.Put GHC.Int.Int8
+ Binrep.Put.Bytezap: instance Binrep.Put.Bytezap.Put GHC.Word.Word8
+ Binrep.Put.Bytezap: instance Binrep.Put.Bytezap.Put a => Binrep.Put.Bytezap.Put [a]
+ Binrep.Put.Bytezap: instance Generic.Data.Function.FoldMap.Constructor.GenericFoldMap Bytezap.Poke
+ Binrep.Put.Bytezap: put :: Put a => a -> Poke
+ Binrep.Put.Bytezap: putGenericNonSum :: forall {cd} {f} {asserts} a. (Generic a, Rep a ~ D1 cd f, GFoldMapNonSum Poke f, asserts ~ '[ 'NoEmpty, 'NoSum], ApplyGCAsserts asserts f) => a -> Poke
+ Binrep.Put.Bytezap: 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
+ Binrep.Put.Bytezap: runPut :: (BLen a, Put a) => a -> ByteString
+ Binrep.Put.Mason: class Put a
+ Binrep.Put.Mason: class PutWith r a
+ Binrep.Put.Mason: instance (Binrep.Put.Mason.Put a, Binrep.Put.Mason.Put b) => Binrep.Put.Mason.Put (a, b)
+ Binrep.Put.Mason: instance Binrep.Put.Mason.Put Data.ByteString.Internal.Type.ByteString
+ Binrep.Put.Mason: instance Binrep.Put.Mason.Put Data.Void.Void
+ Binrep.Put.Mason: instance Binrep.Put.Mason.Put GHC.Int.Int8
+ Binrep.Put.Mason: instance Binrep.Put.Mason.Put GHC.Word.Word8
+ Binrep.Put.Mason: instance Binrep.Put.Mason.Put a => Binrep.Put.Mason.Put [a]
+ Binrep.Put.Mason: instance Binrep.Put.Mason.Put a => Binrep.Put.Mason.PutWith r [a]
+ Binrep.Put.Mason: instance Generic.Data.Function.FoldMap.Constructor.GenericFoldMap Binrep.Put.Mason.Builder
+ Binrep.Put.Mason: put :: Put a => a -> Builder
+ Binrep.Put.Mason: putGenericNonSum :: forall {cd} {f} {asserts} a. (Generic a, Rep a ~ D1 cd f, GFoldMapNonSum Builder f, asserts ~ '[ 'NoEmpty, 'NoSum], ApplyGCAsserts asserts f) => a -> Builder
+ Binrep.Put.Mason: 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
+ Binrep.Put.Mason: putWith :: (PutWith r a, Put a) => r -> a -> Either String Builder
+ Binrep.Put.Mason: putWithout :: Put a => a -> Either String Builder
+ Binrep.Put.Mason: runBuilder :: Builder -> ByteString
+ Binrep.Put.Mason: runPut :: Put a => a -> ByteString
+ Binrep.Put.Mason: runPutWith :: PutWith r a => r -> a -> Either String ByteString
+ Binrep.Put.Mason: type Builder = BuilderFor StrictByteStringBackend
+ Binrep.Type.Byte: instance (Binrep.Type.Byte.ByteVal n, Binrep.Type.Byte.ReifyBytes ns) => Binrep.Type.Byte.ReifyBytes (n : ns)
+ Binrep.Type.Byte: instance Binrep.Type.Byte.ReifyBytes '[]
+ Binrep.Type.Int: Endian :: a -> Endian (end :: Endianness) a
+ Binrep.Type.Int: [unEndian] :: Endian (end :: Endianness) a -> a
+ Binrep.Type.Int: flatparseParseEndianMin :: Getter a -> Int -> Getter (Endian end a)
+ Binrep.Type.Int: instance (Data.Typeable.Internal.Typeable end, Data.Data.Data a) => Data.Data.Data (Binrep.Type.Int.Endian end a)
+ Binrep.Type.Int: instance Binrep.BLen.Simple.BLen a => Binrep.BLen.Simple.BLen (Binrep.Type.Int.Endian end a)
+ Binrep.Type.Int: instance Binrep.CBLen.IsCBLen (Binrep.Type.Int.Endian end a)
+ Binrep.Type.Int: instance Binrep.Get.Flatparse.Get (Binrep.Type.Int.Endian 'Binrep.Type.Common.BE GHC.Int.Int16)
+ Binrep.Type.Int: instance Binrep.Get.Flatparse.Get (Binrep.Type.Int.Endian 'Binrep.Type.Common.BE GHC.Int.Int32)
+ Binrep.Type.Int: instance Binrep.Get.Flatparse.Get (Binrep.Type.Int.Endian 'Binrep.Type.Common.BE GHC.Int.Int64)
+ Binrep.Type.Int: instance Binrep.Get.Flatparse.Get (Binrep.Type.Int.Endian 'Binrep.Type.Common.BE GHC.Word.Word16)
+ Binrep.Type.Int: instance Binrep.Get.Flatparse.Get (Binrep.Type.Int.Endian 'Binrep.Type.Common.BE GHC.Word.Word32)
+ Binrep.Type.Int: instance Binrep.Get.Flatparse.Get (Binrep.Type.Int.Endian 'Binrep.Type.Common.BE GHC.Word.Word64)
+ Binrep.Type.Int: instance Binrep.Get.Flatparse.Get (Binrep.Type.Int.Endian 'Binrep.Type.Common.LE GHC.Int.Int16)
+ Binrep.Type.Int: instance Binrep.Get.Flatparse.Get (Binrep.Type.Int.Endian 'Binrep.Type.Common.LE GHC.Int.Int32)
+ Binrep.Type.Int: instance Binrep.Get.Flatparse.Get (Binrep.Type.Int.Endian 'Binrep.Type.Common.LE GHC.Int.Int64)
+ Binrep.Type.Int: instance Binrep.Get.Flatparse.Get (Binrep.Type.Int.Endian 'Binrep.Type.Common.LE GHC.Word.Word16)
+ Binrep.Type.Int: instance Binrep.Get.Flatparse.Get (Binrep.Type.Int.Endian 'Binrep.Type.Common.LE GHC.Word.Word32)
+ Binrep.Type.Int: instance Binrep.Get.Flatparse.Get (Binrep.Type.Int.Endian 'Binrep.Type.Common.LE GHC.Word.Word64)
+ Binrep.Type.Int: instance Binrep.Get.Flatparse.Get (Binrep.Type.Int.Endian end GHC.Int.Int8)
+ Binrep.Type.Int: instance Binrep.Get.Flatparse.Get (Binrep.Type.Int.Endian end GHC.Word.Word8)
+ Binrep.Type.Int: instance Binrep.Put.Bytezap.Put (Binrep.Type.Int.Endian 'Binrep.Type.Common.BE GHC.Int.Int16)
+ Binrep.Type.Int: instance Binrep.Put.Bytezap.Put (Binrep.Type.Int.Endian 'Binrep.Type.Common.BE GHC.Int.Int32)
+ Binrep.Type.Int: instance Binrep.Put.Bytezap.Put (Binrep.Type.Int.Endian 'Binrep.Type.Common.BE GHC.Int.Int64)
+ Binrep.Type.Int: instance Binrep.Put.Bytezap.Put (Binrep.Type.Int.Endian 'Binrep.Type.Common.BE GHC.Word.Word16)
+ Binrep.Type.Int: instance Binrep.Put.Bytezap.Put (Binrep.Type.Int.Endian 'Binrep.Type.Common.BE GHC.Word.Word32)
+ Binrep.Type.Int: instance Binrep.Put.Bytezap.Put (Binrep.Type.Int.Endian 'Binrep.Type.Common.BE GHC.Word.Word64)
+ Binrep.Type.Int: instance Binrep.Put.Bytezap.Put (Binrep.Type.Int.Endian 'Binrep.Type.Common.LE GHC.Int.Int16)
+ Binrep.Type.Int: instance Binrep.Put.Bytezap.Put (Binrep.Type.Int.Endian 'Binrep.Type.Common.LE GHC.Int.Int32)
+ Binrep.Type.Int: instance Binrep.Put.Bytezap.Put (Binrep.Type.Int.Endian 'Binrep.Type.Common.LE GHC.Int.Int64)
+ Binrep.Type.Int: instance Binrep.Put.Bytezap.Put (Binrep.Type.Int.Endian 'Binrep.Type.Common.LE GHC.Word.Word16)
+ Binrep.Type.Int: instance Binrep.Put.Bytezap.Put (Binrep.Type.Int.Endian 'Binrep.Type.Common.LE GHC.Word.Word32)
+ Binrep.Type.Int: instance Binrep.Put.Bytezap.Put (Binrep.Type.Int.Endian 'Binrep.Type.Common.LE GHC.Word.Word64)
+ Binrep.Type.Int: instance Binrep.Put.Mason.Put (Binrep.Type.Int.Endian end GHC.Int.Int8)
+ Binrep.Type.Int: instance Binrep.Put.Mason.Put (Binrep.Type.Int.Endian end GHC.Word.Word8)
+ Binrep.Type.Int: instance Data.Aeson.Types.FromJSON.FromJSON a => Data.Aeson.Types.FromJSON.FromJSON (Binrep.Type.Int.Endian end a)
+ Binrep.Type.Int: instance Data.Aeson.Types.ToJSON.ToJSON a => Data.Aeson.Types.ToJSON.ToJSON (Binrep.Type.Int.Endian end a)
+ Binrep.Type.Int: instance GHC.Classes.Eq a => GHC.Classes.Eq (Binrep.Type.Int.Endian end a)
+ Binrep.Type.Int: instance GHC.Classes.Ord a => GHC.Classes.Ord (Binrep.Type.Int.Endian end a)
+ Binrep.Type.Int: instance GHC.Enum.Bounded a => GHC.Enum.Bounded (Binrep.Type.Int.Endian end a)
+ Binrep.Type.Int: instance GHC.Enum.Enum a => GHC.Enum.Enum (Binrep.Type.Int.Endian end a)
+ Binrep.Type.Int: instance GHC.Generics.Generic (Binrep.Type.Int.Endian end a)
+ Binrep.Type.Int: instance GHC.Num.Num a => GHC.Num.Num (Binrep.Type.Int.Endian end a)
+ Binrep.Type.Int: instance GHC.Real.Integral a => GHC.Real.Integral (Binrep.Type.Int.Endian end a)
+ Binrep.Type.Int: instance GHC.Real.Real a => GHC.Real.Real (Binrep.Type.Int.Endian end a)
+ Binrep.Type.Int: instance GHC.Show.Show a => GHC.Show.Show (Binrep.Type.Int.Endian end a)
+ Binrep.Type.Int: instance Strongweak.Strengthen.Strengthen a => Strongweak.Strengthen.Strengthen (Binrep.Type.Int.Endian end a)
+ Binrep.Type.Int: instance Strongweak.Weaken.Weaken a => Strongweak.Weaken.Weaken (Binrep.Type.Int.Endian end a)
+ Binrep.Type.Int: newtype Endian (end :: Endianness) a
+ Binrep.Type.Magic: instance forall k (a :: k). Binrep.CBLen.IsCBLen (Binrep.Type.Magic.Magic a)
+ Binrep.Type.Magic: 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)
+ Binrep.Type.Magic: 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)
+ Binrep.Type.Magic: 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)
+ Binrep.Type.NullPadded: 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)
+ Binrep.Type.NullPadded: 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)
+ Binrep.Type.NullPadded: instance (Binrep.BLen.Simple.BLen a, GHC.TypeNats.KnownNat n) => Refined.Predicate (Binrep.Type.NullPadded.NullPad n) a
+ Binrep.Type.NullTerminated: class NullCheck a
+ Binrep.Type.NullTerminated: data NullTerminate
+ Binrep.Type.NullTerminated: hasNoNulls :: NullCheck a => a -> Bool
+ Binrep.Type.NullTerminated: instance Binrep.BLen.Simple.BLen a => Binrep.BLen.Simple.BLen (Binrep.Type.NullTerminated.NullTerminated a)
+ Binrep.Type.NullTerminated: instance Binrep.Get.Flatparse.Get (Binrep.Type.NullTerminated.NullTerminated Data.ByteString.Internal.Type.ByteString)
+ Binrep.Type.NullTerminated: instance Binrep.Put.Bytezap.Put a => Binrep.Put.Bytezap.Put (Binrep.Type.NullTerminated.NullTerminated a)
+ Binrep.Type.NullTerminated: instance Binrep.Type.NullTerminated.NullCheck Data.ByteString.Internal.Type.ByteString
+ Binrep.Type.NullTerminated: instance Binrep.Type.NullTerminated.NullCheck a => Refined.Predicate Binrep.Type.NullTerminated.NullTerminate a
+ Binrep.Type.NullTerminated: type NullTerminated = Refined NullTerminate
+ Binrep.Type.Prefix: class Prefix a where {
+ Binrep.Type.Prefix: instance Binrep.Type.Prefix.Prefix ()
+ Binrep.Type.Prefix: instance Binrep.Type.Prefix.Prefix GHC.Word.Word16
+ Binrep.Type.Prefix: instance Binrep.Type.Prefix.Prefix GHC.Word.Word32
+ Binrep.Type.Prefix: instance Binrep.Type.Prefix.Prefix GHC.Word.Word8
+ Binrep.Type.Prefix: instance Binrep.Type.Prefix.Prefix a => Binrep.Type.Prefix.Prefix (Binrep.Type.Int.Endian end a)
+ Binrep.Type.Prefix: lenToPfx :: Prefix a => Int -> a
+ Binrep.Type.Prefix: pfxToLen :: Prefix a => a -> Int
+ Binrep.Type.Prefix: type Max a :: Natural;
+ Binrep.Type.Prefix: }
+ Binrep.Type.Prefix.Count: class GetCount f
+ Binrep.Type.Prefix.Count: data CountPrefix (pfx :: Type)
+ Binrep.Type.Prefix.Count: getCount :: (GetCount f, Get a) => Int -> Getter (f a)
+ Binrep.Type.Prefix.Count: 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)
+ Binrep.Type.Prefix.Count: 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)
+ Binrep.Type.Prefix.Count: 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)
+ Binrep.Type.Prefix.Count: 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)
+ Binrep.Type.Prefix.Count: 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
+ Binrep.Type.Prefix.Count: instance Binrep.Type.Prefix.Count.GetCount []
+ Binrep.Type.Prefix.Count: instance forall k pfx (f :: k -> GHC.Types.Type) (a :: k). Binrep.CBLen.IsCBLen (Binrep.Type.Prefix.Count.CountPrefixed pfx f a)
+ Binrep.Type.Prefix.Count: type CountPrefixed pfx = Refined1 (CountPrefix pfx)
+ Binrep.Type.Prefix.Size: class GetSize a
+ Binrep.Type.Prefix.Size: data SizePrefix (pfx :: Type)
+ Binrep.Type.Prefix.Size: getSize :: GetSize a => Int -> Getter a
+ Binrep.Type.Prefix.Size: 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)
+ Binrep.Type.Prefix.Size: 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)
+ Binrep.Type.Prefix.Size: 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)
+ Binrep.Type.Prefix.Size: 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
+ Binrep.Type.Prefix.Size: instance Binrep.CBLen.IsCBLen (Binrep.Type.Prefix.Size.SizePrefixed pfx a)
+ Binrep.Type.Prefix.Size: instance Binrep.Type.Prefix.Size.GetSize (Binrep.Type.Thin.Thin Data.ByteString.Internal.Type.ByteString)
+ Binrep.Type.Prefix.Size: instance Binrep.Type.Prefix.Size.GetSize Data.ByteString.Internal.Type.ByteString
+ Binrep.Type.Prefix.Size: type SizePrefixed pfx = Refined (SizePrefix pfx)
+ Binrep.Type.Sized: instance (Binrep.BLen.Simple.BLen a, GHC.TypeNats.KnownNat n) => Refined.Predicate (Binrep.Type.Sized.Size n) a
+ Binrep.Type.Sized: instance (Binrep.Get.Flatparse.Get a, GHC.TypeNats.KnownNat n) => Binrep.Get.Flatparse.Get (Binrep.Type.Sized.Sized n a)
+ Binrep.Type.Sized: instance Binrep.CBLen.IsCBLen (Binrep.Type.Sized.Sized n a)
+ Binrep.Type.Sized: instance Binrep.Put.Bytezap.Put a => Binrep.Put.Bytezap.Put (Binrep.Type.Sized.Sized n a)
+ Binrep.Type.Sized: instance GHC.TypeNats.KnownNat n => Binrep.BLen.Simple.BLen (Binrep.Type.Sized.Sized n a)
+ Binrep.Type.Text: encode' :: Encode enc => Text -> Bytes
+ Binrep.Type.Text.Encoding.Ascii: catchErrorCall :: (a -> b) -> a -> Either String b
+ Binrep.Type.Text.Encoding.Ascii: data Ascii
+ Binrep.Type.Text.Encoding.Ascii: instance Binrep.Type.Text.Internal.Decode Binrep.Type.Text.Encoding.Ascii.Ascii
+ Binrep.Type.Text.Encoding.Ascii: instance Binrep.Type.Text.Internal.Encode Binrep.Type.Text.Encoding.Ascii.Ascii
+ Binrep.Type.Text.Encoding.Ascii: instance Refined.Predicate Binrep.Type.Text.Encoding.Ascii.Ascii Data.Text.Internal.Text
+ Binrep.Type.Text.Encoding.ShiftJis: data ShiftJis
+ Binrep.Type.Text.Encoding.ShiftJis: decodeViaTextICU :: String -> ByteString -> IO (Either String Text)
+ Binrep.Type.Text.Encoding.ShiftJis: decodeViaTextICU' :: String -> ByteString -> Either String Text
+ Binrep.Type.Text.Encoding.ShiftJis: encodeViaTextICU :: String -> Text -> IO ByteString
+ Binrep.Type.Text.Encoding.ShiftJis: encodeViaTextICU' :: String -> Text -> ByteString
+ Binrep.Type.Text.Encoding.ShiftJis: instance Binrep.Type.Text.Internal.Decode Binrep.Type.Text.Encoding.ShiftJis.ShiftJis
+ Binrep.Type.Text.Encoding.ShiftJis: instance Binrep.Type.Text.Internal.Encode Binrep.Type.Text.Encoding.ShiftJis.ShiftJis
+ Binrep.Type.Text.Encoding.ShiftJis: instance Refined.Predicate Binrep.Type.Text.Encoding.ShiftJis.ShiftJis Data.Text.Internal.Text
+ Binrep.Type.Text.Encoding.Utf16: data Utf16 (end :: Endianness)
+ Binrep.Type.Text.Encoding.Utf16: instance Binrep.Type.Text.Internal.Decode (Binrep.Type.Text.Encoding.Utf16.Utf16 'Binrep.Type.Common.BE)
+ Binrep.Type.Text.Encoding.Utf16: instance Binrep.Type.Text.Internal.Decode (Binrep.Type.Text.Encoding.Utf16.Utf16 'Binrep.Type.Common.LE)
+ Binrep.Type.Text.Encoding.Utf16: instance Binrep.Type.Text.Internal.Encode (Binrep.Type.Text.Encoding.Utf16.Utf16 'Binrep.Type.Common.BE)
+ Binrep.Type.Text.Encoding.Utf16: instance Binrep.Type.Text.Internal.Encode (Binrep.Type.Text.Encoding.Utf16.Utf16 'Binrep.Type.Common.LE)
+ Binrep.Type.Text.Encoding.Utf16: instance Data.Typeable.Internal.Typeable end => Refined.Predicate (Binrep.Type.Text.Encoding.Utf16.Utf16 end) Data.Text.Internal.Text
+ Binrep.Type.Text.Encoding.Utf32: data Utf32 (end :: Endianness)
+ Binrep.Type.Text.Encoding.Utf32: instance Binrep.Type.Text.Internal.Decode (Binrep.Type.Text.Encoding.Utf32.Utf32 'Binrep.Type.Common.BE)
+ Binrep.Type.Text.Encoding.Utf32: instance Binrep.Type.Text.Internal.Decode (Binrep.Type.Text.Encoding.Utf32.Utf32 'Binrep.Type.Common.LE)
+ Binrep.Type.Text.Encoding.Utf32: instance Binrep.Type.Text.Internal.Encode (Binrep.Type.Text.Encoding.Utf32.Utf32 'Binrep.Type.Common.BE)
+ Binrep.Type.Text.Encoding.Utf32: instance Binrep.Type.Text.Internal.Encode (Binrep.Type.Text.Encoding.Utf32.Utf32 'Binrep.Type.Common.LE)
+ Binrep.Type.Text.Encoding.Utf32: instance Data.Typeable.Internal.Typeable end => Refined.Predicate (Binrep.Type.Text.Encoding.Utf32.Utf32 end) Data.Text.Internal.Text
+ Binrep.Type.Text.Encoding.Utf8: data Utf8
+ Binrep.Type.Text.Encoding.Utf8: instance Binrep.Type.Text.Internal.Decode Binrep.Type.Text.Encoding.Utf8.Utf8
+ Binrep.Type.Text.Encoding.Utf8: instance Binrep.Type.Text.Internal.Encode Binrep.Type.Text.Encoding.Utf8.Utf8
+ Binrep.Type.Text.Encoding.Utf8: instance Refined.Predicate Binrep.Type.Text.Encoding.Utf8.Utf8 Data.Text.Internal.Text
+ Binrep.Type.Text.Internal: class Decode enc
+ Binrep.Type.Text.Internal: class Encode enc
+ Binrep.Type.Text.Internal: decode :: Decode enc => Bytes -> Either String (AsText enc)
+ Binrep.Type.Text.Internal: decodeText :: forall enc e. (e -> String) -> (Bytes -> Either e Text) -> Bytes -> Either String (AsText enc)
+ Binrep.Type.Text.Internal: encode' :: Encode enc => Text -> Bytes
+ Binrep.Type.Text.Internal: type AsText enc = Refined enc Text
+ Binrep.Type.Text.Internal: type Bytes = ByteString
+ Binrep.Type.Text.Internal: wrapUnsafeDecoder :: (Bytes -> Text) -> Bytes -> Either UnicodeException Text
+ Binrep.Type.Thin: Thin :: a -> Thin a
+ Binrep.Type.Thin: [unThin] :: Thin a -> a
+ Binrep.Type.Thin: instance Binrep.BLen.Simple.BLen a => Binrep.BLen.Simple.BLen (Binrep.Type.Thin.Thin a)
+ Binrep.Type.Thin: instance Binrep.Get.Flatparse.Get (Binrep.Type.Thin.Thin Bytezap.Write)
+ Binrep.Type.Thin: instance Binrep.Get.Flatparse.Get (Binrep.Type.Thin.Thin Data.ByteString.Internal.Type.ByteString)
+ Binrep.Type.Thin: instance Binrep.Put.Bytezap.Put a => Binrep.Put.Bytezap.Put (Binrep.Type.Thin.Thin a)
+ Binrep.Type.Thin: instance Control.DeepSeq.NFData a => Control.DeepSeq.NFData (Binrep.Type.Thin.Thin a)
+ Binrep.Type.Thin: instance Data.Data.Data a => Data.Data.Data (Binrep.Type.Thin.Thin a)
+ Binrep.Type.Thin: instance Data.String.IsString a => Data.String.IsString (Binrep.Type.Thin.Thin a)
+ Binrep.Type.Thin: instance GHC.Base.Monoid a => GHC.Base.Monoid (Binrep.Type.Thin.Thin a)
+ Binrep.Type.Thin: instance GHC.Base.Semigroup a => GHC.Base.Semigroup (Binrep.Type.Thin.Thin a)
+ Binrep.Type.Thin: instance GHC.Classes.Eq a => GHC.Classes.Eq (Binrep.Type.Thin.Thin a)
+ Binrep.Type.Thin: instance GHC.Classes.Ord a => GHC.Classes.Ord (Binrep.Type.Thin.Thin a)
+ Binrep.Type.Thin: instance GHC.Generics.Generic (Binrep.Type.Thin.Thin a)
+ Binrep.Type.Thin: instance GHC.IsList.IsList a => GHC.IsList.IsList (Binrep.Type.Thin.Thin a)
+ Binrep.Type.Thin: instance GHC.Read.Read a => GHC.Read.Read (Binrep.Type.Thin.Thin a)
+ Binrep.Type.Thin: instance GHC.Show.Show a => GHC.Show.Show (Binrep.Type.Thin.Thin a)
+ Binrep.Type.Thin: instance Strongweak.Strengthen.Strengthen (Binrep.Type.Thin.Thin a)
+ Binrep.Type.Thin: instance Strongweak.Weaken.Weaken (Binrep.Type.Thin.Thin a)
+ Binrep.Type.Thin: newtype Thin a
+ Binrep.Util.Class: type ENoEmpty = 'Text "No binary representation for empty data type"
+ Binrep.Util.Class: 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"
+ Binrep.Util.Generic: type EUnexpectedNonSum = 'Text "Refusing to derive sum binary representation instance for non-sum data type"
+ Binrep.Util.Generic: type EUnexpectedSum = 'Text "Cannot derive non-sum binary representation instance for sum data type"
+ Binrep.Via: Binreply :: a -> Binreply a
+ Binrep.Via: [unBinreply] :: Binreply a -> a
+ Binrep.Via: instance Binrep.BLen.Simple.BLen a => Binrep.BLen.Simple.BLen (Binrep.Via.Binreply a)
+ Binrep.Via: instance Binrep.CBLen.IsCBLen (Binrep.Via.Binreply a)
+ Binrep.Via: instance Binrep.Get.Flatparse.Get a => Binrep.Get.Flatparse.Get (Binrep.Via.Binreply a)
+ Binrep.Via: instance Binrep.Put.Bytezap.Put a => Binrep.Put.Bytezap.Put (Binrep.Via.Binreply a)
+ Binrep.Via: instance Binrep.Put.Mason.Put a => Binrep.Put.Mason.Put (Binrep.Via.Binreply a)
+ Binrep.Via: instance GHC.Show.Show a => GHC.Show.Show (Binrep.Via.Binreply a)
+ Binrep.Via: newtype Binreply a
+ Bytezap: Poke :: Poke# -> Poke
+ Bytezap: Write :: {-# UNPACK #-} !Int -> !Poke -> Write
+ Bytezap: [unPoke] :: Poke -> Poke#
+ Bytezap: [writePoke] :: Write -> !Poke
+ Bytezap: [writeSize] :: Write -> {-# UNPACK #-} !Int
+ Bytezap: data Write
+ Bytezap: instance GHC.Base.Monoid Bytezap.Poke
+ Bytezap: instance GHC.Base.Monoid Bytezap.Write
+ Bytezap: instance GHC.Base.Semigroup Bytezap.Poke
+ Bytezap: instance GHC.Base.Semigroup Bytezap.Write
+ Bytezap: instance GHC.Show.Show Bytezap.Write
+ Bytezap: newtype Poke
+ Bytezap: poke :: Poke# -> Poke
+ Bytezap: runPoke :: Int -> Poke -> ByteString
+ Bytezap: runWrite :: Write -> ByteString
+ Bytezap: type Poke# = Addr# -> State# RealWorld -> (# State# RealWorld, Addr# #)
+ Bytezap: wrapPoke :: Poke -> Ptr Word8 -> IO ()
+ Bytezap: write :: Int -> Poke# -> Write
+ Bytezap.Bytes: byteString :: ByteString -> Write
+ Bytezap.Bytes: memcpyForeignPtr :: Ptr Word8 -> ForeignPtr Word8 -> Int -> IO ()
+ Bytezap.Bytes: pokeByteArray# :: ByteArray# -> Int# -> Int# -> Poke
+ Bytezap.Bytes: pokeByteReplicate :: Int -> Word8 -> Poke
+ Bytezap.Bytes: pokeForeignPtr :: ForeignPtr Word8 -> Int -> Poke
+ Bytezap.Class: class Put a
+ Bytezap.Class: instance Bytezap.Class.Put Bytezap.Write
+ Bytezap.Class: instance Bytezap.Class.Put Data.ByteString.Internal.Type.ByteString
+ Bytezap.Class: instance Bytezap.Class.Put GHC.Int.Int16
+ Bytezap.Class: instance Bytezap.Class.Put GHC.Int.Int32
+ Bytezap.Class: instance Bytezap.Class.Put GHC.Int.Int64
+ Bytezap.Class: instance Bytezap.Class.Put GHC.Int.Int8
+ Bytezap.Class: instance Bytezap.Class.Put GHC.Word.Word16
+ Bytezap.Class: instance Bytezap.Class.Put GHC.Word.Word32
+ Bytezap.Class: instance Bytezap.Class.Put GHC.Word.Word64
+ Bytezap.Class: instance Bytezap.Class.Put GHC.Word.Word8
+ Bytezap.Class: put :: Put a => a -> Write
+ Bytezap.Int: byteSwapI16 :: Int16 -> Int16
+ Bytezap.Int: byteSwapI32 :: Int32 -> Int32
+ Bytezap.Int: byteSwapI64 :: Int64 -> Int64
+ Bytezap.Int: i16 :: Int16 -> Write
+ Bytezap.Int: i16be :: Int16 -> Write
+ Bytezap.Int: i16le :: Int16 -> Write
+ Bytezap.Int: i32 :: Int32 -> Write
+ Bytezap.Int: i32be :: Int32 -> Write
+ Bytezap.Int: i32le :: Int32 -> Write
+ Bytezap.Int: i64 :: Int64 -> Write
+ Bytezap.Int: i64be :: Int64 -> Write
+ Bytezap.Int: i64le :: Int64 -> Write
+ Bytezap.Int: i8 :: Int8 -> Write
+ Bytezap.Int: int# :: Int# -> Write
+ Bytezap.Int: w16 :: Word16 -> Write
+ Bytezap.Int: w16be :: Word16 -> Write
+ Bytezap.Int: w16le :: Word16 -> Write
+ Bytezap.Int: w32 :: Word32 -> Write
+ Bytezap.Int: w32be :: Word32 -> Write
+ Bytezap.Int: w32le :: Word32 -> Write
+ Bytezap.Int: w64 :: Word64 -> Write
+ Bytezap.Int: w64be :: Word64 -> Write
+ Bytezap.Int: w64le :: Word64 -> Write
+ Bytezap.Int: w8 :: Word8 -> Write
+ Bytezap.Poke.Bytes: byteString :: ByteString -> Poke
+ Bytezap.Poke.Bytes: memcpyForeignPtr :: Ptr Word8 -> ForeignPtr Word8 -> Int -> IO ()
+ Bytezap.Poke.Bytes: pokeByteArray# :: ByteArray# -> Int# -> Int# -> Poke
+ Bytezap.Poke.Bytes: pokeForeignPtr :: ForeignPtr Word8 -> Int -> Poke
+ Bytezap.Poke.Int: byteSwapI16 :: Int16 -> Int16
+ Bytezap.Poke.Int: byteSwapI32 :: Int32 -> Int32
+ Bytezap.Poke.Int: byteSwapI64 :: Int64 -> Int64
+ Bytezap.Poke.Int: i16 :: Int16 -> Poke
+ Bytezap.Poke.Int: i16be :: Int16 -> Poke
+ Bytezap.Poke.Int: i16le :: Int16 -> Poke
+ Bytezap.Poke.Int: i32 :: Int32 -> Poke
+ Bytezap.Poke.Int: i32be :: Int32 -> Poke
+ Bytezap.Poke.Int: i32le :: Int32 -> Poke
+ Bytezap.Poke.Int: i64 :: Int64 -> Poke
+ Bytezap.Poke.Int: i64be :: Int64 -> Poke
+ Bytezap.Poke.Int: i64le :: Int64 -> Poke
+ Bytezap.Poke.Int: i8 :: Int8 -> Poke
+ Bytezap.Poke.Int: int# :: Int# -> Poke
+ Bytezap.Poke.Int: w16 :: Word16 -> Poke
+ Bytezap.Poke.Int: w16be :: Word16 -> Poke
+ Bytezap.Poke.Int: w16le :: Word16 -> Poke
+ Bytezap.Poke.Int: w32 :: Word32 -> Poke
+ Bytezap.Poke.Int: w32be :: Word32 -> Poke
+ Bytezap.Poke.Int: w32le :: Word32 -> Poke
+ Bytezap.Poke.Int: w64 :: Word64 -> Poke
+ Bytezap.Poke.Int: w64be :: Word64 -> Poke
+ Bytezap.Poke.Int: w64le :: Word64 -> Poke
+ Bytezap.Poke.Int: w8 :: Word8 -> Poke
+ Bytezap.Text: charUtf8 :: Char -> Write
+ Bytezap.Text: stringUtf8 :: String -> Write
+ Bytezap.Text: textUtf8 :: Text -> Write
+ Util.TypeNats: natVal'' :: forall n. KnownNat n => Natural
+ Util.TypeNats: natValInt :: forall n. KnownNat n => Int
- Binrep.Type.Byte: byteVal :: ByteVal n => Proxy# n -> Word8#
+ Binrep.Type.Byte: byteVal :: ByteVal n => Word8
- Binrep.Type.Byte: reifyBytes :: ReifyBytes ns => Builder
+ Binrep.Type.Byte: reifyBytes :: ReifyBytes ns => Poke
- Binrep.Type.Int: I :: IRep sign size -> I (sign :: ISign) (size :: ISize) (e :: Endianness)
+ Binrep.Type.Int: I :: ISign
- Binrep.Type.Int: type family MaxBound w :: Natural
+ Binrep.Type.Int: type family IMax (isign :: ISign) (n :: Natural) :: Natural
- Binrep.Type.Sized: type Sized n a = Refined (Size n) a
+ Binrep.Type.Sized: type Sized n = Refined (Size n)
- Binrep.Type.Text: class Decode (enc :: Encoding)
+ Binrep.Type.Text: class Decode enc
- Binrep.Type.Text: class Encode (enc :: Encoding)
+ Binrep.Type.Text: class Encode enc
- Binrep.Type.Text: encodeToRep :: forall (rep :: Rep) enc. (Encode enc, Predicate rep Bytes) => AsText enc -> Either RefineException (Refined rep Bytes)
+ Binrep.Type.Text: encodeToRep :: forall rep enc. (Encode enc, Predicate rep Bytes) => AsText enc -> Either RefineException (Refined rep Bytes)
- Binrep.Type.Text: type AsText (enc :: Encoding) = Refined enc Text
+ Binrep.Type.Text: type AsText enc = Refined enc Text
Files
- CHANGELOG.md +10/−0
- README.md +24/−13
- bench/Main.hs +303/−0
- binrep.cabal +101/−94
- src/Binrep.hs +14/−22
- src/Binrep/BLen.hs +0/−111
- src/Binrep/BLen/Internal/AsBLen.hs +0/−65
- src/Binrep/BLen/Simple.hs +120/−0
- src/Binrep/CBLen.hs +23/−0
- src/Binrep/CBLen/Generic.hs +71/−0
- src/Binrep/Example.hs +0/−65
- src/Binrep/Example/FileTable.hs +0/−105
- src/Binrep/Example/Tar.hs +0/−61
- src/Binrep/Example/Tiff.hs +0/−58
- src/Binrep/Example/Wav.hs +0/−27
- src/Binrep/Extra/HexByteString.hs +1/−1
- src/Binrep/Generic.hs +9/−72
- src/Binrep/Generic/BLen.hs +0/−52
- src/Binrep/Generic/CBLen.hs +0/−70
- src/Binrep/Generic/Get.hs +0/−87
- src/Binrep/Generic/Internal.hs +0/−17
- src/Binrep/Generic/Put.hs +0/−67
- src/Binrep/Get.hs +0/−145
- src/Binrep/Get/Flatparse.hs +268/−0
- src/Binrep/Put.hs +0/−69
- src/Binrep/Put/Bytezap.hs +99/−0
- src/Binrep/Put/Mason.hs +102/−0
- src/Binrep/Type/AsciiNat.hs +0/−110
- src/Binrep/Type/Byte.hs +275/−291
- src/Binrep/Type/ByteString.hs +0/−100
- src/Binrep/Type/Common.hs +2/−2
- src/Binrep/Type/Int.hs +110/−109
- src/Binrep/Type/LenPfx.hs +0/−110
- src/Binrep/Type/Magic.hs +28/−21
- src/Binrep/Type/Magic/UTF8.hs +0/−47
- src/Binrep/Type/NullPadded.hs +38/−41
- src/Binrep/Type/NullTerminated.hs +69/−0
- src/Binrep/Type/Prefix.hs +56/−0
- src/Binrep/Type/Prefix/Count.hs +55/−0
- src/Binrep/Type/Prefix/Size.hs +53/−0
- src/Binrep/Type/Sized.hs +13/−12
- src/Binrep/Type/Text.hs +26/−166
- src/Binrep/Type/Text/Encoding/Ascii.hs +47/−0
- src/Binrep/Type/Text/Encoding/ShiftJis.hs +55/−0
- src/Binrep/Type/Text/Encoding/Utf16.hs +21/−0
- src/Binrep/Type/Text/Encoding/Utf32.hs +21/−0
- src/Binrep/Type/Text/Encoding/Utf8.hs +16/−0
- src/Binrep/Type/Text/Internal.hs +55/−0
- src/Binrep/Type/Thin.hs +55/−0
- src/Binrep/Type/Varint.hs +0/−136
- src/Binrep/Type/Vector.hs +0/−25
- src/Binrep/Util/Class.hs +19/−0
- src/Binrep/Util/Generic.hs +19/−0
- src/Binrep/Via.hs +12/−0
- src/Bytezap.hs +97/−0
- src/Bytezap/Bytes.hs +41/−0
- src/Bytezap/Class.hs +51/−0
- src/Bytezap/Int.hs +158/−0
- src/Bytezap/Poke/Bytes.hs +33/−0
- src/Bytezap/Poke/Int.hs +141/−0
- src/Bytezap/Text.hs +58/−0
- src/Data/Aeson/Extra/SizedVector.hs +2/−2
- src/Haskpatch/Format/Bps.hs +0/−46
- src/Haskpatch/Format/Vcdiff.hs +0/−57
- src/Util/Generic.hs +0/−29
- src/Util/TypeNats.hs +18/−0
- test/ArbitraryOrphans.hs +5/−4
- test/Binrep/LawsSpec.hs +14/−26
CHANGELOG.md view
@@ -1,3 +1,13 @@+## 0.5.0 (2023-08-17)+ * support GHC 9.2 - 9.6+ * extract generic serializing & parsing into separate library. yes, I wrote+ generic generics. what are you going to do about it+ * allow using different libraries for parsing and serializing (since I can't+ decide)+ * count-prefixed types use `Refined1`, currently in my refined fork+ * refactor `Binrep.Type.Text`: users can now add extend to add their own+ encodings+ ## 0.3.1 (2022-08-28) * fix `Get [a]` instance
README.md view
@@ -4,21 +4,24 @@ [gh-refined]: https://github.com/nikita-volkov/refined # binrep-binrep is a library for **precisely modelling binary schemas** and working with-them effectively and efficiently in Haskell. Here's why it's useful:+binrep is a Haskell library for *precisely modelling binary schemas*, especially+byte-oriented file formats, and working with them effectively and efficiently.+Here's why it's useful: - * **Explicit:** Binary representation primitives such as C-style bytestrings- (null-terminated), sized explicit-endian machine integers, and null-padded- data enable defining Haskell data types with the binary schema "baked in".- * **Low boilerplate:** Generic parsers and serializers further reduce boilerplate for- straightforward schemas. (See [Generic binary+ * **Explicit:** Define Haskell data types with the binary schema "baked in".+ Use highly parameterized binary representation primitives including+ null-terminated data (e.g. C-style strings), Pascal-style data (length+ prefixed), sized explicit-endian machine integers, null-padded data. Write+ your own as needed.+ * **Low boilerplate:** Straightforward schemas can leverage efficient generic+ parsers and serializers with just a few lines. (See [Generic binary representation](#generic-binary-representation) for details.)- * **Easy validation:** Goes hand in hand with my [strongweak][gh-strongweak]- library to allow working with unwrapped data internally, and enforcing all- the binary representation invariants before serializing - no extra- definitions required.- * **Performant:** Parsing and serialization is low-level and *extremely fast*,- using [flatparse][gh-flatparse] and [mason][gh-mason] respectively.+ * **Easy validation:** Use the [strongweak][gh-strongweak] library design+ pattern to define an unvalidated data type for easy internal transformation,+ and get validation code for free.+ * **Performant:** Parsing and serialization is *extremely fast*, using+ [flatparse][gh-flatparse] and [mason][gh-mason] respectively. An+ experimental non-allocating serializer is also provided. ## Usage ### Dependencies@@ -139,3 +142,11 @@ Check out Wuffs if you need to write a bunch of codecs and they really, really need to be both fast and safe. The trade-off is, of course, your time.++### flat+https://hackage.haskell.org/package/flat++Cool, bit-oriented rather than byte-oriented.++## License+Provided under the MIT license. See `LICENSE` for license text.
+ bench/Main.hs view
@@ -0,0 +1,303 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE OverloadedStrings #-}++module Main where++import Gauge++import Binrep+import Binrep.Generic+import Binrep.Type.NullTerminated+import Data.ByteString qualified as B+import Refined++import GHC.Generics ( Generic )+import Data.Word++{-+data X = X Word8 Word16 Word8+ deriving stock (Generic)++instance Put X where put = putGeneric c+instance Put' X where put' = put'Generic+instance BLen X where blen _ = 4+-}++data X3+ = X31 Word8+ | X32 Word8+ | X33 Word8 (NullTerminated B.ByteString) X3+ deriving stock (Generic)++instance BLen X3 where blen = blenGenericSum cDef+instance Put X3 where put = putGenericSum cDef++x33 :: X3+x33 =+ X33 001 $$(refineTH "hi, cstring here")+ $ X33 002 $$(refineTH "hi, cstring here")+ $ X33 003 $$(refineTH "hi, cstring here")+ $ X33 004 $$(refineTH "hi, cstring here")+ $ X33 005 $$(refineTH "hi, cstring here")+ $ X33 006 $$(refineTH "hi, cstring here")+ $ X33 007 $$(refineTH "hi, cstring here")+ $ X33 002 $$(refineTH "hi, cstring here")+ $ X33 003 $$(refineTH "hi, cstring here")+ $ X33 004 $$(refineTH "hi, cstring here")+ $ X33 005 $$(refineTH "hi, cstring here")+ $ X33 006 $$(refineTH "hi, cstring here")+ $ X33 007 $$(refineTH "hi, cstring here")+ $ X33 002 $$(refineTH "hi, cstring here")+ $ X33 003 $$(refineTH "hi, cstring here")+ $ X33 004 $$(refineTH "hi, cstring here")+ $ X33 005 $$(refineTH "hi, cstring here")+ $ X33 006 $$(refineTH "hi, cstring here")+ $ X33 007 $$(refineTH "hi, cstring here")+ $ X33 002 $$(refineTH "hi, cstring here")+ $ X33 003 $$(refineTH "hi, cstring here")+ $ X33 004 $$(refineTH "hi, cstring here")+ $ X33 005 $$(refineTH "hi, cstring here")+ $ X33 006 $$(refineTH "hi, cstring here")+ $ X33 007 $$(refineTH "hi, cstring here")+ $ X33 002 $$(refineTH "hi, cstring here")+ $ X33 003 $$(refineTH "hi, cstring here")+ $ X33 004 $$(refineTH "hi, cstring here")+ $ X33 005 $$(refineTH "hi, cstring here")+ $ X33 006 $$(refineTH "hi, cstring here")+ $ X33 007 $$(refineTH "hi, cstring here")+ $ X33 002 $$(refineTH "hi, cstring here")+ $ X33 003 $$(refineTH "hi, cstring here")+ $ X33 004 $$(refineTH "hi, cstring here")+ $ X33 005 $$(refineTH "hi, cstring here")+ $ X33 006 $$(refineTH "hi, cstring here")+ $ X33 007 $$(refineTH "hi, cstring here")+ $ X33 002 $$(refineTH "hi, cstring here")+ $ X33 003 $$(refineTH "hi, cstring here")+ $ X33 004 $$(refineTH "hi, cstring here")+ $ X33 005 $$(refineTH "hi, cstring here")+ $ X33 006 $$(refineTH "hi, cstring here")+ $ X33 007 $$(refineTH "hi, cstring here")+ $ X33 002 $$(refineTH "hi, cstring here")+ $ X33 003 $$(refineTH "hi, cstring here")+ $ X33 004 $$(refineTH "hi, cstring here")+ $ X33 005 $$(refineTH "hi, cstring here")+ $ X33 006 $$(refineTH "hi, cstring here")+ $ X33 007 $$(refineTH "hi, cstring here")+ $ X33 002 $$(refineTH "hi, cstring here")+ $ X33 003 $$(refineTH "hi, cstring here")+ $ X33 004 $$(refineTH "hi, cstring here")+ $ X33 005 $$(refineTH "hi, cstring here")+ $ X33 006 $$(refineTH "hi, cstring here")+ $ X33 007 $$(refineTH "hi, cstring here")+ $ X33 002 $$(refineTH "hi, cstring here")+ $ X33 003 $$(refineTH "hi, cstring here")+ $ X33 004 $$(refineTH "hi, cstring here")+ $ X33 005 $$(refineTH "hi, cstring here")+ $ X33 006 $$(refineTH "hi, cstring here")+ $ X33 007 $$(refineTH "hi, cstring here")+ $ X33 002 $$(refineTH "hi, cstring here")+ $ X33 003 $$(refineTH "hi, cstring here")+ $ X33 004 $$(refineTH "hi, cstring here")+ $ X33 005 $$(refineTH "hi, cstring here")+ $ X33 006 $$(refineTH "hi, cstring here")+ $ X33 007 $$(refineTH "hi, cstring here")+ $ X33 002 $$(refineTH "hi, cstring here")+ $ X33 003 $$(refineTH "hi, cstring here")+ $ X33 004 $$(refineTH "hi, cstring here")+ $ X33 005 $$(refineTH "hi, cstring here")+ $ X33 006 $$(refineTH "hi, cstring here")+ $ X33 007 $$(refineTH "hi, cstring here")+ $ X33 002 $$(refineTH "hi, cstring here")+ $ X33 003 $$(refineTH "hi, cstring here")+ $ X33 004 $$(refineTH "hi, cstring here")+ $ X33 005 $$(refineTH "hi, cstring here")+ $ X33 006 $$(refineTH "hi, cstring here")+ $ X33 007 $$(refineTH "hi, cstring here")+ $ X33 002 $$(refineTH "hi, cstring here")+ $ X33 003 $$(refineTH "hi, cstring here")+ $ X33 004 $$(refineTH "hi, cstring here")+ $ X33 005 $$(refineTH "hi, cstring here")+ $ X33 006 $$(refineTH "hi, cstring here")+ $ X33 007 $$(refineTH "hi, cstring here")+ $ X33 002 $$(refineTH "hi, cstring here")+ $ X33 003 $$(refineTH "hi, cstring here")+ $ X33 004 $$(refineTH "hi, cstring here")+ $ X33 005 $$(refineTH "hi, cstring here")+ $ X33 006 $$(refineTH "hi, cstring here")+ $ X33 007 $$(refineTH "hi, cstring here")+ $ X33 002 $$(refineTH "hi, cstring here")+ $ X33 003 $$(refineTH "hi, cstring here")+ $ X33 004 $$(refineTH "hi, cstring here")+ $ X33 005 $$(refineTH "hi, cstring here")+ $ X33 006 $$(refineTH "hi, cstring here")+ $ X33 007 $$(refineTH "hi, cstring here")+ $ X33 002 $$(refineTH "hi, cstring here")+ $ X33 003 $$(refineTH "hi, cstring here")+ $ X33 004 $$(refineTH "hi, cstring here")+ $ X33 005 $$(refineTH "hi, cstring here")+ $ X33 006 $$(refineTH "hi, cstring here")+ $ X33 007 $$(refineTH "hi, cstring here")+ $ X33 002 $$(refineTH "hi, cstring here")+ $ X33 003 $$(refineTH "hi, cstring here")+ $ X33 004 $$(refineTH "hi, cstring here")+ $ X33 005 $$(refineTH "hi, cstring here")+ $ X33 006 $$(refineTH "hi, cstring here")+ $ X33 007 $$(refineTH "hi, cstring here")+ $ X33 002 $$(refineTH "hi, cstring here")+ $ X33 003 $$(refineTH "hi, cstring here")+ $ X33 004 $$(refineTH "hi, cstring here")+ $ X33 005 $$(refineTH "hi, cstring here")+ $ X33 006 $$(refineTH "hi, cstring here")+ $ X33 007 $$(refineTH "hi, cstring here")+ $ X33 002 $$(refineTH "hi, cstring here")+ $ X33 003 $$(refineTH "hi, cstring here")+ $ X33 004 $$(refineTH "hi, cstring here")+ $ X33 005 $$(refineTH "hi, cstring here")+ $ X33 006 $$(refineTH "hi, cstring here")+ $ X33 007 $$(refineTH "hi, cstring here")+ $ X33 002 $$(refineTH "hi, cstring here")+ $ X33 003 $$(refineTH "hi, cstring here")+ $ X33 004 $$(refineTH "hi, cstring here")+ $ X33 005 $$(refineTH "hi, cstring here")+ $ X33 006 $$(refineTH "hi, cstring here")+ $ X33 007 $$(refineTH "hi, cstring here")+ $ X33 002 $$(refineTH "hi, cstring here")+ $ X33 003 $$(refineTH "hi, cstring here")+ $ X33 004 $$(refineTH "hi, cstring here")+ $ X33 005 $$(refineTH "hi, cstring here")+ $ X33 006 $$(refineTH "hi, cstring here")+ $ X33 007 $$(refineTH "hi, cstring here")+ $ X33 002 $$(refineTH "hi, cstring here")+ $ X33 003 $$(refineTH "hi, cstring here")+ $ X33 004 $$(refineTH "hi, cstring here")+ $ X33 005 $$(refineTH "hi, cstring here")+ $ X33 006 $$(refineTH "hi, cstring here")+ $ X33 007 $$(refineTH "hi, cstring here")+ $ X33 002 $$(refineTH "hi, cstring here")+ $ X33 003 $$(refineTH "hi, cstring here")+ $ X33 004 $$(refineTH "hi, cstring here")+ $ X33 005 $$(refineTH "hi, cstring here")+ $ X33 006 $$(refineTH "hi, cstring here")+ $ X33 007 $$(refineTH "hi, cstring here")+ $ X33 002 $$(refineTH "hi, cstring here")+ $ X33 003 $$(refineTH "hi, cstring here")+ $ X33 004 $$(refineTH "hi, cstring here")+ $ X33 005 $$(refineTH "hi, cstring here")+ $ X33 006 $$(refineTH "hi, cstring here")+ $ X33 007 $$(refineTH "hi, cstring here")+ $ X33 002 $$(refineTH "hi, cstring here")+ $ X33 003 $$(refineTH "hi, cstring here")+ $ X33 004 $$(refineTH "hi, cstring here")+ $ X33 005 $$(refineTH "hi, cstring here")+ $ X33 006 $$(refineTH "hi, cstring here")+ $ X33 007 $$(refineTH "hi, cstring here")+ $ X33 002 $$(refineTH "hi, cstring here")+ $ X33 003 $$(refineTH "hi, cstring here")+ $ X33 004 $$(refineTH "hi, cstring here")+ $ X33 005 $$(refineTH "hi, cstring here")+ $ X33 006 $$(refineTH "hi, cstring here")+ $ X33 007 $$(refineTH "hi, cstring here")+ $ X33 002 $$(refineTH "hi, cstring here")+ $ X33 003 $$(refineTH "hi, cstring here")+ $ X33 004 $$(refineTH "hi, cstring here")+ $ X33 005 $$(refineTH "hi, cstring here")+ $ X33 006 $$(refineTH "hi, cstring here")+ $ X33 007 $$(refineTH "hi, cstring here")+ $ X33 002 $$(refineTH "hi, cstring here")+ $ X33 003 $$(refineTH "hi, cstring here")+ $ X33 004 $$(refineTH "hi, cstring here")+ $ X33 005 $$(refineTH "hi, cstring here")+ $ X33 006 $$(refineTH "hi, cstring here")+ $ X33 007 $$(refineTH "hi, cstring here")+ $ X33 002 $$(refineTH "hi, cstring here")+ $ X33 003 $$(refineTH "hi, cstring here")+ $ X33 004 $$(refineTH "hi, cstring here")+ $ X33 005 $$(refineTH "hi, cstring here")+ $ X33 006 $$(refineTH "hi, cstring here")+ $ X33 007 $$(refineTH "hi, cstring here")+ $ X33 002 $$(refineTH "hi, cstring here")+ $ X33 003 $$(refineTH "hi, cstring here")+ $ X33 004 $$(refineTH "hi, cstring here")+ $ X33 005 $$(refineTH "hi, cstring here")+ $ X33 006 $$(refineTH "hi, cstring here")+ $ X33 007 $$(refineTH "hi, cstring here")+ $ X33 002 $$(refineTH "hi, cstring here")+ $ X33 003 $$(refineTH "hi, cstring here")+ $ X33 004 $$(refineTH "hi, cstring here")+ $ X33 005 $$(refineTH "hi, cstring here")+ $ X33 006 $$(refineTH "hi, cstring here")+ $ X33 007 $$(refineTH "hi, cstring here")+ $ X33 002 $$(refineTH "hi, cstring here")+ $ X33 003 $$(refineTH "hi, cstring here")+ $ X33 004 $$(refineTH "hi, cstring here")+ $ X33 005 $$(refineTH "hi, cstring here")+ $ X33 006 $$(refineTH "hi, cstring here")+ $ X33 007 $$(refineTH "hi, cstring here")+ $ X33 002 $$(refineTH "hi, cstring here")+ $ X33 003 $$(refineTH "hi, cstring here")+ $ X33 004 $$(refineTH "hi, cstring here")+ $ X33 005 $$(refineTH "hi, cstring here")+ $ X33 006 $$(refineTH "hi, cstring here")+ $ X33 007 $$(refineTH "hi, cstring here")+ $ X33 002 $$(refineTH "hi, cstring here")+ $ X33 003 $$(refineTH "hi, cstring here")+ $ X33 004 $$(refineTH "hi, cstring here")+ $ X33 005 $$(refineTH "hi, cstring here")+ $ X33 006 $$(refineTH "hi, cstring here")+ $ X33 007 $$(refineTH "hi, cstring here")+ $ X33 002 $$(refineTH "hi, cstring here")+ $ X33 003 $$(refineTH "hi, cstring here")+ $ X33 004 $$(refineTH "hi, cstring here")+ $ X33 005 $$(refineTH "hi, cstring here")+ $ X33 006 $$(refineTH "hi, cstring here")+ $ X33 007 $$(refineTH "hi, cstring here")+ $ X33 002 $$(refineTH "hi, cstring here")+ $ X33 003 $$(refineTH "hi, cstring here")+ $ X33 004 $$(refineTH "hi, cstring here")+ $ X33 005 $$(refineTH "hi, cstring here")+ $ X33 006 $$(refineTH "hi, cstring here")+ $ X33 007 $$(refineTH "hi, cstring here")+ $ X33 002 $$(refineTH "hi, cstring here")+ $ X33 003 $$(refineTH "hi, cstring here")+ $ X33 004 $$(refineTH "hi, cstring here")+ $ X33 005 $$(refineTH "hi, cstring here")+ $ X33 006 $$(refineTH "hi, cstring here")+ $ X33 007 $$(refineTH "hi, cstring here")+ $ X33 002 $$(refineTH "hi, cstring here")+ $ X33 003 $$(refineTH "hi, cstring here")+ $ X33 004 $$(refineTH "hi, cstring here")+ $ X33 005 $$(refineTH "hi, cstring here")+ $ X33 006 $$(refineTH "hi, cstring here")+ $ X33 007 $$(refineTH "hi, cstring here")+ $ X33 002 $$(refineTH "hi, cstring here")+ $ X33 003 $$(refineTH "hi, cstring here")+ $ X33 004 $$(refineTH "hi, cstring here")+ $ X33 005 $$(refineTH "hi, cstring here")+ $ X33 006 $$(refineTH "hi, cstring here")+ $ X33 007 $$(refineTH "hi, cstring here")+ $ X33 002 $$(refineTH "hi, cstring here")+ $ X33 003 $$(refineTH "hi, cstring here")+ $ X33 004 $$(refineTH "hi, cstring here")+ $ X33 005 $$(refineTH "hi, cstring here")+ $ X33 006 $$(refineTH "hi, cstring here")+ $ X33 007 $$(refineTH "hi, cstring here")+ $ X33 002 $$(refineTH "hi, cstring here")+ $ X33 003 $$(refineTH "hi, cstring here")+ $ X33 004 $$(refineTH "hi, cstring here")+ $ X33 005 $$(refineTH "hi, cstring here")+ $ X33 006 $$(refineTH "hi, cstring here")+ $ X33 007 $$(refineTH "hi, cstring here")+ $ X33 002 $$(refineTH "hi, cstring here")+ $ X33 003 $$(refineTH "hi, cstring here")+ $ X33 004 $$(refineTH "hi, cstring here")+ $ X33 005 $$(refineTH "hi, cstring here")+ $ X33 006 $$(refineTH "hi, cstring here")+ $ X33 007 $$(refineTH "hi, cstring here")+ $ X32 008++main :: IO ()+main = defaultMain+ [ bgroup "tiny"+ [ bench "put" $ whnf Binrep.runPut x33+ ]+ ]
binrep.cabal view
@@ -1,11 +1,11 @@ cabal-version: 1.12 --- This file has been generated from package.yaml by hpack version 0.34.4.+-- This file has been generated from package.yaml by hpack version 0.35.2. -- -- see: https://github.com/sol/hpack name: binrep-version: 0.3.1+version: 0.5.0 synopsis: Encode precise binary representations directly in types description: Please see README.md. category: Data, Serialization@@ -17,7 +17,7 @@ license-file: LICENSE build-type: Simple tested-with:- GHC ==9.2.4+ GHC ==9.4.4 extra-source-files: README.md CHANGELOG.md@@ -34,96 +34,81 @@ library exposed-modules: Binrep- Binrep.BLen- Binrep.BLen.Internal.AsBLen- Binrep.Example- Binrep.Example.FileTable- Binrep.Example.Tar- Binrep.Example.Tiff- Binrep.Example.Wav+ Binrep.BLen.Simple+ Binrep.CBLen+ Binrep.CBLen.Generic Binrep.Extra.HexByteString Binrep.Generic- Binrep.Generic.BLen- Binrep.Generic.CBLen- Binrep.Generic.Get- Binrep.Generic.Internal- Binrep.Generic.Put- Binrep.Get- Binrep.Put- Binrep.Type.AsciiNat+ Binrep.Get.Flatparse+ Binrep.Put.Bytezap+ Binrep.Put.Mason Binrep.Type.Byte- Binrep.Type.ByteString Binrep.Type.Common Binrep.Type.Int- Binrep.Type.LenPfx Binrep.Type.Magic- Binrep.Type.Magic.UTF8 Binrep.Type.NullPadded+ Binrep.Type.NullTerminated+ Binrep.Type.Prefix+ Binrep.Type.Prefix.Count+ Binrep.Type.Prefix.Size Binrep.Type.Sized Binrep.Type.Text- Binrep.Type.Varint- Binrep.Type.Vector+ Binrep.Type.Text.Encoding.Ascii+ Binrep.Type.Text.Encoding.ShiftJis+ Binrep.Type.Text.Encoding.Utf16+ Binrep.Type.Text.Encoding.Utf32+ Binrep.Type.Text.Encoding.Utf8+ Binrep.Type.Text.Internal+ Binrep.Type.Thin Binrep.Util+ Binrep.Util.Class+ Binrep.Util.Generic+ Binrep.Via+ Bytezap+ Bytezap.Bytes+ Bytezap.Class+ Bytezap.Int+ Bytezap.Poke.Bytes+ Bytezap.Poke.Int+ Bytezap.Text Data.Aeson.Extra.SizedVector- Haskpatch.Format.Bps- Haskpatch.Format.Vcdiff- Util.Generic+ Util.TypeNats other-modules: Paths_binrep hs-source-dirs: src default-extensions:- EmptyCase LambdaCase- InstanceSigs- BangPatterns- ExplicitNamespaces- DerivingStrategies+ NoStarIsType DerivingVia- StandaloneDeriving DeriveAnyClass- DeriveGeneric- DeriveDataTypeable- DeriveFunctor- DeriveFoldable- DeriveTraversable- DeriveLift- FlexibleContexts- FlexibleInstances- MultiParamTypeClasses GADTs- PolyKinds RoleAnnotations- RankNTypes- TypeApplications DefaultSignatures TypeFamilies DataKinds MagicHash- ImportQualifiedPost- StandaloneKindSignatures- BinaryLiterals- ScopedTypeVariables- TypeOperators ghc-options: -Wall build-depends:- aeson ==2.0.*+ aeson >=2.0 && <2.2 , base >=4.14 && <5- , bytestring ==0.11.*- , either >=5.0.1.1 && <5.1- , flatparse >=0.3.5.0 && <0.4+ , bytestring >=0.11 && <0.13+ , deepseq >=1.4.6.1 && <1.6+ , flatparse >=0.4.0.1 && <0.6+ , generic-data-functions >=0.2.0 && <0.3 , mason >=0.2.5 && <0.3- , megaparsec >=9.2.0 && <9.3- , refined ==0.7.*- , strongweak >=0.3.1 && <0.4- , text >=1.2 && <2.1- , vector >=0.12.3.1 && <0.13+ , megaparsec >=9.2.0 && <9.5.0+ , parser-combinators >=1.3.0 && <1.4+ , refined1 ==0.9.*+ , strongweak >=0.6.0 && <0.7+ , text >=1.2.5.0 && <2.1+ , vector >=0.12.3.1 && <0.14 , vector-sized >=1.5.0 && <1.6+ default-language: GHC2021 if flag(icu) cpp-options: -DHAVE_ICU build-depends: text-icu >=0.7.0.0 && <0.9- default-language: Haskell2010 test-suite spec type: exitcode-stdio-1.0@@ -136,61 +121,83 @@ hs-source-dirs: test default-extensions:- EmptyCase LambdaCase- InstanceSigs- BangPatterns- ExplicitNamespaces- DerivingStrategies+ NoStarIsType DerivingVia- StandaloneDeriving DeriveAnyClass- DeriveGeneric- DeriveDataTypeable- DeriveFunctor- DeriveFoldable- DeriveTraversable- DeriveLift- FlexibleContexts- FlexibleInstances- MultiParamTypeClasses GADTs- PolyKinds RoleAnnotations- RankNTypes- TypeApplications DefaultSignatures TypeFamilies DataKinds MagicHash- ImportQualifiedPost- StandaloneKindSignatures- BinaryLiterals- ScopedTypeVariables- TypeOperators ghc-options: -Wall build-tool-depends:- hspec-discover:hspec-discover >=2.7 && <2.10+ hspec-discover:hspec-discover >=2.7 && <2.12 build-depends: QuickCheck >=2.14.2 && <2.15- , aeson ==2.0.*+ , aeson >=2.0 && <2.2 , base >=4.14 && <5 , binrep- , bytestring ==0.11.*- , either >=5.0.1.1 && <5.1- , flatparse >=0.3.5.0 && <0.4+ , bytestring >=0.11 && <0.13+ , deepseq >=1.4.6.1 && <1.6+ , flatparse >=0.4.0.1 && <0.6+ , generic-data-functions >=0.2.0 && <0.3 , generic-random >=1.5.0.1 && <1.6- , hspec >=2.7 && <2.10+ , hspec >=2.7 && <2.12 , mason >=0.2.5 && <0.3- , megaparsec >=9.2.0 && <9.3+ , megaparsec >=9.2.0 && <9.5.0+ , parser-combinators >=1.3.0 && <1.4 , quickcheck-instances >=0.3.26 && <0.4- , refined ==0.7.*- , strongweak >=0.3.1 && <0.4- , text >=1.2 && <2.1- , vector >=0.12.3.1 && <0.13+ , refined1 ==0.9.*+ , strongweak >=0.6.0 && <0.7+ , text >=1.2.5.0 && <2.1+ , vector >=0.12.3.1 && <0.14 , vector-sized >=1.5.0 && <1.6+ default-language: GHC2021 if flag(icu) cpp-options: -DHAVE_ICU build-depends: text-icu >=0.7.0.0 && <0.9- default-language: Haskell2010++benchmark bench+ type: exitcode-stdio-1.0+ main-is: Main.hs+ other-modules:+ Paths_binrep+ hs-source-dirs:+ bench+ default-extensions:+ LambdaCase+ NoStarIsType+ DerivingVia+ DeriveAnyClass+ GADTs+ RoleAnnotations+ DefaultSignatures+ TypeFamilies+ DataKinds+ MagicHash+ ghc-options: -Wall -O2+ build-depends:+ aeson >=2.0 && <2.2+ , base >=4.14 && <5+ , binrep+ , bytestring >=0.11 && <0.13+ , deepseq >=1.4.6.1 && <1.6+ , flatparse >=0.4.0.1 && <0.6+ , gauge+ , generic-data-functions >=0.2.0 && <0.3+ , mason >=0.2.5 && <0.3+ , megaparsec >=9.2.0 && <9.5.0+ , parser-combinators >=1.3.0 && <1.4+ , refined1 ==0.9.*+ , strongweak >=0.6.0 && <0.7+ , text >=1.2.5.0 && <2.1+ , vector >=0.12.3.1 && <0.14+ , vector-sized >=1.5.0 && <1.6+ default-language: GHC2021+ if flag(icu)+ cpp-options: -DHAVE_ICU+ build-depends:+ text-icu >=0.7.0.0 && <0.9
src/Binrep.hs view
@@ -1,26 +1,18 @@-{- | Main end-user binrep module bundling most functionality.--Generics are bundled together in 'Binrep.Generic'.--}- module Binrep- ( module Binrep.BLen- , module Binrep.Put- , module Binrep.Get-- -- * Extras- , blenViaPut+ ( module Binrep.CBLen+ , module Binrep.BLen.Simple+ , module Binrep.Put.Bytezap+ , module Binrep.Get.Flatparse ) where -import Binrep.BLen-import Binrep.Put-import Binrep.Get+import Binrep.CBLen+import Binrep.BLen.Simple+import Binrep.Put.Bytezap+import Binrep.Get.Flatparse --- | The length in bytes of a 'Put'-able type is the length of the serialized--- term.------ Do not use this in 'BLen' instances. It's intended as a proof, and--- potentially for testing purposes. Calculating length in bytes shouldn't--- involve serializing (it should be fast and use minimal memory).-blenViaPut :: Put a => a -> BLenT-blenViaPut = blen . runPut+{- TODO+ * binrep is its own ecosystem where explicitness and correctness wins over+ all. There are no binrep instances for 'Data.Void.Void' or 'GHC.Generics.V1'+ because these can't be binrepped; rather than providing an absurd, possibly+ convenient instance, we emit a type error for their attempted use.+-}
− src/Binrep/BLen.hs
@@ -1,111 +0,0 @@-{-# LANGUAGE AllowAmbiguousTypes #-}-{-# LANGUAGE UndecidableInstances #-} -- for CBLen--module Binrep.BLen- ( module Binrep.BLen- , module Binrep.BLen.Internal.AsBLen- ) where--import Binrep.BLen.Internal.AsBLen-import Binrep.Util ( natVal'' )--import GHC.TypeLits--import Data.ByteString qualified as B--import Data.Word-import Data.Int--import Data.Void ( Void, absurd )--type BLenT = Int--{- | The length in bytes of a value of the given type can be known on the cheap- e.g. by reading a length field, or using compile time information.--Some binary representation building blocks require the notion of length in bytes-in order to handle, e.g. null padding. One may always obtain this by serializing-the value, then reading out the length of the output bytestring. But in most-cases, we can be much more efficient.-- * Certain primitives have a size known at compile time, irrelevant of the- value. A 'Word64' is always 8 bytes; some data null-padded to @n@ bytes is- exactly @n@ bytes long.- * For simple ADTs, it's often possible to calculate length in bytes via- pattern matching and some numeric operations. Very little actual work.--This type class enables each type to implement its own efficient method of byte-length calculation. Aim to write something that plainly feels more efficient-than full serialization. If that doesn't feel possible, you might be working-with a type ill-suited for binary representation.--A thought: Some instances could be improved by reifying 'CBLen'. But it would-mess up all the deriving, and it feels like too minor an improvement to be-worthwhile supporting, writing a bunch of newtype wrappers, etc.--}-class BLen a where- -- | The length in bytes of the serialized value.- --- -- The default implementation reifies the constant length for the type. If a- -- type-wide constant length is not defined, it will fail at compile time.- blen :: a -> BLenT- default blen :: KnownNat (CBLen a) => a -> BLenT- blen _ = cblen @a-- -- | The length in bytes of any value of the given type is constant.- --- -- Many binary representation primitives are constant, or may be designed to- -- "store" their size in their type. This is a stronger statement about- -- their length than just 'blen'.- --- -- This is now an associated type family of the 'BLen' type class in hopes- -- of simplifying the binrep framework.- type CBLen a :: Natural- type CBLen a =- TypeError- ( 'Text "No CBLen associated family instance defined for "- ':<>: 'ShowType a- )--typeNatToBLen :: forall n. KnownNat n => BLenT-typeNatToBLen = natToBLen $ natVal'' @n-{-# INLINE typeNatToBLen #-}---- | Reify a type's constant byte length to the term level.-cblen :: forall a n. (n ~ CBLen a, KnownNat n) => BLenT-cblen = typeNatToBLen @n-{-# INLINE cblen #-}---- | Impossible to put a byte length to 'Void'.-instance BLen Void where- blen = absurd---- | @O(n)@-instance BLen a => BLen [a] where- blen = sum . map blen--instance (BLen a, BLen b) => BLen (a, b) where- blen (a, b) = blen a + blen b--instance BLen B.ByteString where- blen = posIntToBLen . B.length--instance BLen Word8 where type CBLen Word8 = 1-instance BLen Int8 where type CBLen Int8 = 1-instance BLen Word16 where type CBLen Word16 = 2-instance BLen Int16 where type CBLen Int16 = 2-instance BLen Word32 where type CBLen Word32 = 4-instance BLen Int32 where type CBLen Int32 = 4-instance BLen Word64 where type CBLen Word64 = 8-instance BLen Int64 where type CBLen Int64 = 8-------------------------------------------------------------------------------------- | Newtype wrapper for defining 'BLen' instances which are allowed to assume--- the existence of a valid 'CBLen' family instance.-newtype WithCBLen a = WithCBLen { unWithCBLen :: a }--instance KnownNat (CBLen a) => BLen (WithCBLen [a]) where- blen (WithCBLen l) = cblen @a * length l-instance KnownNat (CBLen a + CBLen b) => BLen (WithCBLen (a, b)) where- type CBLen (WithCBLen (a, b)) = CBLen a + CBLen b
− src/Binrep/BLen/Internal/AsBLen.hs
@@ -1,65 +0,0 @@-module Binrep.BLen.Internal.AsBLen where--import GHC.Natural ( minusNaturalMaybe )-import GHC.Num.Natural-import GHC.Exts-import Binrep.Util ( posIntToNat )---- | Helper definitions for using the given type to store byte lengths.------ Byte lengths must be non-negative. Thus, the ideal representation is a--- 'Natural'. However, most underlying types that we use ('B.ByteString', lists)--- store their length in 'Int's. By similarly storing an 'Int' ourselves, we--- could potentially improve performance.------ I like both options, and don't want to give up either. So we provide helpers--- via a typeclass so that the user doesn't ever have to think about the--- underlying type.------ For simplicity, documentation may consider 'a' to be an "unsigned" type. For--- example, underflow refers to a negative 'a' result.-class AsBLen a where- -- | Safe blen subtraction, returning 'Nothing' for negative results.- --- -- Regular subtraction should only be used when you have a guarantee that it- -- won't underflow.- safeBLenSub :: a -> a -> Maybe a-- -- | Convert some 'Int' @i@ where @i >= 0@ to a blen.- --- -- This is intended for wrapping the output of 'length' functions.- posIntToBLen :: Int -> a-- -- | Convert some 'Word#' @w@ where @w <= maxBound @a@ to a blen.- wordToBLen# :: Word# -> a-- -- | Convert some 'Natural' @n@ where @n <= maxBound @a@ to a blen.- natToBLen :: Natural -> a--instance AsBLen Int where- safeBLenSub x y = if z >= 0 then Just z else Nothing where z = x - y- {-# INLINE safeBLenSub #-}-- posIntToBLen = id- {-# INLINE posIntToBLen #-}-- natToBLen = \case- NS w# -> wordToBLen# w#- NB _ -> error "TODO natural too large"- {-# INLINE natToBLen #-}-- wordToBLen# w# = I# (word2Int# w#)- {-# INLINE wordToBLen# #-}--instance AsBLen Natural where- safeBLenSub = minusNaturalMaybe- {-# INLINE safeBLenSub #-}-- posIntToBLen = posIntToNat- {-# INLINE posIntToBLen #-}-- wordToBLen# = NS- {-# INLINE wordToBLen# #-}-- natToBLen = id- {-# INLINE natToBLen #-}
+ src/Binrep/BLen/Simple.hs view
@@ -0,0 +1,120 @@+{-# LANGUAGE UndecidableInstances #-} -- for 'CBLenly', 'TypeError'+{-# LANGUAGE AllowAmbiguousTypes #-} -- for 'cblen', 'natValInt'++{- | 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 where++import Binrep.CBLen+import GHC.TypeNats+import Util.TypeNats ( natValInt )++import Binrep.Util.Class+import GHC.TypeLits ( TypeError )++import Data.Void+import Data.ByteString qualified as B+import Data.Word+import Data.Int+import Bytezap ( Write(..) )++import Data.Monoid ( Sum(..) )+import GHC.Generics+import Generic.Data.Function.FoldMap+import Generic.Data.Rep.Assert+import Generic.Data.Function.Common++class BLen a where blen :: a -> Int++-- newtype sum monoid for generic foldMap+newtype BLen' a = BLen' { getBLen' :: a }+ deriving (Semigroup, Monoid) via Sum a++instance GenericFoldMap (BLen' Int) where+ type GenericFoldMapC (BLen' Int) a = BLen a+ genericFoldMapF = BLen' . blen++-- | 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+blenGenericNonSum = getBLen' . genericFoldMapNonSum @asserts++-- | 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+blenGenericSum f = getBLen' . genericFoldMapSum @'SumOnly @asserts (BLen' <$> f)++instance TypeError ENoEmpty => BLen Void where blen = undefined+instance TypeError ENoSum => BLen (Either a b) where blen = undefined++instance BLen Write where+ {-# INLINE blen #-}+ blen = writeSize++-- | Unit type has length 0.+instance BLen () where+ {-# INLINE blen #-}+ blen () = 0++-- | Sum tuples.+instance (BLen l, BLen r) => BLen (l, r) where+ {-# INLINE blen #-}+ blen (l, r) = blen l + blen r++-- | _O(n)_ Sum the length of each element of a list.+instance BLen a => BLen [a] where+ {-# INLINE blen #-}+ blen = sum . map blen++-- | Length of a bytestring is fairly obvious.+instance BLen B.ByteString where+ {-# INLINE blen #-}+ blen = B.length++-- Machine integers have a constant byte length.+deriving via CBLenly Word8 instance BLen Word8+deriving via CBLenly Int8 instance BLen Int8+deriving via CBLenly Word16 instance BLen Word16+deriving via CBLenly Int16 instance BLen Int16+deriving via CBLenly Word32 instance BLen Word32+deriving via CBLenly Int32 instance BLen Int32+deriving via CBLenly Word64 instance BLen Word64+deriving via CBLenly Int64 instance BLen Int64++--------------------------------------------------------------------------------++-- | 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 { unCBLenly :: a }+instance KnownNat (CBLen a) => BLen (CBLenly a) where+ {-# INLINE blen #-}+ blen _ = cblen @a++-- | Reify a type's constant byte length to the term level.+cblen :: forall a n. (n ~ CBLen a, KnownNat n) => Int+cblen = natValInt @n+{-# INLINE cblen #-}
+ src/Binrep/CBLen.hs view
@@ -0,0 +1,23 @@+{-# LANGUAGE UndecidableInstances #-} -- for 'WithCBLen'+{-# LANGUAGE AllowAmbiguousTypes #-} -- for 'cblen'++module Binrep.CBLen where++import GHC.TypeNats+import Data.Word+import Data.Int++class IsCBLen a where type CBLen a :: Natural++instance IsCBLen () where type CBLen () = 0+instance (IsCBLen l, IsCBLen r) => IsCBLen (l, r) where+ type CBLen (l, r) = CBLen l + CBLen r++instance IsCBLen Word8 where type CBLen Word8 = 2^0+instance IsCBLen Int8 where type CBLen Int8 = 2^0+instance IsCBLen Word16 where type CBLen Word16 = 2^1+instance IsCBLen Int16 where type CBLen Int16 = 2^1+instance IsCBLen Word32 where type CBLen Word32 = 2^2+instance IsCBLen Int32 where type CBLen Int32 = 2^2+instance IsCBLen Word64 where type CBLen Word64 = 2^3+instance IsCBLen Int64 where type CBLen Int64 = 2^3
+ src/Binrep/CBLen/Generic.hs view
@@ -0,0 +1,71 @@+{-# LANGUAGE UndecidableInstances #-} -- hugely unsafe module++{- | _Experimental._ Generically derive 'CBLen' type family instances.++A type having a valid 'CBLen' instance usually indicates one of the following:++ * it's a primitive, or extremely simple+ * it holds size information in its type+ * it's constructed from other constant byte length types++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 where++import Binrep.CBLen+import Binrep.Util.Class++import GHC.Generics+import GHC.TypeLits+import Data.Kind++import Data.Type.Equality+import Data.Type.Bool++type CBLenGeneric w a = GCBLen w (Rep a)++type family GCBLen w (f :: k -> Type) :: Natural where+ GCBLen _ U1 = 0+ GCBLen _ (K1 i c) = CBLen c+ GCBLen w (l :*: r) = GCBLen w l + GCBLen w r++ GCBLen w (l :+: r) = CBLen w + GCBLenCaseMaybe (GCBLenSum w (l :+: r))++ GCBLen _ V1 = TypeError ENoEmpty+ GCBLen w (M1 _ _ f) = GCBLen w f++--type family GCBLenSum w (f :: k -> Type) :: Maybe Natural where+type family GCBLenSum w (f :: k -> Type) where+ GCBLenSum w (C1 ('MetaCons name _ _) f) = JustX (GCBLen w f) name+ GCBLenSum w (l :+: r) = MaybeEq (GCBLenSum w l) (GCBLenSum w r)++type family MaybeEq a b where+ MaybeEq (JustX n nName) (JustX m _) = If (n == m) (JustX n nName) NothingX+ MaybeEq _ _ = NothingX++-- | I don't know how to pattern match in types without writing type families.+type family GCBLenCaseMaybe a where+ GCBLenCaseMaybe (JustX n _) = n+ GCBLenCaseMaybe NothingX =+ TypeError+ ( 'Text "Two constructors didn't have equal constant size."+ ':$$: 'Text "Sry dunno how to thread errors thru LOL"+ )++-- TODO rewrite this stuff to thread error info through!+data JustX a b+data NothingX+
− src/Binrep/Example.hs
@@ -1,65 +0,0 @@-{-# LANGUAGE UndecidableInstances #-}--module Binrep.Example where--import Binrep-import Binrep.Generic-import Binrep.Generic qualified as BR-import Binrep.Type.Common ( Endianness(..) )-import Binrep.Type.Int--import GHC.Generics ( Generic )-import Data.Data ( Data )--import Data.Void ( Void )--data DV- deriving stock (Generic, Data)---- Disallowed. No binrepping void datatypes.-{--instance BLen DV where blen = blenGeneric BR.cNoSum-instance Put DV where put = putGeneric BR.cNoSum-instance Get DV where get = getGeneric BR.cNoSum--}--data DU = DU- deriving stock (Generic, Data, Show, Eq)----instance BLen DU where blen = blenGeneric BR.cNoSum-instance BLen DU where type CBLen DU = CBLenGeneric Void DU-instance Put DU where put = putGeneric cNoSum-instance Get DU where get = getGeneric cNoSum--data DSS = DSS- { dss1 :: I 'U 'I1 'LE- , dss2 :: I 'U 'I2 'LE- , dss3 :: I 'U 'I4 'LE- , dss4 :: I 'U 'I8 'LE- , dss5 :: I 'U 'I1 'LE- } deriving stock (Generic, Data, Show, Eq)--instance BLen DSS where blen = blenGeneric cNoSum---instance BLen DSS where type CBLen DSS = CBLenGeneric Void DSS-instance Put DSS where put = putGeneric cNoSum-instance Get DSS where get = getGeneric cNoSum--data DCS = DCS1 {- DSS -} | DCS2 | DCS3 | DCS4 | DCS5- deriving stock (Generic, Data, Show, Eq)--type BrSumDCS = I 'U 'I1 'LE-brCfgDCS :: BR.Cfg BrSumDCS-brCfgDCS = BR.cfg $ BR.cSumTagHex $ drop 3----instance BLen DCS where blen = BR.blenGeneric brCfgDCS-instance BLen DCS where type CBLen DCS = CBLenGeneric BrSumDCS DCS-instance Put DCS where put = putGeneric brCfgDCS-instance Get DCS where get = getGeneric brCfgDCS--data DX = DX DU- deriving stock (Generic, Data, Show, Eq)----instance BLen DX where blen = blenGeneric brCfgNoSum-instance BLen DX where type CBLen DX = CBLenGeneric Void DX-instance Put DX where put = putGeneric cNoSum-instance Get DX where get = getGeneric cNoSum
− src/Binrep/Example/FileTable.hs
@@ -1,105 +0,0 @@-module Binrep.Example.FileTable where--import Binrep-import Refined hiding ( Weaken )-import Refined.Unsafe-import Binrep.Type.Common ( Endianness(..) )-import Binrep.Type.Int-import Binrep.Type.LenPfx-import FlatParse.Basic qualified as FP-import Data.ByteString qualified as B-import Strongweak-import Strongweak.Generic---import Data.Map ( Map )-import GHC.Generics ( Generic )-import GHC.Exts-import Data.Vector.Sized qualified as V-import Data.Word--type BS = B.ByteString---- We're unable to put one invariant in the types: an entry can't be placed past--- the maximum offset. Validating that requires quite a lot of work: we have to--- do much of the layouting work, which will be repeated for serializing. This--- is a downside of phase separation, it crops up every now and then.------ The BLen instance will similarly be a bit complex, but it could probably be--- implemented with similar code to strengthening.-newtype Table s a = Table { unTable :: SW s (LenPfx 'I1 'LE (Entry s a)) }--instance (Put a, BLen a) => Put (Table 'Strong a) where put = putFileTable--putFileTable :: (Put a, BLen a) => Table 'Strong a -> Builder-putFileTable (Table a@(LenPfx es)) =- let es' = V.map prepEntry es- osBase = V.sum $ V.map (\(l, _, _) -> l) es'- in case V.foldl go ((fromIntegral osBase) - 1, mempty, mempty) es' of- (_, bh, bd) -> put (lenPfxSize a) <> bh <> bd- where- go :: (Word8, Builder, Builder) -> (BLenT, Word8 -> Builder, BS) -> (Word8, Builder, Builder)- go (os, bh, bd) (_, eh, ed) = (os+fromIntegral (B.length ed), bh<>eh os, bd<>put ed)--prepEntry :: (Put a, BLen a) => Entry 'Strong a -> (BLenT, Word8 -> Builder, BS)-prepEntry (Entry nm bs) = (l, b, bs')- where- bs' = unrefine bs- b os =- put nm <> put os <> put (fromIntegral (B.length bs') :: Word8)- l = blen nm + 1 + 1 + blen bs'--instance Get a => Get (Table 'Strong a) where get = getFileTable--getFileTable :: Get a => Getter (Table 'Strong a)-getFileTable = FP.withAddr# $ \addr# -> Table <$> getLenPfx (getWith addr#)--{--This is certainly a weird type.-- * Can use regular strongweak generics- * Has no 'Get' instance- * Has a 'GetWith Addr#' instance- * Has no 'Put' instance- * Has no 'PutWith' instance--You can't serialize an 'Entry' by itself, because it serializes to two-artifacts, a header entry and the associated data. Now I see why Kaitai Struct-was having trouble with serializing this sort of type.--}-data Entry s a = Entry- { entryName :: a- , entryData :: SW s (Refined (SizeLessThan (IMax 'U 'I1)) BS)- } deriving stock (Generic)-deriving stock instance Show a => Show (Entry 'Weak a)-deriving stock instance Eq a => Eq (Entry 'Weak a)-deriving stock instance Show a => Show (Entry 'Strong a)-deriving stock instance Eq a => Eq (Entry 'Strong a)-instance Weaken (Entry 'Strong a) where- type Weak (Entry 'Strong a) = Entry 'Weak a- weaken = weakenGeneric-instance Strengthen (Entry 'Strong a) where- strengthen = strengthenGeneric--instance Get a => GetWith Addr# (Entry 'Strong a) where getWith = getEntry--getEntry :: Get a => Addr# -> Getter (Entry 'Strong a)-getEntry addr# = do- name <- get- dat <- FP.withAnyWord8# $ \offset# -> FP.withAnyWord8# $ \len# ->- FP.takeBsOffAddr# addr# (w8i# offset#) (w8i# len#)- return $ Entry name (reallyUnsafeRefine dat)--w8i# :: Word8# -> Int#-w8i# w# = word2Int# (word8ToWord# w#)--exBs :: BS-exBs = B.pack- [ 0x02- , 0x30, 0x31, 0x32, 0x00- , 12 -- <- offset!!- , 0x01- , 0x39, 0x38, 0x00- , 13- , 0x01- , 0xFF- , 0xF0- ]
− src/Binrep/Example/Tar.hs
@@ -1,61 +0,0 @@-module Binrep.Example.Tar where--import Binrep-import Binrep.Generic-import Binrep.Type.NullPadded-import Binrep.Type.AsciiNat--import GHC.Generics ( Generic )--import Data.Word ( Word8 )--import GHC.TypeNats--import Data.ByteString qualified as B--import FlatParse.Basic qualified as FP--type BS = B.ByteString---- | The naturals in tars are sized octal ASCII digit strings that end with a--- null byte (and may start with leading ASCII zeroes). The size includes the--- terminating null, so you get @n-1@ digits. What a farce.------ Don't use this constructor directly! The size must be checked to ensure it--- fits.-newtype TarNat n = TarNat { getTarNat :: AsciiNat 8 }- deriving stock (Generic, Show, Eq)--instance KnownNat n => BLen (TarNat n) where- type CBLen (TarNat n) = n---- | No need to check for underflow etc. as TarNat guarantees good sizing.-instance KnownNat n => Put (TarNat n) where- put (TarNat an) = put pfxNulls <> put an <> put @Word8 0x00- where- pfxNulls = B.replicate (fromIntegral pfxNullCount) 0x30- pfxNullCount = n - blen an - 1- n = typeNatToBLen @n--instance KnownNat n => Get (TarNat n) where- get = do- an <- FP.isolate (fromIntegral (n - 1)) get- get @Word8 >>= \case- 0x00 -> return $ TarNat an- w -> eBase $ EExpectedByte 0x00 w- where- n = typeNatToBLen @n---- Partial header-data Tar = Tar- { tarFileName :: NullPadded 100 BS- , tarFileMode :: TarNat 8- , tarFileUIDOwner :: TarNat 8- , tarFileUIDGroup :: TarNat 8- , tarFileFileSize :: TarNat 12- , tarFileLastMod :: TarNat 12- } deriving stock (Generic, Show, Eq)--instance BLen Tar where blen = blenGeneric cNoSum-instance Put Tar where put = putGeneric cNoSum-instance Get Tar where get = getGeneric cNoSum
− src/Binrep/Example/Tiff.hs
@@ -1,58 +0,0 @@-{-# LANGUAGE AllowAmbiguousTypes #-}-{-# LANGUAGE UndecidableInstances #-}--module Binrep.Example.Tiff where--import Binrep-import Binrep.Generic-import Binrep.Type.Common ( Endianness(..) )-import Binrep.Type.Int-import Binrep.Type.Magic-import Binrep.Type.Byte-import FlatParse.Basic ( (<|>) )--import GHC.Generics ( Generic )-import Data.Data ( Data, Typeable )-import GHC.TypeLits--import Data.ByteString qualified as B--type W8 = I 'U 'I1 'LE--data Tiff where- Tiff :: (Put (I 'U 'I4 end), bs ~ MagicBytes (TiffMagic end), ReifyBytes bs, KnownNat (Length bs)) => TiffBody end -> Tiff--instance Show Tiff where- show (Tiff body) = "Tiff " <> show body--data TiffBody (end :: Endianness) = TiffBody- { tiffBodyMagic :: Magic (TiffMagic end)- , tiffBodyExInt :: I 'U 'I4 end- } deriving stock (Generic, Show, Eq)-deriving stock instance (KnownSymbol (TiffMagic end), Typeable end) => Data (TiffBody end)--instance (bs ~ MagicBytes (TiffMagic end), KnownNat (Length bs)) => BLen (TiffBody end) where- blen = blenGeneric cNoSum-instance (bs ~ MagicBytes (TiffMagic end), ReifyBytes bs, irep ~ I 'U 'I4 end, Put irep) => Put (TiffBody end) where- put = putGeneric cNoSum-instance (bs ~ MagicBytes (TiffMagic end), ReifyBytes bs, irep ~ I 'U 'I4 end, Get irep) => Get (TiffBody end) where- get = getGeneric cNoSum--instance BLen Tiff where- blen (Tiff body) = blen body--instance Put Tiff where- put (Tiff body) = put body--instance Get Tiff where- get = fmap Tiff (get @(TiffBody 'LE)) <|> fmap Tiff (get @(TiffBody 'BE))--type family TiffMagic (end :: Endianness) :: Symbol where- TiffMagic 'LE = "II"- TiffMagic 'BE = "MM"--tiffLEbs :: B.ByteString-tiffLEbs = B.pack [0x49, 0x49, 0xFF, 0x00, 0x00, 0x00]--tiffBEbs :: B.ByteString-tiffBEbs = B.pack [0x4D, 0x4D, 0x00, 0x00, 0x00, 0xFF]
− src/Binrep/Example/Wav.hs
@@ -1,27 +0,0 @@-module Binrep.Example.Wav where--import Binrep-import Binrep.Generic-import Binrep.Type.Common ( Endianness(..) )-import Binrep.Type.Int-import Binrep.Type.Magic--import GHC.Generics ( Generic )-import Data.Data ( Data )--type End = 'LE-type W32 = I 'U 'I4 End-type W16 = I 'U 'I2 End--data WavHeader = WavHeader- { wavHeaderMagic :: Magic "RIFF"- , wavHeaderChunkSize :: W32 -- file size - 8- , wavHeaderFmt :: Magic "WAVE"- , wavHeaderFmtChunkMarker :: Magic "fmt "- , wavHeaderFmtType :: W16- , wavHeaderChannels :: W16- } deriving stock (Generic, Data, Show, Eq)--instance BLen WavHeader where blen = blenGeneric cNoSum-instance Put WavHeader where put = putGeneric cNoSum-instance Get WavHeader where get = getGeneric cNoSum
src/Binrep/Extra/HexByteString.hs view
@@ -76,7 +76,7 @@ parseHexByte = do c1 <- MC.hexDigitChar c2 <- MC.hexDigitChar- return $ 0x10 * fromIntegral (Char.digitToInt c1) + fromIntegral (Char.digitToInt c2)+ pure $ 0x10 * fromIntegral (Char.digitToInt c1) + fromIntegral (Char.digitToInt c2) -- | Pretty print to default format @00 12 AB FF@: space between each byte, all -- caps.
src/Binrep/Generic.hs view
@@ -1,79 +1,16 @@--- | Derive 'BLen', 'Put', 'Get' and 'CBLen' instances generically.--module Binrep.Generic- ( Cfg(..), cfg- , cSumTagHex, cSumTagNullTerm, cDef- , cNoSum, EDerivedSumInstanceWithNonSumCfg(..)- , blenGeneric, putGeneric, getGeneric, CBLenGeneric- ) where--import Binrep.Generic.Internal-import Binrep.Generic.BLen-import Binrep.Generic.Put-import Binrep.Generic.Get-import Binrep.Generic.CBLen+module Binrep.Generic where -import Binrep.Type.ByteString ( AsByteString, Rep(..) )-import Refined.Unsafe ( reallyUnsafeRefine )+import Binrep.Type.NullTerminated+import Data.ByteString qualified as B import Data.Text qualified as Text import Data.Text.Encoding qualified as Text--import Numeric ( readHex )--import Data.Void ( Void )-import Control.Exception ( Exception, throw )--import Binrep.Util ( tshow )--cfg :: (Eq a, Show a) => (String -> a) -> Cfg a-cfg f = Cfg { cSumTag = f, cSumTagEq = (==), cSumTagShow = tshow }---- | Obtain the tag for a sum type value by applying a function to the--- constructor name, and reading the result as a hexadecimal number.-cSumTagHex :: forall a. Integral a => (String -> String) -> String -> a-cSumTagHex f = forceRead . readHex . f---- | Successfully parse exactly one result, or runtime error.-forceRead :: [(a, String)] -> a-forceRead = \case [] -> error "no parse"- [(x, "")] -> x- [(_x, _)] -> error "incomplete parse"- (_:_) -> error "too many parses (how??)"+import Refined.Unsafe --- | Obtain the tag for a sum type value using the constructor name directly--- (with a null terminator).+-- | Turn a constructor name into a prefix tag by adding a null terminator. ----- This is probably not what you want in a binary representation, but it's safe--- and may be useful for debugging.+-- 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. I haven't confirmed that, but I'm--- fairly certain.-cSumTagNullTerm :: String -> AsByteString 'C-cSumTagNullTerm = reallyUnsafeRefine . Text.encodeUtf8 . Text.pack---- | Default generic derivation configuration, using 'cSumTagNullTerm'.-cDef :: Cfg (AsByteString 'C)-cDef = cfg cSumTagNullTerm---- | Special generic derivation configuration you may use for non-sum data--- types.------ When generically deriving binrep instances for a non-sum type, you may like--- to ignore sum tag handling. You could use 'cDef', but this will silently--- change behaviour if your type becomes a sum type. This configuration will--- generate clear runtime errors when used with a sum type.------ By selecting 'Void' for the sum tag type, consumption actions (serializing,--- getting length in bytes) will runtime error, while generation actions--- (parsing) will hit the 'Void' instance first and always safely error out.-cNoSum :: Cfg Void-cNoSum = cfg $ \_ -> throw EDerivedSumInstanceWithNonSumCfg---- This indirection enables us to test for this precise exception being thrown--- in an incorrect configuration! Awesome!-data EDerivedSumInstanceWithNonSumCfg = EDerivedSumInstanceWithNonSumCfg-instance Show EDerivedSumInstanceWithNonSumCfg where- show EDerivedSumInstanceWithNonSumCfg =- "Binrep.Generic.cNoSum: non-sum generic derivation configuration used with a sum type"-instance Exception EDerivedSumInstanceWithNonSumCfg+-- are UTF-8 with no null bytes allowed. Fairly certain that's true.+nullTermCstrPfxTag :: String -> NullTerminated B.ByteString+nullTermCstrPfxTag = reallyUnsafeRefine . Text.encodeUtf8 . Text.pack
− src/Binrep/Generic/BLen.hs
@@ -1,52 +0,0 @@-{-# LANGUAGE UndecidableInstances #-} -- required for TypeError >:(--module Binrep.Generic.BLen where--import GHC.Generics-import GHC.TypeLits ( TypeError )--import Binrep.BLen-import Binrep.Generic.Internal-import Util.Generic--blenGeneric :: (Generic a, GBLen (Rep a), BLen w) => Cfg w -> a -> BLenT-blenGeneric cfg = gblen cfg . from--class GBLen f where- gblen :: BLen w => Cfg w -> f p -> BLenT---- | Empty constructor.-instance GBLen U1 where- gblen _ U1 = 0---- | Field.-instance BLen c => GBLen (K1 i c) where- gblen _ (K1 c) = blen c---- | Product type fields are consecutive.-instance (GBLen l, GBLen r) => GBLen (l :*: r) where- gblen cfg (l :*: r) = gblen cfg l + gblen cfg r---- | Constructor sums are differentiated by a prefix tag.-instance GBLenSum (l :+: r) => GBLen (l :+: r) where- gblen = gblensum---- | Refuse to derive instance for void datatype.-instance TypeError GErrRefuseVoid => GBLen V1 where- gblen = undefined---- | Any datatype, constructor or record.-instance GBLen f => GBLen (M1 i d f) where- gblen cfg = gblen cfg . unM1------------------------------------------------------------------------------------class GBLenSum f where- gblensum :: BLen w => Cfg w -> f p -> BLenT--instance (GBLenSum l, GBLenSum r) => GBLenSum (l :+: r) where- gblensum cfg = \case L1 l -> gblensum cfg l- R1 r -> gblensum cfg r--instance (GBLen f, Constructor c) => GBLenSum (C1 c f) where- gblensum cfg x = blen ((cSumTag cfg) (conName' @c)) + gblen cfg (unM1 x)
− src/Binrep/Generic/CBLen.hs
@@ -1,70 +0,0 @@-{-# LANGUAGE UndecidableInstances #-}--{- | _Experimental._ Generically derive 'CBLen' type family instances.--A type having a valid 'CBLen' instance usually indicates one of the following:-- * it's a primitive, or extremely simple- * it holds size information in its type- * it's constructed from other constant byte length types--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.Generic.CBLen where--import Binrep.BLen-import Binrep.Generic.Internal--import GHC.Generics-import GHC.TypeLits-import Data.Kind--import Data.Type.Equality-import Data.Type.Bool--type CBLenGeneric w a = GCBLen w (Rep a)--type family GCBLen w (f :: k -> Type) :: Natural where- GCBLen _ U1 = 0- GCBLen _ (K1 i c) = CBLen c- GCBLen w (l :*: r) = GCBLen w l + GCBLen w r-- GCBLen w (l :+: r) = CBLen w + GCBLenCaseMaybe (GCBLenSum w (l :+: r))-- GCBLen _ V1 = TypeError GErrRefuseVoid- GCBLen w (M1 _ _ f) = GCBLen w f----type family GCBLenSum w (f :: k -> Type) :: Maybe Natural where-type family GCBLenSum w (f :: k -> Type) where- GCBLenSum w (C1 ('MetaCons name _ _) f) = JustX (GCBLen w f) name- GCBLenSum w (l :+: r) = MaybeEq (GCBLenSum w l) (GCBLenSum w r)--type family MaybeEq a b where- MaybeEq (JustX n nName) (JustX m _) = If (n == m) (JustX n nName) NothingX- MaybeEq _ _ = NothingX---- | I don't know how to pattern match in types without writing type families.-type family GCBLenCaseMaybe a where- GCBLenCaseMaybe (JustX n _) = n- GCBLenCaseMaybe NothingX =- TypeError- ( 'Text "Two constructors didn't have equal constant size."- ':$$: 'Text "Sry dunno how to thread errors thru LOL"- )---- TODO rewrite this stuff to thread error info through!-data JustX a b-data NothingX
− src/Binrep/Generic/Get.hs
@@ -1,87 +0,0 @@-{-# LANGUAGE UndecidableInstances #-} -- required for TypeError >:(--module Binrep.Generic.Get where--import GHC.Generics-import GHC.TypeLits ( TypeError )--import Binrep.Get-import Binrep.Generic.Internal-import Util.Generic--import FlatParse.Basic qualified as FP-import Control.Applicative ( (<|>) )--import Numeric.Natural--getGeneric :: (Generic a, GGetD (Rep a), Get w) => Cfg w -> Getter a-getGeneric cfg = to <$> ggetD cfg--class GGetD f where- ggetD :: Get w => Cfg w -> Getter (f a)--instance (GGetC f, Datatype d) => GGetD (D1 d f) where- ggetD cfg = M1 <$> ggetC cfg (datatypeName' @d)--class GGetC f where- ggetC :: Get w => Cfg w -> String -> Getter (f a)---- | Refuse to derive instance for empty data types.-instance TypeError GErrRefuseVoid => GGetC V1 where- ggetC = undefined---- | TODO: Non-sum data types.-instance (GGetS f, Constructor c) => GGetC (C1 c f) where- ggetC cfg dStr = (M1 . snd) <$> ggetS cfg dStr (conName' @c) 0--class GGetS f where- ggetS :: Get w => Cfg w -> String -> String -> Natural -> Getter (Natural, (f a))---- | The empty constructor trivially succeeds without parsing anything.-instance GGetS U1 where- ggetS _ _ _ fIdx = pure (fIdx, U1)--instance (GGetS l, GGetS r) => GGetS (l :*: r) where- ggetS cfg dStr cStr fIdx = do- (fIdx', l) <- ggetS cfg dStr cStr fIdx- (fIdx'', r) <- ggetS cfg dStr cStr (fIdx'+1)- pure (fIdx'', l :*: r)--instance (Get a, Selector s) => GGetS (S1 s (Rec0 a)) where- ggetS _ dStr cStr fIdx = do- a <- getEWrap $ EGeneric dStr . EGenericField cStr sStr fIdx- pure (fIdx, M1 (K1 a))- where- sStr = selName'' @s-------------------------------------------------------------------------------------- | Constructor sums are differentiated by a prefix tag.-instance GGetCSum (l :+: r) => GGetC (l :+: r) where- ggetC cfg dStr = do- tag <- getEWrap $ EGeneric dStr . EGenericSum . EGenericSumTag- case ggetCSum cfg dStr tag of- Just parser -> parser- Nothing -> do- let tagPretty = cSumTagShow cfg $ tag- FP.err $ EGeneric dStr $ EGenericSum $ EGenericSumTagNoMatch [] tagPretty---- | TODO: Want to return an @Either [(String, Text)]@ indicating the--- constructors and their expected tags tested, but needs fiddling (can't use--- 'Alternative'). Pretty minor, but Aeson does it and it's nice.-class GGetCSum f where- ggetCSum :: Get w => Cfg w -> String -> w -> Maybe (Getter (f a))--instance (GGetCSum l, GGetCSum r) => GGetCSum (l :+: r) where- ggetCSum cfg dStr tag = l <|> r- where- l = fmap L1 <$> ggetCSum cfg dStr tag- r = fmap R1 <$> ggetCSum cfg dStr tag--instance (GGetS f, Constructor c) => GGetCSum (C1 c f) where- ggetCSum cfg dStr tag =- let cStr = conName' @c- cTag = (cSumTag cfg) cStr- in if (cSumTagEq cfg) tag cTag- then Just ((M1 . snd) <$> ggetS cfg dStr cStr 0)- else Nothing
− src/Binrep/Generic/Internal.hs
@@ -1,17 +0,0 @@-module Binrep.Generic.Internal where--import GHC.TypeLits-import Data.Text ( Text )--data Cfg a = Cfg- { cSumTag :: String -> a- -- ^ How to turn a constructor name into a byte tag.-- , cSumTagEq :: a -> a -> Bool- , cSumTagShow :: a -> Text- }---- | Common type error string for when GHC attempts to derive an binrep instance--- for a (the?) void datatype @V1@.-type GErrRefuseVoid =- 'Text "Refusing to derive binary representation for void datatype"
− src/Binrep/Generic/Put.hs
@@ -1,67 +0,0 @@-{-# LANGUAGE UndecidableInstances #-} -- required for TypeError >:(--module Binrep.Generic.Put where--import GHC.Generics-import GHC.TypeLits ( TypeError )--import Binrep.Put-import Binrep.Generic.Internal-import Util.Generic--putGeneric :: (Generic a, GPut (Rep a), Put w) => Cfg w -> a -> Builder-putGeneric cfg = gput cfg . from--class GPut f where- gput :: Put w => Cfg w -> f p -> Builder---- | Empty constructor.-instance GPut U1 where- gput _ U1 = mempty---- | Field.-instance Put c => GPut (K1 i c) where- gput _ = put . unK1---- | Product type fields are consecutive.-instance (GPut l, GPut r) => GPut (l :*: r) where- gput cfg (l :*: r) = gput cfg l <> gput cfg r---- | Constructor sums are differentiated by a prefix tag.-instance (GPutSum (l :+: r), GetConName (l :+: r)) => GPut (l :+: r) where- gput = gputsum---- | Refuse to derive instance for void datatype.-instance TypeError GErrRefuseVoid => GPut V1 where- gput = undefined---- | Any datatype, constructor or record.-instance GPut f => GPut (M1 i d f) where- gput cfg = gput cfg . unM1------------------------------------------------------------------------------------class GPutSum f where- gputsum :: Put w => Cfg w -> f a -> Builder--instance (GPutSum l, GPutSum r) => GPutSum (l :+: r) where- gputsum cfg = \case L1 a -> gputsum cfg a- R1 a -> gputsum cfg a--instance (GPut r, Constructor c) => GPutSum (C1 c r) where- gputsum cfg x = putTag <> putConstructor- where putTag = put $ (cSumTag cfg) (conName' @c)- putConstructor = gput cfg $ unM1 x--------- | Get the name of the constructor of a sum datatype.-class GetConName f where- getConName :: f a -> String--instance (GetConName a, GetConName b) => GetConName (a :+: b) where- getConName (L1 x) = getConName x- getConName (R1 x) = getConName x--instance Constructor c => GetConName (C1 c a) where- getConName = conName
− src/Binrep/Get.hs
@@ -1,145 +0,0 @@-{-# LANGUAGE FunctionalDependencies #-}--module Binrep.Get- ( Getter, Get(..), runGet, runGetter- , E(..), EBase(..), EGeneric(..), EGenericSum(..)- , eBase- , getEWrap, getEBase- , cutEBase- , GetWith(..), runGetWith- ) where--import FlatParse.Basic qualified as FP--import Data.ByteString qualified as B--import GHC.Exts ( TYPE, type LiftedRep )--import Data.Word-import Data.Int-import Data.Void ( Void )--import GHC.Generics ( Generic )--import Data.Text ( Text )--import Binrep.BLen ( BLenT )--import Numeric.Natural--type Getter a = FP.Parser E a--data E- = EBase EBase-- | EGeneric String {- ^ datatype name -} EGeneric-- deriving stock (Eq, Show, Generic)--eBase :: EBase -> Getter a-eBase = FP.err . EBase---- | TODO confirm correct operation (error combination)-getEWrap :: Get a => (E -> E) -> Getter a-getEWrap f = FP.cutting get (f $ EBase EFail) (\e _ -> f e)--getEBase :: Get a => EBase -> Getter a-getEBase = FP.cut get . EBase--cutEBase :: Getter a -> EBase -> Getter a-cutEBase f e = FP.cut f $ EBase e--data EBase- = ENoVoid- | EFail-- | EExpectedByte Word8 Word8- -- ^ expected first, got second-- | EOverlong BLenT BLenT- -- ^ expected first, got second-- | EExpected B.ByteString B.ByteString- -- ^ expected first, got second-- | EFailNamed String- -- ^ known fail-- | EFailParse String B.ByteString Word8- -- ^ parse fail (where you parse a larger object, then a smaller one in it)-- | ERanOut Natural- -- ^ ran out of input, needed precisely @n@ bytes for this part (n > 0)-- deriving stock (Eq, Show, Generic)--data EGeneric- = EGenericSum EGenericSum- | EGenericField String (Maybe String) Natural E- deriving stock (Eq, Show, Generic)--data EGenericSum- = EGenericSumTag E- | EGenericSumTagNoMatch [String] Text- deriving stock (Eq, Show, Generic)--class Get a where- -- | Parse from binary.- get :: Getter a--runGet :: Get a => B.ByteString -> Either E (a, B.ByteString)-runGet = runGetter get--runGetter :: Getter a -> B.ByteString -> Either E (a, B.ByteString)-runGetter g bs = case FP.runParser g bs of- FP.OK a bs' -> Right (a, bs')- FP.Fail -> Left $ EBase EFail- FP.Err e -> Left e---- | Impossible to parse 'Void'.-instance Get Void where- get = eBase ENoVoid---- | Parse heterogeneous lists in order. No length indicator, so either fails or--- succeeds by reaching EOF. Probably not what you usually want, but sometimes--- used at the "top" of binary formats.-instance Get a => Get [a] where- get = go- where- go = do- FP.withOption FP.eof (\() -> pure []) $ do- a <- get- as <- go- pure $ a : as--instance (Get a, Get b) => Get (a, b) where- get = do- a <- get- b <- get- return (a, b)--instance Get B.ByteString where- get = FP.takeRestBs--instance Get Word8 where get = cutEBase FP.anyWord8 (ERanOut 1)-instance Get Int8 where get = cutEBase FP.anyInt8 (ERanOut 1)---- | A type that can be parsed from binary given some environment.------ Making this levity polymorphic makes things pretty strange, but is useful.--- See @Binrep.Example.FileTable@.-class GetWith (r :: TYPE rep) a | a -> r where- -- | Parse from binary with the given environment.- getWith :: r -> Getter a- -- can no longer provide default implementation due to levity polymorphism- --default getWith :: Get a => r -> Getter a- --getWith _ = get----deriving anyclass instance Get a => GetWith r [a]---- Note that @r@ is not levity polymorphic, GHC forces it to be lifted. You--- can't bind (LHS) a levity polymorphic value.-runGetWith- :: GetWith (r :: TYPE LiftedRep) a- => r -> B.ByteString -> Either E (a, B.ByteString)-runGetWith r bs = runGetter (getWith r) bs
+ src/Binrep/Get/Flatparse.hs view
@@ -0,0 +1,268 @@+{-# LANGUAGE UndecidableInstances #-} -- required below GHC 9.6+{-# LANGUAGE BlockArguments #-}++module Binrep.Get.Flatparse+ ( Getter, Get(..), runGet, runGetter+ , E(..), EBase(..), EGeneric(..), EGenericSum(..)+ , eBase+ , getEBase+ -- , GetWith(..), runGetWith+ , getGenericNonSum, getGenericSum+ ) where++import FlatParse.Basic qualified as FP+import Data.ByteString qualified as B++import Binrep.Util.Class+import GHC.TypeLits ( TypeError )++import Data.Void+import Data.Word+import Data.Int+import Bytezap+import Bytezap.Bytes qualified as BZ++import Data.Text ( Text )++import Numeric.Natural++import GHC.Generics+import Generic.Data.Function.Traverse+import Generic.Data.Function.Common+import Generic.Data.Rep.Assert++import GHC.Exts ( minusAddr#, Int(I#) )++type Getter a = FP.Parser E a++-- | Structured parse error.+data E+ = E Int EMiddle++ -- | 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++ deriving stock (Eq, Show, Generic)++data EMiddle++ -- | Parse error with no further context.+ = EBase EBase++ -- | Somehow, we got two parse errors.+ --+ -- I have a feeling that seeing this indicates a problem in your code.+ | EAnd E EBase++ -- | Parse error decorated with generic info.+ --+ -- Should not be set except by library code.+ | EGeneric String {- ^ data type name -} (EGeneric E)++ deriving stock (Eq, Show, Generic)++data EBase+ = EExpectedByte Word8 Word8+ -- ^ expected first, got second++ | EOverlong Int Int+ -- ^ expected first, got second++ | EExpected B.ByteString B.ByteString+ -- ^ expected first, got second++ | EFailNamed String+ -- ^ known fail++ | EFailParse String B.ByteString Word8+ -- ^ parse fail (where you parse a larger object, then a smaller one in it)++ | ERanOut Int+ -- ^ 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.++ deriving stock (Eq, Show, Generic)++-- | 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)++ -- | Parse error in a constructor field.+ | EGenericField+ String -- ^ constructor name+ (Maybe String) -- ^ field record name (if present)+ Natural -- ^ field index in constructor+ e -- ^ field parse error+ deriving stock (Eq, Show, Generic)++data EGenericSum e+ -- | Parse error parsing prefix tag.+ = EGenericSumTag e++ -- | Unable to match a constructor to the parsed prefix tag.+ | EGenericSumTagNoMatch+ [String] -- ^ constructors tested+ Text -- ^ prettified prefix tag+ deriving stock (Eq, Show, Generic)++eBase :: EBase -> Getter a+eBase eb = FP.ParserT \_fp eob s st ->+ let os = I# (minusAddr# eob s)+ in FP.Err# st (E os $ EBase eb)++getEBase :: Getter a -> EBase -> Getter a+getEBase (FP.ParserT f) eb =+ FP.ParserT \fp eob s st ->+ let os = I# (minusAddr# eob s)+ in case f fp eob s st of+ FP.Fail# st' -> FP.Err# st' (E os $ EBase eb)+ FP.Err# st' e -> FP.Err# st' (E os $ EAnd e eb)+ x -> x++-- | Parse. On parse error, coat it in a generic context layer.+getWrapGeneric :: Get a => String -> (E -> EGeneric E) -> Getter a+getWrapGeneric = getWrapGeneric' get++getWrapGeneric' :: Getter a -> String -> (E -> EGeneric E) -> Getter a+getWrapGeneric' (FP.ParserT f) cd fe =+ FP.ParserT \fp eob s st ->+ let os = I# (minusAddr# eob s)+ in case f fp eob s st of+ FP.Fail# st' -> FP.Err# st' (E os $ EGeneric cd $ fe EFail)+ FP.Err# st' e -> FP.Err# st' (E os $ EGeneric cd $ fe e)+ x -> x++class Get a where+ -- | Parse from binary.+ get :: Getter a++runGet :: Get a => B.ByteString -> Either E (a, B.ByteString)+runGet = runGetter get++runGetter :: Getter a -> B.ByteString -> Either E (a, B.ByteString)+runGetter g bs = case FP.runParser g bs of+ FP.OK a bs' -> Right (a, bs')+ FP.Fail -> Left EFail+ FP.Err e -> Left e++instance GenericTraverse (FP.Parser E) where+ type GenericTraverseC (FP.Parser E) a = Get a+ genericTraverseAction cd cc mcs si =+ getWrapGeneric cd $ EGenericField cc mcs si++instance GenericTraverseSum (FP.Parser E) where+ genericTraverseSumPfxTagAction cd =+ getWrapGeneric cd $ EGenericSum . EGenericSumTag+ -- TODO proper offset info+ genericTraverseSumNoMatchingCstrAction cd cstrs ptText =+ FP.err $ E 0 $ EGeneric cd $ EGenericSum $ EGenericSumTagNoMatch cstrs ptText++getGenericNonSum+ :: forall {cd} {f} {asserts} a+ . (Generic a, Rep a ~ D1 cd f, GTraverseNonSum cd (FP.Parser E) f+ , asserts ~ '[ 'NoEmpty, 'NoSum], ApplyGCAsserts asserts f)+ => Getter a+getGenericNonSum = genericTraverseNonSum @asserts++getGenericSum+ :: forall {cd} {f} {asserts} pt a+ . ( Generic a, Rep a ~ D1 cd f, GTraverseSum 'SumOnly cd (FP.Parser E) f+ , Get pt+ , asserts ~ '[ 'NoEmpty, 'NeedSum], ApplyGCAsserts asserts f)+ => PfxTagCfg pt -> Getter a+getGenericSum = genericTraverseSum @'SumOnly @asserts++instance TypeError ENoEmpty => Get Void where get = undefined+instance TypeError ENoSum => Get (Either a b) where get = undefined++-- | Parse a bytestring and... immediate reserialize it.+--+-- Note that this _does_ perform work: we make a new bytestring so we don't rely+-- on the input bytestring. To use the input bytestring directly, see+-- "Binrep.Type.Thin".+instance Get Write where+ {-# INLINE get #-}+ get = fmap BZ.byteString $ fmap B.copy $ FP.takeRest++-- | Unit type parses nothing.+instance Get () where+ {-# INLINE get #-}+ get = pure ()++-- | Parse tuples left-to-right.+instance (Get l, Get r) => Get (l, r) where+ {-# INLINE get #-}+ get = do+ l <- get+ r <- get+ pure (l, r)++-- | Parse elements until EOF. Sometimes used at the "top" of binary formats.+instance Get a => Get [a] where+ get = go+ where+ go = do+ FP.withOption FP.eof (\() -> pure []) $ do+ a <- get+ as <- go+ pure $ a : as++-- | Return the rest of the input.+--+-- A plain unannotated bytestring isn't very useful -- you'll usually want to+-- null-terminate or length-prefix it.+--+-- Note that this _does_ perform work: we make a new bytestring so we don't rely+-- on the input bytestring. To use the input bytestring directly, see+-- "Binrep.Type.Thin".+instance Get B.ByteString where+ {-# INLINE get #-}+ get = B.copy <$> FP.takeRest++-- | Unsigned byte.+instance Get Word8 where get = getEBase FP.anyWord8 (ERanOut 1)++-- | Signed byte.+instance Get Int8 where get = getEBase FP.anyInt8 (ERanOut 1)++{-+Multi-byte machine integers require an endianness to use. A common wrapper is+defined in "Binrep.Type.Int".+-}++{-++-- | A type that can be parsed from binary given some environment.+--+-- Making this levity polymorphic makes things pretty strange, but is useful.+-- See @Binrep.Example.FileTable@.+class GetWith (r :: TYPE rep) a | a -> r where+ -- | Parse from binary with the given environment.+ getWith :: r -> Getter a+ -- can no longer provide default implementation due to levity polymorphism+ --default getWith :: Get a => r -> Getter a+ --getWith _ = get++--deriving anyclass instance Get a => GetWith r [a]++-- Note that @r@ is not levity polymorphic, GHC forces it to be lifted. You+-- can't bind (LHS) a levity polymorphic value.+runGetWith+ :: GetWith (r :: TYPE LiftedRep) a+ => r -> B.ByteString -> Either E (a, B.ByteString)+runGetWith r bs = runGetter (getWith r) bs++-}
− src/Binrep/Put.hs
@@ -1,69 +0,0 @@-module Binrep.Put where--import Mason.Builder qualified as Mason--import Data.ByteString qualified as B--import Data.Word-import Data.Int-import Data.Void ( Void, absurd )--type Builder = Mason.BuilderFor Mason.StrictByteStringBackend--class Put a where- -- | Serialize to binary.- put :: a -> Builder---- | Run the serializer.-runPut :: Put a => a -> B.ByteString-runPut = runBuilder . put--runBuilder :: Builder -> B.ByteString-runBuilder = Mason.toStrictByteString---- | Impossible to serialize 'Void'.-instance Put Void where- put = absurd---- | Serialize each element in order. No length indicator, so parse until either--- error or EOF. Usually not what you want, but sometimes used at the "top" of--- binary formats.-instance Put a => Put [a] where- put = mconcat . map put--instance (Put a, Put b) => Put (a, b) where- put (a, b) = put a <> put b---- | Serialize the bytestring as-is.------ Careful -- the only way you're going to be able to parse this is to read--- until EOF.-instance Put B.ByteString where- put = Mason.byteString- {-# INLINE put #-}---- need to give args for RankNTypes reasons I don't understand-instance Put Word8 where- put w = Mason.word8 w- {-# INLINE put #-}-instance Put Int8 where- put w = Mason.int8 w- {-# INLINE put #-}---- | Put with inlined checks via an environment.-class PutWith r a where- -- | Attempt to serialize to binary with the given environment.- putWith :: r -> a -> Either String Builder- default putWith :: Put a => r -> a -> Either String Builder- putWith _ = putWithout---- | Helper for wrapping a 'BinRep' into a 'BinRepWith' (for encoding).-putWithout :: Put a => a -> Either String Builder-putWithout = Right . put--instance Put a => PutWith r [a]---- | Run the serializer with the given environment.-runPutWith :: PutWith r a => r -> a -> Either String B.ByteString-runPutWith r a = case putWith r a of Left e -> Left e- Right x -> Right $ runBuilder x
+ src/Binrep/Put/Bytezap.hs view
@@ -0,0 +1,99 @@+{-# LANGUAGE UndecidableInstances #-} -- required below GHC 9.6+{-# OPTIONS_GHC -fno-warn-orphans #-} -- for generic data op instance++{- | 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 where++import Bytezap+import Bytezap.Poke.Bytes+import Bytezap.Poke.Int+import Data.ByteString qualified as B+import Binrep.BLen.Simple++import Binrep.Util.Class+import GHC.TypeLits ( TypeError )++import Data.Void+import Data.Word+import Data.Int++import GHC.Generics+import Generic.Data.Function.FoldMap+import Generic.Data.Function.Common+import Generic.Data.Rep.Assert++class Put a where put :: a -> Poke++runPut :: (BLen a, Put a) => a -> B.ByteString+runPut a = runPoke (blen a) (put a)+{-# INLINE runPut #-}++instance GenericFoldMap Poke where+ type GenericFoldMapC Poke a = Put a+ genericFoldMapF = put++-- | 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+putGenericNonSum = genericFoldMapNonSum @asserts++-- | 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 'String's. 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+putGenericSum = genericFoldMapSum @'SumOnly @asserts++instance TypeError ENoEmpty => Put Void where put = undefined+instance TypeError ENoSum => Put (Either a b) where put = undefined++instance Put Write where+ {-# INLINE put #-}+ put = writePoke++-- | Fairly useless because 'Poke' doesn't have a 'BLen' instance.+instance Put Poke where+ {-# INLINE put #-}+ put = id++-- | Unit type serializes to nothing. How zen.+instance Put () where+ {-# INLINE put #-}+ put = mempty++instance (Put l, Put r) => Put (l, r) where+ {-# INLINE put #-}+ put (l, r) = put l <> put r++instance Put a => Put [a] where+ {-# INLINE put #-}+ put = mconcat . map put++instance Put B.ByteString where+ {-# INLINE put #-}+ put = byteString++instance Put Word8 where+ {-# INLINE put #-}+ put = w8++instance Put Int8 where+ {-# INLINE put #-}+ put = i8
+ src/Binrep/Put/Mason.hs view
@@ -0,0 +1,102 @@+{-# OPTIONS_GHC -fno-warn-orphans #-} -- for generic data op instance++-- TODO some instances are wrong, Void should be typeerror++module Binrep.Put.Mason where++import Mason.Builder qualified as Mason++import Data.ByteString qualified as B++import Data.Word+import Data.Int+import Data.Void ( Void, absurd )++import GHC.Generics+import Generic.Data.Function.FoldMap+import Generic.Data.Function.Common+import Generic.Data.Rep.Assert++type Builder = Mason.BuilderFor Mason.StrictByteStringBackend++class Put a where+ -- | Serialize to binary.+ put :: a -> Builder++-- | Run the serializer.+runPut :: Put a => a -> B.ByteString+runPut = runBuilder . put++runBuilder :: Builder -> B.ByteString+runBuilder = Mason.toStrictByteString++instance GenericFoldMap Builder where+ type GenericFoldMapC Builder a = Put a+ genericFoldMapF = put++-- | 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+putGenericNonSum = genericFoldMapNonSum @asserts++-- | 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 'String's. 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+putGenericSum = genericFoldMapSum @'SumOnly @asserts++-- | Impossible to serialize 'Void'.+instance Put Void where+ put = absurd++-- | Serialize each element in order. No length indicator, so parse until either+-- error or EOF. Usually not what you want, but sometimes used at the "top" of+-- binary formats.+instance Put a => Put [a] where+ put = mconcat . map put++instance (Put a, Put b) => Put (a, b) where+ put (a, b) = put a <> put b++-- | Serialize the bytestring as-is.+--+-- Careful -- the only way you're going to be able to parse this is to read+-- until EOF.+instance Put B.ByteString where+ put = Mason.byteString+ {-# INLINE put #-}++-- need to give args for RankNTypes reasons I don't understand+instance Put Word8 where+ put w = Mason.word8 w+ {-# INLINE put #-}+instance Put Int8 where+ put w = Mason.int8 w+ {-# INLINE put #-}++-- | Put with inlined checks via an environment.+class PutWith r a where+ -- | Attempt to serialize to binary with the given environment.+ putWith :: r -> a -> Either String Builder+ default putWith :: Put a => r -> a -> Either String Builder+ putWith _ = putWithout++-- | Helper for wrapping a 'BinRep' into a 'BinRepWith' (for encoding).+putWithout :: Put a => a -> Either String Builder+putWithout = Right . put++instance Put a => PutWith r [a]++-- | Run the serializer with the given environment.+runPutWith :: PutWith r a => r -> a -> Either String B.ByteString+runPutWith r a = case putWith r a of Left e -> Left e+ Right x -> Right $ runBuilder x
− src/Binrep/Type/AsciiNat.hs
@@ -1,110 +0,0 @@-{-| Naturals represented via ASCII numerals.--A concept which sees occasional use in places where neither speed nor size-efficiency matter.--The tar file format uses it, apparently to sidestep making a decision on byte-ordering. Though digits are encoded "big-endian", so, uh. I don't get it.--I don't really see the usage of these. It seems silly and inefficient, aimed-solely at easing debugging.--}--{-# LANGUAGE AllowAmbiguousTypes #-}--module Binrep.Type.AsciiNat where--import Binrep-import Binrep.Util ( natVal'' )--import Data.Word ( Word8 )-import Data.List.NonEmpty ( NonEmpty( (:|) ) )-import Mason.Builder qualified as Mason-import Data.ByteString qualified as B-import Data.Semigroup ( sconcat )--import GHC.TypeNats ( Natural, KnownNat )-import GHC.Num.Natural ( naturalSizeInBase#, naturalToWord# )--import GHC.Generics ( Generic )-import Data.Data ( Data )-import Numeric ( showOct, showHex, showBin, showInt )---- | A 'Natural' represented in binary as an ASCII string, where each character--- a is a digit in the given base (> 1).------ 'Show' instances display the stored number in the given base. If the base has--- a common prefix (e.g. @0x@ for hex), it is used.-newtype AsciiNat (base :: Natural) = AsciiNat { getAsciiNat :: Natural }- deriving stock (Generic, Data)- deriving (Eq, Ord) via Natural--instance Show (AsciiNat 2) where showsPrec _ n = showString "0b" . showBin (getAsciiNat n)-instance Show (AsciiNat 8) where showsPrec _ n = showString "0o" . showOct (getAsciiNat n)-instance Show (AsciiNat 10) where showsPrec _ n = showInt (getAsciiNat n)-instance Show (AsciiNat 16) where showsPrec _ n = showString "0x" . showHex (getAsciiNat n)---- | Compare two 'AsciiNat's with arbitrary bases.-asciiNatCompare :: AsciiNat b1 -> AsciiNat b2 -> Ordering-asciiNatCompare (AsciiNat n1) (AsciiNat n2) = compare n1 n2---- | The bytelength of an 'AsciiNat' is the number of digits in the number in--- the given base. We can calculate this generically with great efficiency--- using GHC primitives.-instance KnownNat base => BLen (AsciiNat base) where- blen (AsciiNat n) = wordToBLen# (naturalSizeInBase# (naturalToWord# base) n)- where base = natVal'' @base------------------------------------------------------------------------------------instance Put (AsciiNat 8) where- put = natToAsciiBytes (+ 0x30) 8 . getAsciiNat--instance Get (AsciiNat 8) where- get = do- bs <- get- case asciiBytesToNat octalFromAsciiDigit 8 bs of- Left w -> eBase $ EFailParse "hex ASCII natural" bs w- Right n -> return $ AsciiNat n--octalFromAsciiDigit :: Word8 -> Maybe Word8-octalFromAsciiDigit = \case- 0x30 -> Just 0- 0x31 -> Just 1- 0x32 -> Just 2- 0x33 -> Just 3- 0x34 -> Just 4- 0x35 -> Just 5- 0x36 -> Just 6- 0x37 -> Just 7- _ -> Nothing------------------------------------------------------------------------------------natToAsciiBytes :: (Word8 -> Word8) -> Natural -> Natural -> Builder-natToAsciiBytes f base =- sconcat . fmap (\w -> Mason.word8 w) . fmap f . digits @Word8 base--asciiBytesToNat :: (Word8 -> Maybe Word8) -> Natural -> B.ByteString -> Either Word8 Natural-asciiBytesToNat f base bs =- case B.foldr go (Right (0, 0)) bs of- Left w -> Left w- Right (n, _) -> Right n- where- go :: Word8 -> Either Word8 (Natural, Natural) -> Either Word8 (Natural, Natural)- go _ (Left w) = Left w- go w (Right (n, expo)) =- case f w of- Nothing -> Left w- Just d -> Right (n + fromIntegral d * base^expo, expo+1)--digits :: forall b a. (Integral a, Integral b) => a -> a -> NonEmpty b-digits base = go []- where- go s x = loop (head' :| s) tail'- where- head' = fromIntegral (x `mod` base)- tail' = x `div` base- loop s@(r :| rs) = \case- 0 -> s- x -> go (r : rs) x
src/Binrep/Type/Byte.hs view
@@ -17,809 +17,793 @@ module Binrep.Type.Byte where -import Mason.Builder qualified as Mason-import Data.ByteString.Builder.Prim.Internal qualified as BI-import Binrep.Util ( natVal'' )-import Binrep.Put ( Builder )+import Bytezap qualified as BZ+import Bytezap.Poke.Int qualified as BZ import GHC.TypeNats-import GHC.Exts+import GHC.Word --- Needs to be a function type to work. Interesting. It's perhaps not an--- improvement on regular boxed. But interesting idea, so sticking with it.-class ByteVal (n :: Natural) where byteVal :: Proxy# n -> Word8#+-- | 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]) where reifyBytes :: BZ.Poke+instance ReifyBytes '[] where+ {-# INLINE reifyBytes #-}+ reifyBytes = mempty+instance (ByteVal n, ReifyBytes ns) => ReifyBytes (n ': ns) where+ {-# INLINE reifyBytes #-}+ reifyBytes = BZ.w8 (byteVal @n) <> reifyBytes @ns +class ByteVal (n :: Natural) where byteVal :: Word8+ instance ByteVal 0x00 where- byteVal _ = wordToWord8# 0x00## {-# INLINE byteVal #-}+ byteVal = 0x00 instance ByteVal 0x01 where- byteVal _ = wordToWord8# 0x01## {-# INLINE byteVal #-}+ byteVal = 0x01 instance ByteVal 0x02 where- byteVal _ = wordToWord8# 0x02## {-# INLINE byteVal #-}+ byteVal = 0x02 instance ByteVal 0x03 where- byteVal _ = wordToWord8# 0x03## {-# INLINE byteVal #-}+ byteVal = 0x03 instance ByteVal 0x04 where- byteVal _ = wordToWord8# 0x04## {-# INLINE byteVal #-}+ byteVal = 0x04 instance ByteVal 0x05 where- byteVal _ = wordToWord8# 0x05## {-# INLINE byteVal #-}+ byteVal = 0x05 instance ByteVal 0x06 where- byteVal _ = wordToWord8# 0x06## {-# INLINE byteVal #-}+ byteVal = 0x06 instance ByteVal 0x07 where- byteVal _ = wordToWord8# 0x07## {-# INLINE byteVal #-}+ byteVal = 0x07 instance ByteVal 0x08 where- byteVal _ = wordToWord8# 0x08## {-# INLINE byteVal #-}+ byteVal = 0x08 instance ByteVal 0x09 where- byteVal _ = wordToWord8# 0x09## {-# INLINE byteVal #-}+ byteVal = 0x09 instance ByteVal 0x0a where- byteVal _ = wordToWord8# 0x0a## {-# INLINE byteVal #-}+ byteVal = 0x0a instance ByteVal 0x0b where- byteVal _ = wordToWord8# 0x0b## {-# INLINE byteVal #-}+ byteVal = 0x0b instance ByteVal 0x0c where- byteVal _ = wordToWord8# 0x0c## {-# INLINE byteVal #-}+ byteVal = 0x0c instance ByteVal 0x0d where- byteVal _ = wordToWord8# 0x0d## {-# INLINE byteVal #-}+ byteVal = 0x0d instance ByteVal 0x0e where- byteVal _ = wordToWord8# 0x0e## {-# INLINE byteVal #-}+ byteVal = 0x0e instance ByteVal 0x0f where- byteVal _ = wordToWord8# 0x0f## {-# INLINE byteVal #-}+ byteVal = 0x0f instance ByteVal 0x10 where- byteVal _ = wordToWord8# 0x10## {-# INLINE byteVal #-}+ byteVal = 0x10 instance ByteVal 0x11 where- byteVal _ = wordToWord8# 0x11## {-# INLINE byteVal #-}+ byteVal = 0x11 instance ByteVal 0x12 where- byteVal _ = wordToWord8# 0x12## {-# INLINE byteVal #-}+ byteVal = 0x12 instance ByteVal 0x13 where- byteVal _ = wordToWord8# 0x13## {-# INLINE byteVal #-}+ byteVal = 0x13 instance ByteVal 0x14 where- byteVal _ = wordToWord8# 0x14## {-# INLINE byteVal #-}+ byteVal = 0x14 instance ByteVal 0x15 where- byteVal _ = wordToWord8# 0x15## {-# INLINE byteVal #-}+ byteVal = 0x15 instance ByteVal 0x16 where- byteVal _ = wordToWord8# 0x16## {-# INLINE byteVal #-}+ byteVal = 0x16 instance ByteVal 0x17 where- byteVal _ = wordToWord8# 0x17## {-# INLINE byteVal #-}+ byteVal = 0x17 instance ByteVal 0x18 where- byteVal _ = wordToWord8# 0x18## {-# INLINE byteVal #-}+ byteVal = 0x18 instance ByteVal 0x19 where- byteVal _ = wordToWord8# 0x19## {-# INLINE byteVal #-}+ byteVal = 0x19 instance ByteVal 0x1a where- byteVal _ = wordToWord8# 0x1a## {-# INLINE byteVal #-}+ byteVal = 0x1a instance ByteVal 0x1b where- byteVal _ = wordToWord8# 0x1b## {-# INLINE byteVal #-}+ byteVal = 0x1b instance ByteVal 0x1c where- byteVal _ = wordToWord8# 0x1c## {-# INLINE byteVal #-}+ byteVal = 0x1c instance ByteVal 0x1d where- byteVal _ = wordToWord8# 0x1d## {-# INLINE byteVal #-}+ byteVal = 0x1d instance ByteVal 0x1e where- byteVal _ = wordToWord8# 0x1e## {-# INLINE byteVal #-}+ byteVal = 0x1e instance ByteVal 0x1f where- byteVal _ = wordToWord8# 0x1f## {-# INLINE byteVal #-}+ byteVal = 0x1f instance ByteVal 0x20 where- byteVal _ = wordToWord8# 0x20## {-# INLINE byteVal #-}+ byteVal = 0x20 instance ByteVal 0x21 where- byteVal _ = wordToWord8# 0x21## {-# INLINE byteVal #-}+ byteVal = 0x21 instance ByteVal 0x22 where- byteVal _ = wordToWord8# 0x22## {-# INLINE byteVal #-}+ byteVal = 0x22 instance ByteVal 0x23 where- byteVal _ = wordToWord8# 0x23## {-# INLINE byteVal #-}+ byteVal = 0x23 instance ByteVal 0x24 where- byteVal _ = wordToWord8# 0x24## {-# INLINE byteVal #-}+ byteVal = 0x24 instance ByteVal 0x25 where- byteVal _ = wordToWord8# 0x25## {-# INLINE byteVal #-}+ byteVal = 0x25 instance ByteVal 0x26 where- byteVal _ = wordToWord8# 0x26## {-# INLINE byteVal #-}+ byteVal = 0x26 instance ByteVal 0x27 where- byteVal _ = wordToWord8# 0x27## {-# INLINE byteVal #-}+ byteVal = 0x27 instance ByteVal 0x28 where- byteVal _ = wordToWord8# 0x28## {-# INLINE byteVal #-}+ byteVal = 0x28 instance ByteVal 0x29 where- byteVal _ = wordToWord8# 0x29## {-# INLINE byteVal #-}+ byteVal = 0x29 instance ByteVal 0x2a where- byteVal _ = wordToWord8# 0x2a## {-# INLINE byteVal #-}+ byteVal = 0x2a instance ByteVal 0x2b where- byteVal _ = wordToWord8# 0x2b## {-# INLINE byteVal #-}+ byteVal = 0x2b instance ByteVal 0x2c where- byteVal _ = wordToWord8# 0x2c## {-# INLINE byteVal #-}+ byteVal = 0x2c instance ByteVal 0x2d where- byteVal _ = wordToWord8# 0x2d## {-# INLINE byteVal #-}+ byteVal = 0x2d instance ByteVal 0x2e where- byteVal _ = wordToWord8# 0x2e## {-# INLINE byteVal #-}+ byteVal = 0x2e instance ByteVal 0x2f where- byteVal _ = wordToWord8# 0x2f## {-# INLINE byteVal #-}+ byteVal = 0x2f instance ByteVal 0x30 where- byteVal _ = wordToWord8# 0x30## {-# INLINE byteVal #-}+ byteVal = 0x30 instance ByteVal 0x31 where- byteVal _ = wordToWord8# 0x31## {-# INLINE byteVal #-}+ byteVal = 0x31 instance ByteVal 0x32 where- byteVal _ = wordToWord8# 0x32## {-# INLINE byteVal #-}+ byteVal = 0x32 instance ByteVal 0x33 where- byteVal _ = wordToWord8# 0x33## {-# INLINE byteVal #-}+ byteVal = 0x33 instance ByteVal 0x34 where- byteVal _ = wordToWord8# 0x34## {-# INLINE byteVal #-}+ byteVal = 0x34 instance ByteVal 0x35 where- byteVal _ = wordToWord8# 0x35## {-# INLINE byteVal #-}+ byteVal = 0x35 instance ByteVal 0x36 where- byteVal _ = wordToWord8# 0x36## {-# INLINE byteVal #-}+ byteVal = 0x36 instance ByteVal 0x37 where- byteVal _ = wordToWord8# 0x37## {-# INLINE byteVal #-}+ byteVal = 0x37 instance ByteVal 0x38 where- byteVal _ = wordToWord8# 0x38## {-# INLINE byteVal #-}+ byteVal = 0x38 instance ByteVal 0x39 where- byteVal _ = wordToWord8# 0x39## {-# INLINE byteVal #-}+ byteVal = 0x39 instance ByteVal 0x3a where- byteVal _ = wordToWord8# 0x3a## {-# INLINE byteVal #-}+ byteVal = 0x3a instance ByteVal 0x3b where- byteVal _ = wordToWord8# 0x3b## {-# INLINE byteVal #-}+ byteVal = 0x3b instance ByteVal 0x3c where- byteVal _ = wordToWord8# 0x3c## {-# INLINE byteVal #-}+ byteVal = 0x3c instance ByteVal 0x3d where- byteVal _ = wordToWord8# 0x3d## {-# INLINE byteVal #-}+ byteVal = 0x3d instance ByteVal 0x3e where- byteVal _ = wordToWord8# 0x3e## {-# INLINE byteVal #-}+ byteVal = 0x3e instance ByteVal 0x3f where- byteVal _ = wordToWord8# 0x3f## {-# INLINE byteVal #-}+ byteVal = 0x3f instance ByteVal 0x40 where- byteVal _ = wordToWord8# 0x40## {-# INLINE byteVal #-}+ byteVal = 0x40 instance ByteVal 0x41 where- byteVal _ = wordToWord8# 0x41## {-# INLINE byteVal #-}+ byteVal = 0x41 instance ByteVal 0x42 where- byteVal _ = wordToWord8# 0x42## {-# INLINE byteVal #-}+ byteVal = 0x42 instance ByteVal 0x43 where- byteVal _ = wordToWord8# 0x43## {-# INLINE byteVal #-}+ byteVal = 0x43 instance ByteVal 0x44 where- byteVal _ = wordToWord8# 0x44## {-# INLINE byteVal #-}+ byteVal = 0x44 instance ByteVal 0x45 where- byteVal _ = wordToWord8# 0x45## {-# INLINE byteVal #-}+ byteVal = 0x45 instance ByteVal 0x46 where- byteVal _ = wordToWord8# 0x46## {-# INLINE byteVal #-}+ byteVal = 0x46 instance ByteVal 0x47 where- byteVal _ = wordToWord8# 0x47## {-# INLINE byteVal #-}+ byteVal = 0x47 instance ByteVal 0x48 where- byteVal _ = wordToWord8# 0x48## {-# INLINE byteVal #-}+ byteVal = 0x48 instance ByteVal 0x49 where- byteVal _ = wordToWord8# 0x49## {-# INLINE byteVal #-}+ byteVal = 0x49 instance ByteVal 0x4a where- byteVal _ = wordToWord8# 0x4a## {-# INLINE byteVal #-}+ byteVal = 0x4a instance ByteVal 0x4b where- byteVal _ = wordToWord8# 0x4b## {-# INLINE byteVal #-}+ byteVal = 0x4b instance ByteVal 0x4c where- byteVal _ = wordToWord8# 0x4c## {-# INLINE byteVal #-}+ byteVal = 0x4c instance ByteVal 0x4d where- byteVal _ = wordToWord8# 0x4d## {-# INLINE byteVal #-}+ byteVal = 0x4d instance ByteVal 0x4e where- byteVal _ = wordToWord8# 0x4e## {-# INLINE byteVal #-}+ byteVal = 0x4e instance ByteVal 0x4f where- byteVal _ = wordToWord8# 0x4f## {-# INLINE byteVal #-}+ byteVal = 0x4f instance ByteVal 0x50 where- byteVal _ = wordToWord8# 0x50## {-# INLINE byteVal #-}+ byteVal = 0x50 instance ByteVal 0x51 where- byteVal _ = wordToWord8# 0x51## {-# INLINE byteVal #-}+ byteVal = 0x51 instance ByteVal 0x52 where- byteVal _ = wordToWord8# 0x52## {-# INLINE byteVal #-}+ byteVal = 0x52 instance ByteVal 0x53 where- byteVal _ = wordToWord8# 0x53## {-# INLINE byteVal #-}+ byteVal = 0x53 instance ByteVal 0x54 where- byteVal _ = wordToWord8# 0x54## {-# INLINE byteVal #-}+ byteVal = 0x54 instance ByteVal 0x55 where- byteVal _ = wordToWord8# 0x55## {-# INLINE byteVal #-}+ byteVal = 0x55 instance ByteVal 0x56 where- byteVal _ = wordToWord8# 0x56## {-# INLINE byteVal #-}+ byteVal = 0x56 instance ByteVal 0x57 where- byteVal _ = wordToWord8# 0x57## {-# INLINE byteVal #-}+ byteVal = 0x57 instance ByteVal 0x58 where- byteVal _ = wordToWord8# 0x58## {-# INLINE byteVal #-}+ byteVal = 0x58 instance ByteVal 0x59 where- byteVal _ = wordToWord8# 0x59## {-# INLINE byteVal #-}+ byteVal = 0x59 instance ByteVal 0x5a where- byteVal _ = wordToWord8# 0x5a## {-# INLINE byteVal #-}+ byteVal = 0x5a instance ByteVal 0x5b where- byteVal _ = wordToWord8# 0x5b## {-# INLINE byteVal #-}+ byteVal = 0x5b instance ByteVal 0x5c where- byteVal _ = wordToWord8# 0x5c## {-# INLINE byteVal #-}+ byteVal = 0x5c instance ByteVal 0x5d where- byteVal _ = wordToWord8# 0x5d## {-# INLINE byteVal #-}+ byteVal = 0x5d instance ByteVal 0x5e where- byteVal _ = wordToWord8# 0x5e## {-# INLINE byteVal #-}+ byteVal = 0x5e instance ByteVal 0x5f where- byteVal _ = wordToWord8# 0x5f## {-# INLINE byteVal #-}+ byteVal = 0x5f instance ByteVal 0x60 where- byteVal _ = wordToWord8# 0x60## {-# INLINE byteVal #-}+ byteVal = 0x60 instance ByteVal 0x61 where- byteVal _ = wordToWord8# 0x61## {-# INLINE byteVal #-}+ byteVal = 0x61 instance ByteVal 0x62 where- byteVal _ = wordToWord8# 0x62## {-# INLINE byteVal #-}+ byteVal = 0x62 instance ByteVal 0x63 where- byteVal _ = wordToWord8# 0x63## {-# INLINE byteVal #-}+ byteVal = 0x63 instance ByteVal 0x64 where- byteVal _ = wordToWord8# 0x64## {-# INLINE byteVal #-}+ byteVal = 0x64 instance ByteVal 0x65 where- byteVal _ = wordToWord8# 0x65## {-# INLINE byteVal #-}+ byteVal = 0x65 instance ByteVal 0x66 where- byteVal _ = wordToWord8# 0x66## {-# INLINE byteVal #-}+ byteVal = 0x66 instance ByteVal 0x67 where- byteVal _ = wordToWord8# 0x67## {-# INLINE byteVal #-}+ byteVal = 0x67 instance ByteVal 0x68 where- byteVal _ = wordToWord8# 0x68## {-# INLINE byteVal #-}+ byteVal = 0x68 instance ByteVal 0x69 where- byteVal _ = wordToWord8# 0x69## {-# INLINE byteVal #-}+ byteVal = 0x69 instance ByteVal 0x6a where- byteVal _ = wordToWord8# 0x6a## {-# INLINE byteVal #-}+ byteVal = 0x6a instance ByteVal 0x6b where- byteVal _ = wordToWord8# 0x6b## {-# INLINE byteVal #-}+ byteVal = 0x6b instance ByteVal 0x6c where- byteVal _ = wordToWord8# 0x6c## {-# INLINE byteVal #-}+ byteVal = 0x6c instance ByteVal 0x6d where- byteVal _ = wordToWord8# 0x6d## {-# INLINE byteVal #-}+ byteVal = 0x6d instance ByteVal 0x6e where- byteVal _ = wordToWord8# 0x6e## {-# INLINE byteVal #-}+ byteVal = 0x6e instance ByteVal 0x6f where- byteVal _ = wordToWord8# 0x6f## {-# INLINE byteVal #-}+ byteVal = 0x6f instance ByteVal 0x70 where- byteVal _ = wordToWord8# 0x70## {-# INLINE byteVal #-}+ byteVal = 0x70 instance ByteVal 0x71 where- byteVal _ = wordToWord8# 0x71## {-# INLINE byteVal #-}+ byteVal = 0x71 instance ByteVal 0x72 where- byteVal _ = wordToWord8# 0x72## {-# INLINE byteVal #-}+ byteVal = 0x72 instance ByteVal 0x73 where- byteVal _ = wordToWord8# 0x73## {-# INLINE byteVal #-}+ byteVal = 0x73 instance ByteVal 0x74 where- byteVal _ = wordToWord8# 0x74## {-# INLINE byteVal #-}+ byteVal = 0x74 instance ByteVal 0x75 where- byteVal _ = wordToWord8# 0x75## {-# INLINE byteVal #-}+ byteVal = 0x75 instance ByteVal 0x76 where- byteVal _ = wordToWord8# 0x76## {-# INLINE byteVal #-}+ byteVal = 0x76 instance ByteVal 0x77 where- byteVal _ = wordToWord8# 0x77## {-# INLINE byteVal #-}+ byteVal = 0x77 instance ByteVal 0x78 where- byteVal _ = wordToWord8# 0x78## {-# INLINE byteVal #-}+ byteVal = 0x78 instance ByteVal 0x79 where- byteVal _ = wordToWord8# 0x79## {-# INLINE byteVal #-}+ byteVal = 0x79 instance ByteVal 0x7a where- byteVal _ = wordToWord8# 0x7a## {-# INLINE byteVal #-}+ byteVal = 0x7a instance ByteVal 0x7b where- byteVal _ = wordToWord8# 0x7b## {-# INLINE byteVal #-}+ byteVal = 0x7b instance ByteVal 0x7c where- byteVal _ = wordToWord8# 0x7c## {-# INLINE byteVal #-}+ byteVal = 0x7c instance ByteVal 0x7d where- byteVal _ = wordToWord8# 0x7d## {-# INLINE byteVal #-}+ byteVal = 0x7d instance ByteVal 0x7e where- byteVal _ = wordToWord8# 0x7e## {-# INLINE byteVal #-}+ byteVal = 0x7e instance ByteVal 0x7f where- byteVal _ = wordToWord8# 0x7f## {-# INLINE byteVal #-}+ byteVal = 0x7f instance ByteVal 0x80 where- byteVal _ = wordToWord8# 0x80## {-# INLINE byteVal #-}+ byteVal = 0x80 instance ByteVal 0x81 where- byteVal _ = wordToWord8# 0x81## {-# INLINE byteVal #-}+ byteVal = 0x81 instance ByteVal 0x82 where- byteVal _ = wordToWord8# 0x82## {-# INLINE byteVal #-}+ byteVal = 0x82 instance ByteVal 0x83 where- byteVal _ = wordToWord8# 0x83## {-# INLINE byteVal #-}+ byteVal = 0x83 instance ByteVal 0x84 where- byteVal _ = wordToWord8# 0x84## {-# INLINE byteVal #-}+ byteVal = 0x84 instance ByteVal 0x85 where- byteVal _ = wordToWord8# 0x85## {-# INLINE byteVal #-}+ byteVal = 0x85 instance ByteVal 0x86 where- byteVal _ = wordToWord8# 0x86## {-# INLINE byteVal #-}+ byteVal = 0x86 instance ByteVal 0x87 where- byteVal _ = wordToWord8# 0x87## {-# INLINE byteVal #-}+ byteVal = 0x87 instance ByteVal 0x88 where- byteVal _ = wordToWord8# 0x88## {-# INLINE byteVal #-}+ byteVal = 0x88 instance ByteVal 0x89 where- byteVal _ = wordToWord8# 0x89## {-# INLINE byteVal #-}+ byteVal = 0x89 instance ByteVal 0x8a where- byteVal _ = wordToWord8# 0x8a## {-# INLINE byteVal #-}+ byteVal = 0x8a instance ByteVal 0x8b where- byteVal _ = wordToWord8# 0x8b## {-# INLINE byteVal #-}+ byteVal = 0x8b instance ByteVal 0x8c where- byteVal _ = wordToWord8# 0x8c## {-# INLINE byteVal #-}+ byteVal = 0x8c instance ByteVal 0x8d where- byteVal _ = wordToWord8# 0x8d## {-# INLINE byteVal #-}+ byteVal = 0x8d instance ByteVal 0x8e where- byteVal _ = wordToWord8# 0x8e## {-# INLINE byteVal #-}+ byteVal = 0x8e instance ByteVal 0x8f where- byteVal _ = wordToWord8# 0x8f## {-# INLINE byteVal #-}+ byteVal = 0x8f instance ByteVal 0x90 where- byteVal _ = wordToWord8# 0x90## {-# INLINE byteVal #-}+ byteVal = 0x90 instance ByteVal 0x91 where- byteVal _ = wordToWord8# 0x91## {-# INLINE byteVal #-}+ byteVal = 0x91 instance ByteVal 0x92 where- byteVal _ = wordToWord8# 0x92## {-# INLINE byteVal #-}+ byteVal = 0x92 instance ByteVal 0x93 where- byteVal _ = wordToWord8# 0x93## {-# INLINE byteVal #-}+ byteVal = 0x93 instance ByteVal 0x94 where- byteVal _ = wordToWord8# 0x94## {-# INLINE byteVal #-}+ byteVal = 0x94 instance ByteVal 0x95 where- byteVal _ = wordToWord8# 0x95## {-# INLINE byteVal #-}+ byteVal = 0x95 instance ByteVal 0x96 where- byteVal _ = wordToWord8# 0x96## {-# INLINE byteVal #-}+ byteVal = 0x96 instance ByteVal 0x97 where- byteVal _ = wordToWord8# 0x97## {-# INLINE byteVal #-}+ byteVal = 0x97 instance ByteVal 0x98 where- byteVal _ = wordToWord8# 0x98## {-# INLINE byteVal #-}+ byteVal = 0x98 instance ByteVal 0x99 where- byteVal _ = wordToWord8# 0x99## {-# INLINE byteVal #-}+ byteVal = 0x99 instance ByteVal 0x9a where- byteVal _ = wordToWord8# 0x9a## {-# INLINE byteVal #-}+ byteVal = 0x9a instance ByteVal 0x9b where- byteVal _ = wordToWord8# 0x9b## {-# INLINE byteVal #-}+ byteVal = 0x9b instance ByteVal 0x9c where- byteVal _ = wordToWord8# 0x9c## {-# INLINE byteVal #-}+ byteVal = 0x9c instance ByteVal 0x9d where- byteVal _ = wordToWord8# 0x9d## {-# INLINE byteVal #-}+ byteVal = 0x9d instance ByteVal 0x9e where- byteVal _ = wordToWord8# 0x9e## {-# INLINE byteVal #-}+ byteVal = 0x9e instance ByteVal 0x9f where- byteVal _ = wordToWord8# 0x9f## {-# INLINE byteVal #-}+ byteVal = 0x9f instance ByteVal 0xa0 where- byteVal _ = wordToWord8# 0xa0## {-# INLINE byteVal #-}+ byteVal = 0xa0 instance ByteVal 0xa1 where- byteVal _ = wordToWord8# 0xa1## {-# INLINE byteVal #-}+ byteVal = 0xa1 instance ByteVal 0xa2 where- byteVal _ = wordToWord8# 0xa2## {-# INLINE byteVal #-}+ byteVal = 0xa2 instance ByteVal 0xa3 where- byteVal _ = wordToWord8# 0xa3## {-# INLINE byteVal #-}+ byteVal = 0xa3 instance ByteVal 0xa4 where- byteVal _ = wordToWord8# 0xa4## {-# INLINE byteVal #-}+ byteVal = 0xa4 instance ByteVal 0xa5 where- byteVal _ = wordToWord8# 0xa5## {-# INLINE byteVal #-}+ byteVal = 0xa5 instance ByteVal 0xa6 where- byteVal _ = wordToWord8# 0xa6## {-# INLINE byteVal #-}+ byteVal = 0xa6 instance ByteVal 0xa7 where- byteVal _ = wordToWord8# 0xa7## {-# INLINE byteVal #-}+ byteVal = 0xa7 instance ByteVal 0xa8 where- byteVal _ = wordToWord8# 0xa8## {-# INLINE byteVal #-}+ byteVal = 0xa8 instance ByteVal 0xa9 where- byteVal _ = wordToWord8# 0xa9## {-# INLINE byteVal #-}+ byteVal = 0xa9 instance ByteVal 0xaa where- byteVal _ = wordToWord8# 0xaa## {-# INLINE byteVal #-}+ byteVal = 0xaa instance ByteVal 0xab where- byteVal _ = wordToWord8# 0xab## {-# INLINE byteVal #-}+ byteVal = 0xab instance ByteVal 0xac where- byteVal _ = wordToWord8# 0xac## {-# INLINE byteVal #-}+ byteVal = 0xac instance ByteVal 0xad where- byteVal _ = wordToWord8# 0xad## {-# INLINE byteVal #-}+ byteVal = 0xad instance ByteVal 0xae where- byteVal _ = wordToWord8# 0xae## {-# INLINE byteVal #-}+ byteVal = 0xae instance ByteVal 0xaf where- byteVal _ = wordToWord8# 0xaf## {-# INLINE byteVal #-}+ byteVal = 0xaf instance ByteVal 0xb0 where- byteVal _ = wordToWord8# 0xb0## {-# INLINE byteVal #-}+ byteVal = 0xb0 instance ByteVal 0xb1 where- byteVal _ = wordToWord8# 0xb1## {-# INLINE byteVal #-}+ byteVal = 0xb1 instance ByteVal 0xb2 where- byteVal _ = wordToWord8# 0xb2## {-# INLINE byteVal #-}+ byteVal = 0xb2 instance ByteVal 0xb3 where- byteVal _ = wordToWord8# 0xb3## {-# INLINE byteVal #-}+ byteVal = 0xb3 instance ByteVal 0xb4 where- byteVal _ = wordToWord8# 0xb4## {-# INLINE byteVal #-}+ byteVal = 0xb4 instance ByteVal 0xb5 where- byteVal _ = wordToWord8# 0xb5## {-# INLINE byteVal #-}+ byteVal = 0xb5 instance ByteVal 0xb6 where- byteVal _ = wordToWord8# 0xb6## {-# INLINE byteVal #-}+ byteVal = 0xb6 instance ByteVal 0xb7 where- byteVal _ = wordToWord8# 0xb7## {-# INLINE byteVal #-}+ byteVal = 0xb7 instance ByteVal 0xb8 where- byteVal _ = wordToWord8# 0xb8## {-# INLINE byteVal #-}+ byteVal = 0xb8 instance ByteVal 0xb9 where- byteVal _ = wordToWord8# 0xb9## {-# INLINE byteVal #-}+ byteVal = 0xb9 instance ByteVal 0xba where- byteVal _ = wordToWord8# 0xba## {-# INLINE byteVal #-}+ byteVal = 0xba instance ByteVal 0xbb where- byteVal _ = wordToWord8# 0xbb## {-# INLINE byteVal #-}+ byteVal = 0xbb instance ByteVal 0xbc where- byteVal _ = wordToWord8# 0xbc## {-# INLINE byteVal #-}+ byteVal = 0xbc instance ByteVal 0xbd where- byteVal _ = wordToWord8# 0xbd## {-# INLINE byteVal #-}+ byteVal = 0xbd instance ByteVal 0xbe where- byteVal _ = wordToWord8# 0xbe## {-# INLINE byteVal #-}+ byteVal = 0xbe instance ByteVal 0xbf where- byteVal _ = wordToWord8# 0xbf## {-# INLINE byteVal #-}+ byteVal = 0xbf instance ByteVal 0xc0 where- byteVal _ = wordToWord8# 0xc0## {-# INLINE byteVal #-}+ byteVal = 0xc0 instance ByteVal 0xc1 where- byteVal _ = wordToWord8# 0xc1## {-# INLINE byteVal #-}+ byteVal = 0xc1 instance ByteVal 0xc2 where- byteVal _ = wordToWord8# 0xc2## {-# INLINE byteVal #-}+ byteVal = 0xc2 instance ByteVal 0xc3 where- byteVal _ = wordToWord8# 0xc3## {-# INLINE byteVal #-}+ byteVal = 0xc3 instance ByteVal 0xc4 where- byteVal _ = wordToWord8# 0xc4## {-# INLINE byteVal #-}+ byteVal = 0xc4 instance ByteVal 0xc5 where- byteVal _ = wordToWord8# 0xc5## {-# INLINE byteVal #-}+ byteVal = 0xc5 instance ByteVal 0xc6 where- byteVal _ = wordToWord8# 0xc6## {-# INLINE byteVal #-}+ byteVal = 0xc6 instance ByteVal 0xc7 where- byteVal _ = wordToWord8# 0xc7## {-# INLINE byteVal #-}+ byteVal = 0xc7 instance ByteVal 0xc8 where- byteVal _ = wordToWord8# 0xc8## {-# INLINE byteVal #-}+ byteVal = 0xc8 instance ByteVal 0xc9 where- byteVal _ = wordToWord8# 0xc9## {-# INLINE byteVal #-}+ byteVal = 0xc9 instance ByteVal 0xca where- byteVal _ = wordToWord8# 0xca## {-# INLINE byteVal #-}+ byteVal = 0xca instance ByteVal 0xcb where- byteVal _ = wordToWord8# 0xcb## {-# INLINE byteVal #-}+ byteVal = 0xcb instance ByteVal 0xcc where- byteVal _ = wordToWord8# 0xcc## {-# INLINE byteVal #-}+ byteVal = 0xcc instance ByteVal 0xcd where- byteVal _ = wordToWord8# 0xcd## {-# INLINE byteVal #-}+ byteVal = 0xcd instance ByteVal 0xce where- byteVal _ = wordToWord8# 0xce## {-# INLINE byteVal #-}+ byteVal = 0xce instance ByteVal 0xcf where- byteVal _ = wordToWord8# 0xcf## {-# INLINE byteVal #-}+ byteVal = 0xcf instance ByteVal 0xd0 where- byteVal _ = wordToWord8# 0xd0## {-# INLINE byteVal #-}+ byteVal = 0xd0 instance ByteVal 0xd1 where- byteVal _ = wordToWord8# 0xd1## {-# INLINE byteVal #-}+ byteVal = 0xd1 instance ByteVal 0xd2 where- byteVal _ = wordToWord8# 0xd2## {-# INLINE byteVal #-}+ byteVal = 0xd2 instance ByteVal 0xd3 where- byteVal _ = wordToWord8# 0xd3## {-# INLINE byteVal #-}+ byteVal = 0xd3 instance ByteVal 0xd4 where- byteVal _ = wordToWord8# 0xd4## {-# INLINE byteVal #-}+ byteVal = 0xd4 instance ByteVal 0xd5 where- byteVal _ = wordToWord8# 0xd5## {-# INLINE byteVal #-}+ byteVal = 0xd5 instance ByteVal 0xd6 where- byteVal _ = wordToWord8# 0xd6## {-# INLINE byteVal #-}+ byteVal = 0xd6 instance ByteVal 0xd7 where- byteVal _ = wordToWord8# 0xd7## {-# INLINE byteVal #-}+ byteVal = 0xd7 instance ByteVal 0xd8 where- byteVal _ = wordToWord8# 0xd8## {-# INLINE byteVal #-}+ byteVal = 0xd8 instance ByteVal 0xd9 where- byteVal _ = wordToWord8# 0xd9## {-# INLINE byteVal #-}+ byteVal = 0xd9 instance ByteVal 0xda where- byteVal _ = wordToWord8# 0xda## {-# INLINE byteVal #-}+ byteVal = 0xda instance ByteVal 0xdb where- byteVal _ = wordToWord8# 0xdb## {-# INLINE byteVal #-}+ byteVal = 0xdb instance ByteVal 0xdc where- byteVal _ = wordToWord8# 0xdc## {-# INLINE byteVal #-}+ byteVal = 0xdc instance ByteVal 0xdd where- byteVal _ = wordToWord8# 0xdd## {-# INLINE byteVal #-}+ byteVal = 0xdd instance ByteVal 0xde where- byteVal _ = wordToWord8# 0xde## {-# INLINE byteVal #-}+ byteVal = 0xde instance ByteVal 0xdf where- byteVal _ = wordToWord8# 0xdf## {-# INLINE byteVal #-}+ byteVal = 0xdf instance ByteVal 0xe0 where- byteVal _ = wordToWord8# 0xe0## {-# INLINE byteVal #-}+ byteVal = 0xe0 instance ByteVal 0xe1 where- byteVal _ = wordToWord8# 0xe1## {-# INLINE byteVal #-}+ byteVal = 0xe1 instance ByteVal 0xe2 where- byteVal _ = wordToWord8# 0xe2## {-# INLINE byteVal #-}+ byteVal = 0xe2 instance ByteVal 0xe3 where- byteVal _ = wordToWord8# 0xe3## {-# INLINE byteVal #-}+ byteVal = 0xe3 instance ByteVal 0xe4 where- byteVal _ = wordToWord8# 0xe4## {-# INLINE byteVal #-}+ byteVal = 0xe4 instance ByteVal 0xe5 where- byteVal _ = wordToWord8# 0xe5## {-# INLINE byteVal #-}+ byteVal = 0xe5 instance ByteVal 0xe6 where- byteVal _ = wordToWord8# 0xe6## {-# INLINE byteVal #-}+ byteVal = 0xe6 instance ByteVal 0xe7 where- byteVal _ = wordToWord8# 0xe7## {-# INLINE byteVal #-}+ byteVal = 0xe7 instance ByteVal 0xe8 where- byteVal _ = wordToWord8# 0xe8## {-# INLINE byteVal #-}+ byteVal = 0xe8 instance ByteVal 0xe9 where- byteVal _ = wordToWord8# 0xe9## {-# INLINE byteVal #-}+ byteVal = 0xe9 instance ByteVal 0xea where- byteVal _ = wordToWord8# 0xea## {-# INLINE byteVal #-}+ byteVal = 0xea instance ByteVal 0xeb where- byteVal _ = wordToWord8# 0xeb## {-# INLINE byteVal #-}+ byteVal = 0xeb instance ByteVal 0xec where- byteVal _ = wordToWord8# 0xec## {-# INLINE byteVal #-}+ byteVal = 0xec instance ByteVal 0xed where- byteVal _ = wordToWord8# 0xed## {-# INLINE byteVal #-}+ byteVal = 0xed instance ByteVal 0xee where- byteVal _ = wordToWord8# 0xee## {-# INLINE byteVal #-}+ byteVal = 0xee instance ByteVal 0xef where- byteVal _ = wordToWord8# 0xef## {-# INLINE byteVal #-}+ byteVal = 0xef instance ByteVal 0xf0 where- byteVal _ = wordToWord8# 0xf0## {-# INLINE byteVal #-}+ byteVal = 0xf0 instance ByteVal 0xf1 where- byteVal _ = wordToWord8# 0xf1## {-# INLINE byteVal #-}+ byteVal = 0xf1 instance ByteVal 0xf2 where- byteVal _ = wordToWord8# 0xf2## {-# INLINE byteVal #-}+ byteVal = 0xf2 instance ByteVal 0xf3 where- byteVal _ = wordToWord8# 0xf3## {-# INLINE byteVal #-}+ byteVal = 0xf3 instance ByteVal 0xf4 where- byteVal _ = wordToWord8# 0xf4## {-# INLINE byteVal #-}+ byteVal = 0xf4 instance ByteVal 0xf5 where- byteVal _ = wordToWord8# 0xf5## {-# INLINE byteVal #-}+ byteVal = 0xf5 instance ByteVal 0xf6 where- byteVal _ = wordToWord8# 0xf6## {-# INLINE byteVal #-}+ byteVal = 0xf6 instance ByteVal 0xf7 where- byteVal _ = wordToWord8# 0xf7## {-# INLINE byteVal #-}+ byteVal = 0xf7 instance ByteVal 0xf8 where- byteVal _ = wordToWord8# 0xf8## {-# INLINE byteVal #-}+ byteVal = 0xf8 instance ByteVal 0xf9 where- byteVal _ = wordToWord8# 0xf9## {-# INLINE byteVal #-}+ byteVal = 0xf9 instance ByteVal 0xfa where- byteVal _ = wordToWord8# 0xfa## {-# INLINE byteVal #-}+ byteVal = 0xfa instance ByteVal 0xfb where- byteVal _ = wordToWord8# 0xfb## {-# INLINE byteVal #-}+ byteVal = 0xfb instance ByteVal 0xfc where- byteVal _ = wordToWord8# 0xfc## {-# INLINE byteVal #-}+ byteVal = 0xfc instance ByteVal 0xfd where- byteVal _ = wordToWord8# 0xfd## {-# INLINE byteVal #-}+ byteVal = 0xfd instance ByteVal 0xfe where- byteVal _ = wordToWord8# 0xfe## {-# INLINE byteVal #-}+ byteVal = 0xfe instance ByteVal 0xff where- byteVal _ = wordToWord8# 0xff## {-# INLINE byteVal #-}--type family Length (a :: [k]) :: Natural where- Length '[] = 0- Length (a ': as) = 1 + Length as---- | 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]) where reifyBytes :: Builder-instance (n ~ Length ns, KnownNat n, WriteReifiedBytes ns) => ReifyBytes ns where- reifyBytes = Mason.primFixed (BI.fixedPrim (fromIntegral n) go) ()- where- n = natVal'' @n- go = \() (Ptr p#) -> writeReifiedBytes @ns p#---- bit ugly-class WriteReifiedBytes (ns :: [Natural]) where writeReifiedBytes :: Addr# -> IO ()-instance WriteReifiedBytes '[] where writeReifiedBytes _ = pure ()-instance (ByteVal n, WriteReifiedBytes ns) => WriteReifiedBytes (n ': ns) where- writeReifiedBytes p# =- case runRW# (writeWord8OffAddr# p# 0# w#) of- _ -> writeReifiedBytes @ns (plusAddr# p# 1#)- where w# = byteVal @n proxy#+ byteVal = 0xff
− src/Binrep/Type/ByteString.hs
@@ -1,100 +0,0 @@-{- | Machine bytestrings.--I mix string and bytestring terminology here due to bad C influences, but this-module is specifically interested in bytestrings and their encoding. String/text-encoding is handled in another module.--Note that the length prefix predicate is also defined here... because that's-just Pascal-style bytestrings, extended to other types. I can't easily put it in-an orphan module, because we define byte length for *all length-prefixed types*-in one fell swoop.--}---- TODO redocument. pretty all over the place--{-# LANGUAGE UndecidableInstances #-}-{-# LANGUAGE OverloadedStrings #-}--module Binrep.Type.ByteString where--import Binrep-import Binrep.Type.Common ( Endianness )-import Binrep.Type.Int-import Binrep.Util--import Refined-import Refined.Unsafe--import Data.ByteString qualified as B-import FlatParse.Basic qualified as FP-import Data.Word ( Word8 )-import GHC.TypeNats ( KnownNat )--import GHC.Generics ( Generic )-import Data.Data ( Data )--import Data.Typeable ( Typeable, typeRep )---- | Bytestring representation.-data Rep- = C- -- ^ C-style bytestring. Arbitrary length, terminated with a null byte.- -- Permits no null bytes inside the bytestring.-- | Pascal ISize Endianness- -- ^ Pascal-style bytestring. Length defined in a prefixing integer of given- -- size and endianness.- deriving stock (Generic, Data, Show, Eq)---- | A bytestring using the given representation, stored in the 'Text' type.-type AsByteString (rep :: Rep) = Refined rep B.ByteString--getCString :: Getter B.ByteString-getCString = FP.cut FP.anyCString $ EBase $ EFailNamed "cstring"--instance BLen (AsByteString 'C) where- blen cbs = posIntToBLen $ B.length (unrefine cbs) + 1--instance Put (AsByteString 'C) where- put = putCString . unrefine--putCString :: B.ByteString -> Builder-putCString bs = put bs <> put @Word8 0x00--instance Get (AsByteString 'C) where- get = reallyUnsafeRefine <$> getCString--instance (itype ~ I 'U size end, irep ~ IRep 'U size, KnownNat (CBLen irep)) => BLen (AsByteString ('Pascal size end)) where- blen pbs = cblen @itype + blen (unrefine pbs)--instance (itype ~ I 'U size end, irep ~ IRep 'U size, Put itype, Num irep) => Put (AsByteString ('Pascal size end)) where- put pbs = put @itype (fromIntegral (B.length bs)) <> put bs- where bs = unrefine pbs--instance (itype ~ I 'U size end, irep ~ IRep 'U size, Integral irep, Get itype) => Get (AsByteString ('Pascal size end)) where- get = do- len <- get @itype- bs <- FP.takeBs $ fromIntegral len- return $ reallyUnsafeRefine bs---- | A C-style bytestring must not contain any null bytes.-instance Predicate 'C B.ByteString where- validate p bs- | B.any (== 0x00) bs = throwRefineOtherException (typeRep p) $- "null byte not permitted in in C-style bytestring"- | otherwise = success--instance- ( irep ~ IRep 'U size- , Bounded irep, Integral irep- , Show irep, Typeable size, Typeable e- ) => Predicate ('Pascal size e) B.ByteString where- validate p bs- | len > fromIntegral max'- = throwRefineOtherException (typeRep p) $- "bytestring too long for given length prefix type: "- <>tshow len<>" > "<>tshow max'- | otherwise = success- where- len = B.length bs- max' = maxBound @irep
src/Binrep/Type/Common.hs view
@@ -5,6 +5,6 @@ -- | Byte order. data Endianness- = BE -- ^ big endian, MSB first. e.g. most network protocols- | LE -- ^ little endian, MSB last. e.g. most processor architectures+ = LE -- ^ little endian, MSB last. e.g. most processor architectures+ | BE -- ^ big endian, MSB first. e.g. most network protocols deriving stock (Generic, Data, Show, Eq)
src/Binrep/Type/Int.hs view
@@ -1,141 +1,142 @@-{-# LANGUAGE UndecidableInstances #-}+-- | "Machine" integers: sized integers & naturals with explicit endianness type+-- tags for serialization. -{- TODO can I replace this with a closed newtype family?? idk if I even want to- it's just this is clumsy to use sometimes--}+{-# LANGUAGE CPP #-} -- for host endianness checking+{-# LANGUAGE UndecidableInstances #-} -- for convenient type level arithmetic module Binrep.Type.Int where -import Binrep+import Binrep.Put.Mason qualified as Mason+import Binrep.Put.Bytezap qualified as Bytezap+import Binrep.Get.Flatparse qualified as Flatparse+import Binrep.BLen.Simple qualified as Simple+import Binrep.CBLen++import Bytezap.Poke.Int qualified as BZ+import FlatParse.Basic qualified as FP+ import Binrep.Type.Common ( Endianness(..) ) import Strongweak import Data.Word import Data.Int import Data.Aeson-import FlatParse.Basic qualified as FP-import Mason.Builder qualified as Mason import GHC.Generics ( Generic )-import Data.Data ( Typeable, Data )+import Data.Data ( Data ) import GHC.TypeNats --- | Wrapper type grouping machine integers (sign, size) along with an explicit--- endianness.+import Binrep.Via ( Binreply(..) )++-- | Machine integer sign. ----- The internal representation is selected via a type family to correspond to--- the relevant Haskell data type, so common overflow behaviour should match.--- We derive lots of handy instances, so you may perform regular arithmetic on--- pairs of these types. For example:+-- Signed integers use two's complement for representation.+data ISign+ = U -- ^ unsigned+ | I -- ^ signed (two's complement)+ deriving stock (Generic, Data, Show, Eq)++-- | A type tagged with the endianness (byte order) to use when serializing. ----- >>> 255 + 1 :: I 'U 'I1 e--- 0+-- 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. ----- >>> 255 + 1 :: I 'U 'I2 e--- 256-newtype I (sign :: ISign) (size :: ISize) (e :: Endianness)- = I { getI :: IRep sign size }- deriving stock (Generic)+-- May be considered a restricted 'Data.Tagged.Tagged' (from the @tagged@+-- package).+newtype Endian (end :: Endianness) a = Endian+ { -- | Discard endianness information.+ unEndian :: a }+ deriving stock (Generic, Data, Show)+ deriving (Eq, Ord, Bounded, Num, Enum, Real, Integral) via a+ deriving (IsCBLen, Simple.BLen) via a+ deriving (Weaken, Strengthen) via a+ deriving (ToJSON, FromJSON) via a -deriving instance (Data (IRep sign size), Typeable sign, Typeable size, Typeable e) => Data (I sign size e)-deriving via (IRep sign size) instance Show (IRep sign size) => Show (I sign size e)+-- | Endianness doesn't matter for single bytes.+deriving via Binreply Word8 instance Mason.Put (Endian end Word8) --- Steal various numeric instances from the representation types.-deriving via (IRep sign size) instance Eq (IRep sign size) => Eq (I sign size e)-deriving via (IRep sign size) instance Ord (IRep sign size) => Ord (I sign size e)-deriving via (IRep sign size) instance Bounded (IRep sign size) => Bounded (I sign size e)-deriving via (IRep sign size) instance Num (IRep sign size) => Num (I sign size e)-deriving via (IRep sign size) instance Real (IRep sign size) => Real (I sign size e)-deriving via (IRep sign size) instance Enum (IRep sign size) => Enum (I sign size e)-deriving via (IRep sign size) instance Integral (IRep sign size) => Integral (I sign size e)+-- | Endianness doesn't matter for single bytes.+deriving via Binreply Word8 instance Flatparse.Get (Endian end Word8) --- | Unsigned machine integers can be idealized as naturals.-instance (irep ~ IRep 'U size, Integral irep) => Weaken (I 'U size end) where- type Weak (I 'U size end) = Natural- weaken = fromIntegral-instance (irep ~ IRep 'U size, Integral irep, Bounded irep, Show irep, Typeable size, Typeable end)- => Strengthen (I 'U size end) where- strengthen = strengthenBounded+-- | Endianness doesn't matter for single bytes.+deriving via Binreply Int8 instance Mason.Put (Endian end Int8) --- | Signed machine integers can be idealized as integers.-instance (irep ~ IRep 'S size, Integral irep) => Weaken (I 'S size end) where- type Weak (I 'S size end) = Integer- weaken = fromIntegral-instance (irep ~ IRep 'S size, Integral irep, Bounded irep, Show irep, Typeable size, Typeable end)- => Strengthen (I 'S size end) where- strengthen = strengthenBounded+-- | Endianness doesn't matter for single bytes.+deriving via Binreply Int8 instance Flatparse.Get (Endian end Int8) --- | Machine integer sign.-data ISign- = S -- ^ signed- | U -- ^ unsigned- deriving stock (Generic, Data, Show, Eq)+{- 2023-02-01 raehik:+byteswapping should be faster than poking "backwards" byte by byte. confirmed+with nikita-volkov's ptr-poker package via benchmarks (single operation ~2%+faster) and inspecting disassembly (byteswapX is inlined at the assembly level+as BSWAP, byte by byte takes lots of MOVs and SHRs) --- | Machine integer size in number of bytes.-data ISize = I1 | I2 | I4 | I8- deriving stock (Generic, Data, Show, Eq)+2023-02-18 raehik: this change is applied to nikita-volkov's ptr-poker pkg :)+-} --- | Grouping for matching a signedness and size to a Haskell integer data type.-type family IRep (sign :: ISign) (size :: ISize) where- IRep 'U 'I1 = Word8- IRep 'S 'I1 = Int8- IRep 'U 'I2 = Word16- IRep 'S 'I2 = Int16- IRep 'U 'I4 = Word32- IRep 'S 'I4 = Int32- IRep 'U 'I8 = Word64- IRep 'S 'I8 = Int64+-- | Ask for a minimum length before running the given parser and wrapping the+-- result in 'Endian'.+flatparseParseEndianMin+ :: Flatparse.Getter a -> Int -> Flatparse.Getter (Endian end a)+flatparseParseEndianMin f n =+ Endian <$> Flatparse.getEBase f (Flatparse.ERanOut n) --- Also steal Aeson instances. The parser applies bounding checks appropriately.-deriving via (IRep sign size) instance ToJSON (IRep sign size) => ToJSON (I sign size e)-deriving via (IRep sign size) instance FromJSON (IRep sign size) => FromJSON (I sign size e)+instance Bytezap.Put (Endian 'LE Word16) where put = BZ.w16le . unEndian+instance Flatparse.Get (Endian 'LE Word16) where+ get = flatparseParseEndianMin FP.anyWord16le 2+instance Bytezap.Put (Endian 'BE Word16) where put = BZ.w16be . unEndian+instance Flatparse.Get (Endian 'BE Word16) where+ get = flatparseParseEndianMin FP.anyWord16be 2 -instance KnownNat (CBLen (I sign size end)) => BLen (I sign size end) where- type CBLen (I sign size end) = CBLen (IRep sign size)+instance Bytezap.Put (Endian 'LE Word32) where put = BZ.w32le . unEndian+instance Flatparse.Get (Endian 'LE Word32) where+ get = flatparseParseEndianMin FP.anyWord32le 4+instance Bytezap.Put (Endian 'BE Word32) where put = BZ.w32be . unEndian+instance Flatparse.Get (Endian 'BE Word32) where+ get = flatparseParseEndianMin FP.anyWord32be 4 -instance Put (I 'U 'I1 e) where put = put . getI-instance Get (I 'U 'I1 e) where get = I <$> get-instance Put (I 'S 'I1 e) where put = put . getI-instance Get (I 'S 'I1 e) where get = I <$> get+instance Bytezap.Put (Endian 'LE Word64) where put = BZ.w64le . unEndian+instance Flatparse.Get (Endian 'LE Word64) where+ get = flatparseParseEndianMin FP.anyWord64le 8+instance Bytezap.Put (Endian 'BE Word64) where put = BZ.w64be . unEndian+instance Flatparse.Get (Endian 'BE Word64) where+ get = flatparseParseEndianMin FP.anyWord64be 8 -instance Put (I 'U 'I2 'BE) where put (I i) = Mason.word16BE i-instance Get (I 'U 'I2 'BE) where get = I <$> cutEBase FP.anyWord16be (ERanOut 2)-instance Put (I 'U 'I2 'LE) where put (I i) = Mason.word16LE i-instance Get (I 'U 'I2 'LE) where get = I <$> cutEBase FP.anyWord16le (ERanOut 2)-instance Put (I 'S 'I2 'BE) where put (I i) = Mason.int16BE i-instance Get (I 'S 'I2 'BE) where get = I <$> cutEBase FP.anyInt16be (ERanOut 2)-instance Put (I 'S 'I2 'LE) where put (I i) = Mason.int16LE i-instance Get (I 'S 'I2 'LE) where get = I <$> cutEBase FP.anyInt16le (ERanOut 2)+instance Bytezap.Put (Endian 'LE Int16) where put = BZ.i16le . unEndian+instance Flatparse.Get (Endian 'LE Int16) where+ get = flatparseParseEndianMin FP.anyInt16le 2+instance Bytezap.Put (Endian 'BE Int16) where put = BZ.i16be . unEndian+instance Flatparse.Get (Endian 'BE Int16) where+ get = flatparseParseEndianMin FP.anyInt16be 2 -instance Put (I 'U 'I4 'BE) where put (I i) = Mason.word32BE i-instance Get (I 'U 'I4 'BE) where get = I <$> cutEBase FP.anyWord32be (ERanOut 4)-instance Put (I 'U 'I4 'LE) where put (I i) = Mason.word32LE i-instance Get (I 'U 'I4 'LE) where get = I <$> cutEBase FP.anyWord32le (ERanOut 4)-instance Put (I 'S 'I4 'BE) where put (I i) = Mason.int32BE i-instance Get (I 'S 'I4 'BE) where get = I <$> cutEBase FP.anyInt32be (ERanOut 4)-instance Put (I 'S 'I4 'LE) where put (I i) = Mason.int32LE i-instance Get (I 'S 'I4 'LE) where get = I <$> cutEBase FP.anyInt32le (ERanOut 4)+instance Bytezap.Put (Endian 'LE Int32) where put = BZ.i32le . unEndian+instance Flatparse.Get (Endian 'LE Int32) where+ get = flatparseParseEndianMin FP.anyInt32le 4+instance Bytezap.Put (Endian 'BE Int32) where put = BZ.i32be . unEndian+instance Flatparse.Get (Endian 'BE Int32) where+ get = flatparseParseEndianMin FP.anyInt32be 4 -instance Put (I 'U 'I8 'BE) where put (I i) = Mason.word64BE i-instance Get (I 'U 'I8 'BE) where get = I <$> cutEBase FP.anyWord64be (ERanOut 8)-instance Put (I 'U 'I8 'LE) where put (I i) = Mason.word64LE i-instance Get (I 'U 'I8 'LE) where get = I <$> cutEBase FP.anyWord64le (ERanOut 8)-instance Put (I 'S 'I8 'BE) where put (I i) = Mason.int64BE i-instance Get (I 'S 'I8 'BE) where get = I <$> cutEBase FP.anyInt64be (ERanOut 8)-instance Put (I 'S 'I8 'LE) where put (I i) = Mason.int64LE i-instance Get (I 'S 'I8 'LE) where get = I <$> cutEBase FP.anyInt64le (ERanOut 8)+instance Bytezap.Put (Endian 'LE Int64) where put = BZ.i64le . unEndian+instance Flatparse.Get (Endian 'LE Int64) where+ get = flatparseParseEndianMin FP.anyInt64le 8+instance Bytezap.Put (Endian 'BE Int64) where put = BZ.i64be . unEndian+instance Flatparse.Get (Endian 'BE Int64) where+ get = flatparseParseEndianMin FP.anyInt64be 8 --- | Shortcut.-type family IMax (sign :: ISign) (size :: ISize) :: Natural where- IMax sign size = MaxBound (IRep sign size)+-- | Grouping for matching a signedness and size to a Haskell integer data type.+type family IRep (isign :: ISign) (isize :: Natural) where+ IRep 'U 8 = Word8+ IRep 'I 8 = Int8+ IRep 'U 16 = Word16+ IRep 'I 16 = Int16+ IRep 'U 32 = Word32+ IRep 'I 32 = Int32+ IRep 'U 64 = Word64+ IRep 'I 64 = Int64 --- | Restricted reflected version of @maxBound@.-type family MaxBound w :: Natural where- MaxBound Word8 = 255- MaxBound Int8 = 127- MaxBound Word16 = 65535- MaxBound Int16 = 32767- MaxBound Word32 = 4294967295- MaxBound Int32 = 2147483647- MaxBound Word64 = 18446744073709551615- MaxBound Int64 = 9223372036854775807+-- | 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 where+ IMax 'U n = 2^n-1+ IMax 'I n = 2^(n-1)
− src/Binrep/Type/LenPfx.hs
@@ -1,110 +0,0 @@--- TODO cleanup proxy usage (can we be faster via unboxed @Proxy#@ s ?)--{-# LANGUAGE AllowAmbiguousTypes #-}-{-# LANGUAGE UndecidableInstances #-}--module Binrep.Type.LenPfx where--import Binrep-import Strongweak-import Data.Either.Validation-import Binrep.Type.Vector ( getVector )-import Binrep.Type.Common ( Endianness )-import Binrep.Type.Int-import Binrep.Util ( natVal'' )-import Data.Vector.Sized ( Vector )-import Data.Vector.Sized qualified as V-import GHC.TypeNats-import GHC.TypeLits ( OrderingI(..) )-import Data.Proxy ( Proxy(..) )--import GHC.Generics-import Data.Typeable ( Typeable )---- | Holy shit - no need to do a smart constructor, it's simply impossible to--- instantiate invalid values of this type!-data LenPfx (size :: ISize) (end :: Endianness) a =- forall n. (KnownNat n, n <= IMax 'U size) => LenPfx { unLenPfx :: Vector n a }---- uhhhhhhhhhh i dunno. TODO-instance Generic (LenPfx size end a) where- type Rep (LenPfx size end a) = Rec0 (LenPfx size end a)- from = K1- to = unK1--instance Eq a => Eq (LenPfx size end a) where- (LenPfx a) == (LenPfx b) = vsEq a b---- TODO-instance Show a => Show (LenPfx size end a) where- show (LenPfx a) = "LenPfx ("<>show a<>")"--vsEq :: forall a n m. (Eq a, KnownNat n, KnownNat m) => Vector n a -> Vector m a -> Bool-vsEq vn vm =- if natVal'' @n == natVal'' @m- then V.toList vn == V.toList vm- else False--instance Weaken (LenPfx size end a) where- type Weak (LenPfx size end a) = [a]- weaken (LenPfx v) = V.toList v--instance (KnownNat (MaxBound (IRep 'U size)), Show a, Typeable a, Typeable size, Typeable end)- => Strengthen (LenPfx size end a) where- strengthen l = case lenPfxFromList l of- Nothing -> strengthenFailBase l "TODO doesn't fit"- Just v -> Success v--asLenPfx- :: forall size end n a irep- . (irep ~ IRep 'U size, KnownNat n, KnownNat (MaxBound irep))- => Vector n a -> Maybe (LenPfx size end a)-asLenPfx v =- case cmpNat (Proxy :: Proxy n) (Proxy :: Proxy (MaxBound (IRep 'U size))) of- LTI -> Just $ LenPfx v- EQI -> Just $ LenPfx v- GTI -> Nothing--lenPfxFromList- :: forall size end a irep- . (irep ~ IRep 'U size, KnownNat (MaxBound irep))- => [a] -> Maybe (LenPfx size end a)-lenPfxFromList l = V.withSizedList l asLenPfx--instance (BLen a, itype ~ I 'U size end, KnownNat (CBLen itype))- => BLen (LenPfx size end a) where- blen (LenPfx v) = cblen @itype + blen v--instance (itype ~ I 'U size end, irep ~ IRep 'U size, Put a, Put itype, Num irep)- => Put (LenPfx size end a) where- put (LenPfx v) = put @itype (fromIntegral (vnatVal v)) <> put v- where- vnatVal :: forall n x. KnownNat n => Vector n x -> Natural- vnatVal _ = natVal'' @n--lenPfxSize :: Num (IRep 'U size) => LenPfx size end a -> I 'U size end-lenPfxSize (LenPfx v) = fromIntegral (vnatVal v)- where- vnatVal :: forall n x. KnownNat n => Vector n x -> Natural- vnatVal _ = natVal'' @n--instance (itype ~ I 'U size end, irep ~ IRep 'U size, Get itype, Integral irep, Get a, KnownNat (MaxBound irep))- => Get (LenPfx size end a) where- get = getLenPfx get--getLenPfx- :: forall size end a itype irep- . (itype ~ I 'U size end, irep ~ IRep 'U size, Get itype, Integral irep, KnownNat (MaxBound irep))- => Getter a -> Getter (LenPfx size end a)-getLenPfx g = do- len <- get @itype- case someNatVal (fromIntegral len) of- SomeNat (Proxy :: Proxy n) -> do- x <- getVector @n g- -- TODO we actually know that @n <= MaxBound irep@ before doing this- -- because @len <= maxBound (_ :: irep)@ but that's hard to prove to- -- GHC without lots of refactoring. This is good enough.- case cmpNat (Proxy :: Proxy n) (Proxy :: Proxy (MaxBound irep)) of- GTI -> error "impossible"- LTI -> return $ LenPfx x- EQI -> return $ LenPfx x
src/Binrep/Type/Magic.hs view
@@ -1,12 +1,8 @@-{-# LANGUAGE UndecidableInstances #-}-{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE UndecidableInstances #-} -- for weirder type families {- | Magic numbers (also just magic): short constant bytestrings usually found at the top of a file, often used as an early sanity check. -TODO unassociated type fams bad (maybe). turn into class -- and turn the reifier-into a default method! (TODO think about this)- There are two main flavors of magics: * "random" bytes e.g. Zstandard: @28 B5 2F FD@@@ -28,22 +24,20 @@ import Binrep import Binrep.Type.Byte+import FlatParse.Basic qualified as FP+import Data.ByteString qualified as B import GHC.TypeLits-import Data.ByteString qualified as B-import FlatParse.Basic qualified as FP import GHC.Generics ( Generic ) import Data.Data ( Data ) -import Mason.Builder qualified as Mason- import Strongweak --- | An empty data type representing a magic number (a constant bytestring) via--- a phantom type.+-- | A singleton data type representing a "magic number" (a constant bytestring)+-- via a phantom type. ----- The phantom type variable unambiguously defines a short, constant bytestring.+-- 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@@ -54,25 +48,38 @@ -- origins. instance Weaken (Magic a) where type Weak (Magic a) = ()- weaken _ = ()+ weaken Magic = () -- | Strengthen the unit to some 'Magic a'. instance Strengthen (Magic a) where- strengthen _ = pure Magic+ strengthen () = pure Magic -instance (KnownNat (Length (MagicBytes a))) => BLen (Magic a) where- type CBLen (Magic a) = Length (MagicBytes a)+instance IsCBLen (Magic a) where type CBLen (Magic a) = Length (MagicBytes a)+deriving via CBLenly (Magic a) instance+ KnownNat (Length (MagicBytes a)) => BLen (Magic a) instance (bs ~ MagicBytes a, ReifyBytes bs) => Put (Magic a) where put Magic = reifyBytes @bs -instance (bs ~ MagicBytes a, ReifyBytes bs) => Get (Magic a) where+instance (bs ~ MagicBytes a, ReifyBytes bs, KnownNat (Length bs))+ => Get (Magic a) where+ -- TODO silly optimization: we _could_ skip comparing BS lengths because we+ -- know they have to be the same. lmao get = do- let expected = Mason.toStrictByteString $ reifyBytes @bs- actual <- FP.takeBs $ B.length expected+ -- Nice case where we _want_ flatparse's no-copy behaviour, because+ -- 'actual' is only in scope for this parser. Except, of course, if we+ -- error, in which case _now_ we copy. Efficient!+ actual <- FP.take (blen magic) if actual == expected- then return Magic- else eBase $ EExpected expected actual+ then pure Magic+ else eBase $ EExpected expected (B.copy actual)+ where+ expected = runPut magic+ magic = Magic :: Magic a++type family Length (a :: [k]) :: Natural where+ Length '[] = 0+ Length (a ': as) = 1 + Length as {- I do lots of functions on lists, because they're structurally simple. But you
− src/Binrep/Type/Magic/UTF8.hs
@@ -1,47 +0,0 @@-{- | Inefficient attempt at UTF-8 magics.--To encode UTF-8 strings to bytestrings at compile time, we really need more-support from the compiler. We can go @Char -> Natural@, but we can't go @Natural--> [Natural]@ where each value is @<= 255@. Doing so is hard without bit-twiddling.--The best we can do is get reify the 'Symbol' directly, then encode as UTF-8 at-runtime. It's a bit of a farce, and we can't derive a 'CBLen' instance, but-works just fine. Actually, I dunno, it might be faster than the bytewise magic-handling, depending on how GHC optimizes its instances.--}--{-# LANGUAGE AllowAmbiguousTypes #-}--module Binrep.Type.Magic.UTF8 where--import Binrep--import GHC.TypeLits-import GHC.Exts ( proxy#, Proxy# )-import Data.Text qualified as Text-import Data.Text.Encoding qualified as Text-import Data.ByteString qualified as B-import FlatParse.Basic qualified as FP--data MagicUTF8 (str :: Symbol) = MagicUTF8 deriving Show--symVal :: forall str. KnownSymbol str => String-symVal = symbolVal' (proxy# :: Proxy# str)--instance KnownSymbol str => BLen (MagicUTF8 str) where- blen MagicUTF8 = posIntToBLen $ B.length $ encodeStringUtf8 $ symVal @str--instance KnownSymbol str => Put (MagicUTF8 str) where- put MagicUTF8 = put $ encodeStringUtf8 $ symVal @str--instance KnownSymbol str => Get (MagicUTF8 str) where- get = do- let expected = encodeStringUtf8 $ symVal @str- actual <- FP.takeBs $ B.length expected- if actual == expected- then return MagicUTF8- else eBase $ EExpected expected actual--encodeStringUtf8 :: String -> B.ByteString-encodeStringUtf8 = Text.encodeUtf8 . Text.pack
src/Binrep/Type/NullPadded.hs view
@@ -3,67 +3,64 @@ module Binrep.Type.NullPadded where import Binrep+import Bytezap.Bytes qualified as BZ+import FlatParse.Basic qualified as FP+import Control.Monad.Combinators qualified as Monad+ import Binrep.Util ( tshow ) import Refined import Refined.Unsafe import GHC.TypeNats+import Util.TypeNats ( natValInt )+ import Data.Typeable ( typeRep )-import FlatParse.Basic qualified as FP-import FlatParse.Basic ( Parser )-import Mason.Builder qualified as Mason-import Data.ByteString qualified as BS 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 KnownNat n => BLen (NullPadded n a) where- -- | The size of some null-padded data is known - at compile time!- type CBLen (NullPadded n a) = n- instance (BLen a, KnownNat n) => Predicate (NullPad n) a where validate p a- | len > n+ | len <= n = success+ | otherwise = throwRefineOtherException (typeRep p) $ "too long: " <> tshow len <> " > " <> tshow n- | otherwise = success where- n = typeNatToBLen @n+ n = natValInt @n len = blen a --- TODO cleanup-instance (Put a, BLen a, KnownNat n) => Put (NullPadded n a) where- put wrnpa =- let npa = unrefine wrnpa- paddingLength = n - blen npa- in put npa <> Mason.byteString (BS.replicate (fromIntegral paddingLength) 0x00)+instance (BLen a, Put a, KnownNat n) => Put (NullPadded n a) where+ put ra = put a <> BZ.pokeByteReplicate paddingLen 0x00 where- n = typeNatToBLen @n+ a = unrefine ra+ paddingLen = natValInt @n - blen a+ -- ^ refinement guarantees >=0 --- | Safety: we assert actual length is within expected length (in order to--- calculate how much padding to parse).------ Note that the consumer probably doesn't care about the content of the--- padding, just that the data is chunked correctly. I figure we care about--- correctness here, so it'd be nice to know about the padding well-formedness--- (i.e. that it's all nulls).------ TODO maybe better definition via isolate-instance (Get a, BLen a, KnownNat n) => Get (NullPadded n a) where+instance (BLen a, Get a, KnownNat n) => Get (NullPadded n a) where get = do a <- get- let len = blen a- nullStrLen = n - len- if nullStrLen < 0- then eBase $ EOverlong n len- else getNNulls nullStrLen >> return (reallyUnsafeRefine a)- where- n = typeNatToBLen @n--getNNulls :: BLenT -> Parser E ()-getNNulls = \case 0 -> return ()- n -> FP.anyWord8 >>= \case- 0x00 -> getNNulls $ n-1- nonNull -> eBase $ EExpectedByte 0x00 nonNull+ let paddingLen = natValInt @n - blen a+ if paddingLen < 0+ then eBase $ EFailNamed "TODO used to be EOverlong, cba"+ else do+ Monad.skipCount paddingLen (FP.word8 0x00)+ pure $ reallyUnsafeRefine a
+ src/Binrep/Type/NullTerminated.hs view
@@ -0,0 +1,69 @@+{- | 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 'Binrep.Type.Text'.+-}++{-# LANGUAGE OverloadedStrings #-} -- for refined errors++module Binrep.Type.NullTerminated where++import Binrep++import Binrep.Get.Flatparse qualified as Flatparse+import FlatParse.Basic qualified as FP++import Refined+import Refined.Unsafe+import Data.Typeable ( typeRep )++import Data.ByteString qualified as B+import Data.Word ( Word8 )++-- | Null-terminated data. Arbitrary length terminated with a null byte.+-- Permits no null bytes inside the data.+data NullTerminate+type NullTerminated = Refined NullTerminate++-- | Null-terminated data may not contain any null bytes.+instance NullCheck a => Predicate NullTerminate a where+ validate p a+ | hasNoNulls a = throwRefineOtherException (typeRep p) $+ "null byte not permitted in null-terminated data"+ | otherwise = success++class NullCheck a where hasNoNulls :: a -> Bool+instance NullCheck B.ByteString where+ {-# INLINE hasNoNulls #-}+ hasNoNulls = B.any (== 0x00)++instance BLen a => BLen (NullTerminated a) where+ blen ra = 1 + blen (unrefine ra)+ {-# INLINE blen #-}++-- | Serialization of null-terminated data may be defined generally using the+-- data's underlying serializer.+instance Put a => Put (NullTerminated a) where+ {-# INLINE put #-}+ put a = put (unrefine a) <> put @Word8 0x00++-- | Parse a null-terminated bytestring.+instance Flatparse.Get (NullTerminated B.ByteString) where+ {-# INLINE get #-}+ get = reallyUnsafeRefine <$> Flatparse.getEBase FP.anyCString (EFailNamed "cstring")++{-+I don't know how to do @[a]@. Either I nullterm each element, which is weird+because it's not required in all cases, or I don't, in which case the general+Put doesn't work. Nullterming every element feels weird anyway -- what about+[Word8]?++instance NullCheck a => NullCheck [a] where+ {-# INLINE hasNoNulls #-}+ hasNoNulls = all hasNoNulls+instance NullCheck Word8 where+ {-# INLINE hasNoNulls #-}+ hasNoNulls = \case 0x00 -> False+ _ -> True+-}
+ src/Binrep/Type/Prefix.hs view
@@ -0,0 +1,56 @@+{-# LANGUAGE UndecidableInstances #-} -- for convenient type level arithmetic++module Binrep.Type.Prefix where++import Binrep.Type.Int+import GHC.TypeNats+import Data.Word++import Data.Kind++-- | 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 'Int's 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 :: Int -> a++ -- | used by get. better not lie.+ pfxToLen :: a -> Int++-- | Length prefixing with the unit means a length of 0.+--+-- This is the only sensible case. 1 doesn't work because refining checks @<=@.+--+-- I think there are laws here, where using this is the same as doing nothing at+-- all.+instance Prefix () where+ type Max () = 0+ lenToPfx 0 = ()+ lenToPfx _ = error "you lied to refine and broke everything :("+ pfxToLen () = 0++deriving via (a :: Type) instance Prefix a => Prefix (Endian end a)++instance Prefix Word8 where+ type Max Word8 = 2^8 - 1+ lenToPfx = fromIntegral+ pfxToLen = fromIntegral+instance Prefix Word16 where+ type Max Word16 = 2^16 - 1+ lenToPfx = fromIntegral+ pfxToLen = fromIntegral+instance Prefix Word32 where+ type Max Word32 = 2^32 - 1+ lenToPfx = fromIntegral+ pfxToLen = fromIntegral++-- TODO no instances > Int, since they would break when too large
+ src/Binrep/Type/Prefix/Count.hs view
@@ -0,0 +1,55 @@+{-# LANGUAGE UndecidableInstances #-} -- required for type-level stuff+{-# LANGUAGE OverloadedStrings #-} -- required for refined errors++module Binrep.Type.Prefix.Count where++import Binrep.Type.Prefix+import Binrep+import Control.Monad.Combinators qualified as Monad++import GHC.TypeNats+import Util.TypeNats ( natValInt )+import Refined hiding ( Weaken(..), strengthen )+import Refined.Unsafe ( reallyUnsafeRefine1 )++import Data.Typeable ( Typeable, typeRep )+import Data.Kind++import Data.Foldable qualified as Foldable++data CountPrefix (pfx :: Type)+type CountPrefixed pfx = Refined1 (CountPrefix pfx)++instance (KnownNat (Max pfx), Foldable f, Typeable pfx)+ => Predicate1 (CountPrefix pfx) f where+ validate1 p fa+ | Foldable.length fa <= natValInt @(Max pfx) = success+ | otherwise = throwRefineOtherException (typeRep p) "TODO bad"++instance (KnownNat (Max pfx), Foldable f, Typeable pfx)+ => Predicate (CountPrefix pfx) (f a) where+ validate = validate1++-- TODO no idea if this is sensible+instance IsCBLen (CountPrefixed pfx f a) where+ type CBLen (CountPrefixed pfx f a) = CBLen pfx + CBLen (f a)++instance (Prefix pfx, Foldable f, BLen pfx, BLen (f a))+ => BLen (CountPrefixed pfx f a) where+ blen rfa = blen (lenToPfx @pfx (Foldable.length fa)) + blen fa+ where fa = unrefine1 rfa++instance (Prefix pfx, Foldable f, Put pfx, Put (f a))+ => Put (CountPrefixed pfx f a) where+ put rfa = put (lenToPfx @pfx (Foldable.length fa)) <> put fa+ where fa = unrefine1 rfa++class GetCount f where getCount :: Get a => Int -> Getter (f a)+instance GetCount [] where getCount n = Monad.count n get++instance (Prefix pfx, GetCount f, Get pfx, Get a)+ => Get (CountPrefixed pfx f a) where+ get = do+ pfx <- get @pfx+ fa <- getCount (pfxToLen pfx)+ pure $ reallyUnsafeRefine1 fa
+ src/Binrep/Type/Prefix/Size.hs view
@@ -0,0 +1,53 @@+{-# LANGUAGE UndecidableInstances #-} -- required for type-level stuff+{-# LANGUAGE OverloadedStrings #-} -- required for refined errors++module Binrep.Type.Prefix.Size where++import Binrep.Type.Prefix+import Binrep.Type.Thin+import Binrep+import FlatParse.Basic qualified as FP++import GHC.TypeNats+import Util.TypeNats ( natValInt )+import Data.ByteString qualified as B+import Refined hiding ( Weaken(..), strengthen )+import Refined.Unsafe++import Data.Typeable ( Typeable, typeRep )+import Data.Kind++data SizePrefix (pfx :: Type)+type SizePrefixed pfx = Refined (SizePrefix pfx)++instance (KnownNat (Max pfx), BLen a, Typeable pfx)+ => Predicate (SizePrefix pfx) a where+ validate p a+ | blen a <= natValInt @(Max pfx) = Nothing+ | otherwise = throwRefineOtherException (typeRep p) $+ "thing too big for length prefix type"++-- TODO no idea if this is sensible+instance IsCBLen (SizePrefixed pfx a) where+ type CBLen (SizePrefixed pfx a) = CBLen pfx + CBLen a++instance (Prefix pfx, BLen a, BLen pfx)+ => BLen (SizePrefixed pfx a) where+ blen ra = blen (lenToPfx @pfx (blen a)) + blen a+ where a = unrefine ra++instance (Prefix pfx, BLen a, Put pfx, Put a)+ => Put (SizePrefixed pfx a) where+ put ra = put (lenToPfx @pfx (blen a)) <> put a+ where a = unrefine ra++class GetSize a where getSize :: Int -> Getter a+instance GetSize B.ByteString where getSize = fmap B.copy . FP.take+instance GetSize (Thin B.ByteString) where getSize = fmap Thin . FP.take++instance (Prefix pfx, GetSize a, Get pfx)+ => Get (SizePrefixed pfx a) where+ get = do+ pfx <- get @pfx+ a <- getSize (pfxToLen pfx)+ pure $ reallyUnsafeRefine a
src/Binrep/Type/Sized.hs view
@@ -5,38 +5,39 @@ module Binrep.Type.Sized where import Binrep+import FlatParse.Basic qualified as FP+ import Binrep.Util ( tshow ) import Refined import Refined.Unsafe+import Data.Typeable ( typeRep ) import GHC.TypeNats-import Data.Typeable ( typeRep )-import FlatParse.Basic qualified as FP+import Util.TypeNats ( natValInt ) +-- | Essentially reflects a 'BLen' type to 'CBLen'. data Size (n :: Natural)--type Sized n a = Refined (Size n) a--instance KnownNat n => BLen (Sized n a) where type CBLen (Sized n a) = n+type Sized n = Refined (Size n) instance (BLen a, KnownNat n) => Predicate (Size n) a where validate p a- | len > n+ | len /= n = throwRefineOtherException (typeRep p) $ "not correctly sized: "<>tshow len<>" /= "<>tshow n | otherwise = success where- n = typeNatToBLen @n+ n = natValInt @n len = blen a +instance IsCBLen (Sized n a) where type CBLen (Sized n a) = n+deriving via CBLenly (Sized n a) instance KnownNat n => BLen (Sized n a)+ instance Put a => Put (Sized n a) where put = put . unrefine -- TODO safety: isolate consumes all bytes if succeeds instance (Get a, KnownNat n) => Get (Sized n a) where get = do- a <- FP.isolate (fromIntegral n) get- return $ reallyUnsafeRefine a- where- n = typeNatToBLen @n+ a <- FP.isolate (natValInt @n) get+ pure $ reallyUnsafeRefine a
src/Binrep/Type/Text.hs view
@@ -1,193 +1,53 @@-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE AllowAmbiguousTypes #-}-{-# LANGUAGE CPP #-}+{- TODO 2023-02-15 raehik+Encoding shouldn't change to a bytestring, for efficiency. Due to convenient+representations, we can efficiently serialize a Text directly to a builder,+skipping intermediate ByteString conversion. +Hm. Maybe that means it should be changed to the builder. What does that mean+for decoding?+-}+ module Binrep.Type.Text- ( Encoding(..)- , AsText- , Encode, encode+ ( AsText+ , Encode(..), encode, encodeToRep , Decode(..)- , encodeToRep-#ifdef HAVE_ICU- , decodeViaTextICU-#endif- ) where -import Binrep.Type.Common ( Endianness(..) )-import Binrep.Type.ByteString ( Rep )--import Refined-import Refined.Unsafe--import Data.ByteString qualified as B-import Data.Text qualified as Text-import Data.Text ( Text )-import Data.Char qualified as Char-import Data.Text.Encoding qualified as Text-import Data.Either.Combinators qualified as Either--import GHC.Generics ( Generic )-import Data.Data ( Data )--import Data.Typeable ( Typeable, typeRep )--import System.IO.Unsafe qualified-import Control.Exception qualified-import Data.Text.Encoding.Error qualified--#ifdef HAVE_ICU-import Data.Text.ICU.Convert qualified as ICU-#endif--type Bytes = B.ByteString---- | Character encoding.------ Byte-oriented encodings like ASCII and UTF-8 don't need to worry about--- endianness. For UTF-16 and UTF-32, the designers decided to allow different--- endiannesses, rather than saying "codepoints must be X-endian".-data Encoding- = UTF8- | UTF16 Endianness- | UTF32 Endianness- | ASCII -- ^ 7-bit- | SJIS- deriving stock (Generic, Data, Show, Eq)---- | A string of a given encoding, stored in the 'Text' type.-type AsText (enc :: Encoding) = Refined enc Text+ , module Binrep.Type.Text.Encoding.Utf8+ , module Binrep.Type.Text.Encoding.Ascii+ , module Binrep.Type.Text.Encoding.Utf16+ , module Binrep.Type.Text.Encoding.Utf32+ , module Binrep.Type.Text.Encoding.ShiftJis --- | Bytestring encoders for text validated for a given encoding.-class Encode (enc :: Encoding) where- -- | Encode text to bytes. Internal function, use 'encode'.- encode' :: Text -> Bytes+ ) where -instance Encode 'UTF8 where encode' = Text.encodeUtf8+import Binrep.Type.Text.Internal --- | ASCII is a subset of UTF-8, so valid ASCII is valid UTF-8, so this is safe.-instance Encode 'ASCII where encode' = encode' @'UTF8+import Refined -instance Encode ('UTF16 'BE) where encode' = Text.encodeUtf16BE-instance Encode ('UTF16 'LE) where encode' = Text.encodeUtf16LE-instance Encode ('UTF32 'BE) where encode' = Text.encodeUtf32BE-instance Encode ('UTF32 'LE) where encode' = Text.encodeUtf32LE+import Binrep.Type.Text.Encoding.Utf8+import Binrep.Type.Text.Encoding.Ascii+import Binrep.Type.Text.Encoding.Utf16+import Binrep.Type.Text.Encoding.Utf32+import Binrep.Type.Text.Encoding.ShiftJis -- | Encode some validated text. encode :: forall enc. Encode enc => AsText enc -> Bytes encode = encode' @enc . unrefine --- | Any 'Text' value is always valid UTF-8.-instance Predicate 'UTF8 Text where validate _ _ = success---- | Any 'Text' value is always valid UTF-16.-instance Typeable e => Predicate ('UTF16 e) Text where validate _ _ = success---- | Any 'Text' value is always valid UTF-32.-instance Typeable e => Predicate ('UTF32 e) Text where validate _ _ = success---- | 'Text' must be validated if you want to permit 7-bit ASCII only.-instance Predicate 'ASCII Text where- validate p t = if Text.all Char.isAscii t- then success- else throwRefineOtherException (typeRep p) "not valid 7-bit ASCII"---- | TODO Unsafely assume all 'Text's are valid Shift-JIS.-instance Predicate 'SJIS Text where validate _ _ = success--class Decode (enc :: Encoding) where- -- | Decode a 'ByteString' to 'Text' with an explicit encoding.- --- -- This is intended to be used with visible type applications.- decode :: Bytes -> Either String (AsText enc)--instance Decode 'UTF8 where decode = decodeText show Text.decodeUtf8'-instance Decode ('UTF16 'BE) where decode = decodeText show $ wrapUnsafeDecoder Text.decodeUtf16BE-instance Decode ('UTF16 'LE) where decode = decodeText show $ wrapUnsafeDecoder Text.decodeUtf16LE-instance Decode ('UTF32 'BE) where decode = decodeText show $ wrapUnsafeDecoder Text.decodeUtf32BE-instance Decode ('UTF32 'LE) where decode = decodeText show $ wrapUnsafeDecoder Text.decodeUtf32LE---- Pre-@text-2.0@, @decodeASCII@ generated a warning and ran @decodeUtf8@.-#if MIN_VERSION_text(2,0,0)-instance Decode 'ASCII where decode = decodeText $ wrapUnsafeDecoder Text.decodeASCII-#endif------------------------------------------------------------------------------------- Helpers- -- | 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")+-- >>> let Right t = refine @UTF8 (Text.pack "hi") -- >>> :t t--- t :: AsText 'UTF8+-- t :: AsText UTF8 -- >>> let Right bs = encodeToRep @'C t -- >>> :t bs -- bs :: Refined 'C Bytes encodeToRep- :: forall (rep :: Rep) enc+ :: forall rep enc . (Encode enc, Predicate rep Bytes) => AsText enc -> Either RefineException (Refined rep Bytes) encodeToRep = refine . encode------------------------------------------------------------------------------------- Internal helpers---- | 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)-decodeText g f = Either.mapBoth g reallyUnsafeRefine . f---- | Run an unsafe decoder safely.------ Copied from @Data.Text.Encoding.decodeUtf8'@, so should be bulletproof?-wrapUnsafeDecoder- :: (Bytes -> Text)- -> Bytes -> Either Data.Text.Encoding.Error.UnicodeException Text-wrapUnsafeDecoder f =- System.IO.Unsafe.unsafeDupablePerformIO- . Control.Exception.try- . Control.Exception.evaluate- . f------------------------------------------------------------------------------------- ICU--#ifdef HAVE_ICU-instance Encode 'SJIS where encode' = encodeViaTextICU' "Shift-JIS"-instance Decode 'SJIS where- decode = decodeText id $ decodeViaTextICU' "Shift-JIS"---- | 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 B.ByteString-encodeViaTextICU charset t = do- conv <- ICU.open charset Nothing- return $ ICU.fromUnicode conv t--encodeViaTextICU' :: String -> Text -> B.ByteString-encodeViaTextICU' charset t =- System.IO.Unsafe.unsafeDupablePerformIO $ encodeViaTextICU charset t---- TODO Shitty library doesn't let us say how to handle errors. Apparently, the--- only solution is to scan through the resulting 'Text' to look for @\SUB@--- characters, or lie about correctness. Sigh.-decodeViaTextICU :: String -> B.ByteString -> IO (Either String Text)-decodeViaTextICU charset t = do- conv <- ICU.open charset Nothing- return $ Right $ ICU.toUnicode conv t--decodeViaTextICU' :: String -> B.ByteString -> Either String Text-decodeViaTextICU' charset t = do- System.IO.Unsafe.unsafeDupablePerformIO $ decodeViaTextICU charset t-#endif
+ src/Binrep/Type/Text/Encoding/Ascii.hs view
@@ -0,0 +1,47 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE OverloadedStrings #-}++module Binrep.Type.Text.Encoding.Ascii where++import Binrep.Type.Text.Internal+import Binrep.Type.Text.Encoding.Utf8++import Refined+import Data.Typeable ( typeRep )++import Data.Char qualified as Char+import Data.Text qualified as Text+import Data.Text ( Text )++import Data.Text.Encoding qualified as Text+import Control.Exception qualified+import System.IO.Unsafe qualified++-- | 7-bit+data Ascii++-- | We reuse UTF-8 encoding for ASCII, since it is a subset of UTF-8.+instance Encode Ascii where encode' = encode' @Utf8++-- Pre-@text-2.0@, @decodeASCII@ generated a warning and ran @decodeUtf8@.+-- TODO can I give some compile time warning about this instance missing on+-- below text-2.0?? would be cool+#if MIN_VERSION_text(2,0,0)+-- TODO 2023-01-26 raehik: awful UX by text. hopefully safe lol?? works at least+instance Decode Ascii where decode = decodeText id $ catchErrorCall Text.decodeASCII+#endif++catchErrorCall :: (a -> b) -> a -> Either String b+catchErrorCall f a = System.IO.Unsafe.unsafeDupablePerformIO $ do+ Control.Exception.try @Control.Exception.ErrorCall (Control.Exception.evaluate (f a)) >>= \case+ Right b -> pure $ Right b+ Left (Control.Exception.ErrorCallWithLocation msg _) -> pure $ Left msg++-- | 'Text' must be validated if you want to permit 7-bit ASCII only.+--+-- TODO there should be a MUCH faster check here in text-2.0. text-short has it,+-- text doesn't yet. see: https://github.com/haskell/text/issues/496+instance Predicate Ascii Text where+ validate p t = if Text.all Char.isAscii t+ then success+ else throwRefineOtherException (typeRep p) "not valid 7-bit ASCII"
+ src/Binrep/Type/Text/Encoding/ShiftJis.hs view
@@ -0,0 +1,55 @@+{-# LANGUAGE CPP #-}++module Binrep.Type.Text.Encoding.ShiftJis where++import Refined++import Data.Text ( Text )++#ifdef HAVE_ICU+import Data.Text.ICU.Convert qualified as ICU+import System.IO.Unsafe qualified+import Data.ByteString qualified as B++import Binrep.Type.Text.Internal+#endif++data ShiftJis++-- | TODO Unsafely assume all 'Text's are valid Shift-JIS.+instance Predicate ShiftJis Text where validate _ _ = success++#ifdef HAVE_ICU+instance Encode ShiftJis where encode' = encodeViaTextICU' "Shift-JIS"+instance Decode ShiftJis where+ decode = decodeText id $ decodeViaTextICU' "Shift-JIS"++-- | 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 B.ByteString+encodeViaTextICU charset t = do+ conv <- ICU.open charset Nothing+ pure $ ICU.fromUnicode conv t++encodeViaTextICU' :: String -> Text -> B.ByteString+encodeViaTextICU' charset t =+ System.IO.Unsafe.unsafeDupablePerformIO $ encodeViaTextICU charset t++-- TODO Shitty library doesn't let us say how to handle errors. Apparently, the+-- only solution is to scan through the resulting 'Text' to look for @\SUB@+-- characters, or lie about correctness. Sigh.+decodeViaTextICU :: String -> B.ByteString -> IO (Either String Text)+decodeViaTextICU charset t = do+ conv <- ICU.open charset Nothing+ pure $ Right $ ICU.toUnicode conv t++decodeViaTextICU' :: String -> B.ByteString -> Either String Text+decodeViaTextICU' charset t = do+ System.IO.Unsafe.unsafeDupablePerformIO $ decodeViaTextICU charset t+#endif
+ src/Binrep/Type/Text/Encoding/Utf16.hs view
@@ -0,0 +1,21 @@+module Binrep.Type.Text.Encoding.Utf16 where++import Binrep.Type.Text.Internal+import Binrep.Type.Common ( Endianness(..) )++import Refined+import Data.Typeable ( Typeable )++import Data.Text.Encoding qualified as Text+import Data.Text ( Text )++data Utf16 (end :: Endianness)++instance Encode (Utf16 'BE) where encode' = Text.encodeUtf16BE+instance Encode (Utf16 'LE) where encode' = Text.encodeUtf16LE++instance Decode (Utf16 'BE) where decode = decodeText show $ wrapUnsafeDecoder Text.decodeUtf16BE+instance Decode (Utf16 'LE) where decode = decodeText show $ wrapUnsafeDecoder Text.decodeUtf16LE++-- | Any 'Text' value is always valid UTF-16.+instance Typeable end => Predicate (Utf16 end) Text where validate _ _ = success
+ src/Binrep/Type/Text/Encoding/Utf32.hs view
@@ -0,0 +1,21 @@+module Binrep.Type.Text.Encoding.Utf32 where++import Binrep.Type.Text.Internal+import Binrep.Type.Common ( Endianness(..) )++import Refined+import Data.Typeable ( Typeable )++import Data.Text.Encoding qualified as Text+import Data.Text ( Text )++data Utf32 (end :: Endianness)++instance Encode (Utf32 'BE) where encode' = Text.encodeUtf32BE+instance Encode (Utf32 'LE) where encode' = Text.encodeUtf32LE++instance Decode (Utf32 'BE) where decode = decodeText show $ wrapUnsafeDecoder Text.decodeUtf32BE+instance Decode (Utf32 'LE) where decode = decodeText show $ wrapUnsafeDecoder Text.decodeUtf32LE++-- | Any 'Text' value is always valid UTF-32.+instance Typeable end => Predicate (Utf32 end) Text where validate _ _ = success
+ src/Binrep/Type/Text/Encoding/Utf8.hs view
@@ -0,0 +1,16 @@+module Binrep.Type.Text.Encoding.Utf8 where++import Binrep.Type.Text.Internal++import Refined++import Data.Text.Encoding qualified as Text+import Data.Text ( Text )++data Utf8++instance Encode Utf8 where encode' = Text.encodeUtf8+instance Decode Utf8 where decode = decodeText show Text.decodeUtf8'++-- | Any 'Text' value is always valid UTF-8.+instance Predicate Utf8 Text where validate _ _ = success
+ src/Binrep/Type/Text/Internal.hs view
@@ -0,0 +1,55 @@+{-# LANGUAGE AllowAmbiguousTypes #-}++module Binrep.Type.Text.Internal where++import Data.Text ( Text )+import Data.ByteString qualified as B+import Refined+import Refined.Unsafe ( reallyUnsafeRefine )++import System.IO.Unsafe qualified+import Control.Exception qualified+import Data.Text.Encoding.Error qualified+import Data.Bifunctor ( bimap )++type Bytes = B.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 where+ -- | Encode text to bytes. Internal function, use 'encode'.+ encode' :: Text -> Bytes++class Decode enc where+ -- | Decode a 'ByteString' to 'Text' with an explicit encoding.+ --+ -- This is intended to be used with visible type applications.+ decode :: Bytes -> Either String (AsText enc)++--------------------------------------------------------------------------------+-- Internal helpers++-- | 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)+decodeText g f = bimap g reallyUnsafeRefine . f++-- | Run an unsafe decoder safely.+--+-- Copied from @Data.Text.Encoding.decodeUtf8'@, so should be bulletproof?+wrapUnsafeDecoder+ :: (Bytes -> Text)+ -> Bytes -> Either Data.Text.Encoding.Error.UnicodeException Text+wrapUnsafeDecoder f =+ System.IO.Unsafe.unsafeDupablePerformIO+ . Control.Exception.try+ . Control.Exception.evaluate+ . f
+ src/Binrep/Type/Thin.hs view
@@ -0,0 +1,55 @@+{- | "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.++-}++{-# LANGUAGE UndecidableInstances #-} -- for strongweak derivingvia++module Binrep.Type.Thin where++import Binrep++import FlatParse.Basic qualified as FP+import Bytezap qualified as BZ+import Bytezap.Bytes qualified as BZ++import GHC.Generics ( Generic )+import Data.Data ( Data )+import GHC.Exts ( IsList )+import Data.String+import Control.DeepSeq+import Data.Functor.Identity+import Strongweak++import Data.ByteString qualified as B++newtype Thin a = Thin { unThin :: a }+ -- derive all instances that 'Data.ByteString.ByteString' has+ deriving stock (Generic, Data, Show, Read)+ deriving+ ( Eq, Ord, Semigroup, Monoid -- simple+ , NFData, IsString, IsList -- weird+ , BLen, Put -- binrep+ ) via a++ -- at the end of the day, we are the identity functor+ deriving (Weaken, Strengthen) via Identity a++instance Get (Thin B.ByteString) where get = Thin <$> FP.takeRest+instance Get (Thin BZ.Write) where+ get = fmap Thin $ fmap BZ.byteString $ FP.takeRest
− src/Binrep/Type/Varint.hs
@@ -1,136 +0,0 @@-{- | Variable-length integers (varints), a method to store arbitrarily large- integers in a space efficient manner.--Note that varints aren't particularly efficient due to their decoding being-slow. They are most interesting when you wish to provide support for large-integers, but know that many (most?) inputs will be small, and want to be space-efficient for them. Protocol Buffers uses them extensively, while Cap'n Proto-swears them off.--TODO-- * https://en.wikipedia.org/wiki/Variable-length_quantity- * I've defined basic unsigned varints. Signed varints have lots of options.- You can use twos comp, zigzag, a sign bit, whatever.--}--{-# LANGUAGE AllowAmbiguousTypes #-}--module Binrep.Type.Varint where--import Binrep-import Binrep.Type.Common ( Endianness(..) )--import Data.Bits-import FlatParse.Basic qualified as FP--import Data.Word ( Word8 )---- | A variable-length unsigned integer (natural).------ The base algorithm is to split the natural into groups of 7 bits, and use the--- MSB to indicate whether another octet follows. You must specify a handful of--- type variables, which select precise varint behaviour beyond this. See their--- documentation for details.------ You may select the type to use varnats at, but error handling isn't provided:--- negatives won't work correctly, and overflow cannot be detected. So most of--- the time, you probably want 'Natural' and 'Integer'.------ Some examples:------ * @'Varnat' ''Redundant' ''OnContinues' ''BE' matches VLQ.--- * @'Varnat' ''Redundant' ''OnContinues' ''LE' matches LEB128, protobuf.--- * @'Varnat' ''Bijective' ''OnContinues' ''LE' matches Git's varints.--- * @'Varnat' ''Bijective' ''OffContinues' ''LE' matches BPS's varints.-newtype Varnat (enc :: Encoding) (cont :: ContinuationBitBehaviour) (e :: Endianness) i = Varnat { getVarnat :: i }- deriving (Eq, Ord, Enum, Num, Real, Integral) via i- deriving stock Show--data ContinuationBitBehaviour- = OnContinues- -- ^ on=continue, off=end-- | OffContinues- -- ^ on=end, off=continue--data Encoding- = Redundant- -- ^ simple, some varints have the same value-- | Bijective- -- ^ each integer has exactly 1 varint encoding---- | VLQ (cont=on)-instance (VarintContinuation cont, Integral i, Bits i) => Get (Varnat 'Redundant cont 'BE i) where- get = go (0 :: i)- where- go i = do- w8 <- FP.anyWord8- let i' = unsafeShiftL i 7 .|. fromIntegral (clearBit w8 7)- if testVarintCont @cont w8 7 then go i' else pure (Varnat i')---- | TODO nothing to test against - unsure if correct-instance (VarintContinuation cont, Integral i, Bits i) => Get (Varnat 'Bijective cont 'BE i) where- get = go (0 :: i)- where- go i = do- w8 <- FP.anyWord8- let i' = unsafeShiftL i 7 .|. (fromIntegral (clearBit w8 7) + 1)- if testVarintCont @cont w8 7 then go i' else pure (Varnat (i'-1))---- | protobuf (cont=on), LEB128 (cont=on)------ not truly infinite length since shifters take 'Int', but practically infinite-instance (VarintContinuation cont, Integral i, Bits i) => Get (Varnat 'Redundant cont 'LE i) where- get = go (0 :: i) (0 :: Int)- where- go i n = do- w8 <- FP.anyWord8- let i' = i .|. unsafeShiftL (fromIntegral (clearBit w8 7)) n- if testVarintCont @cont w8 7 then go i' (n+7) else pure (Varnat i')---- | Git varint (cont=on), BPS (beat patches) (cont=off)-instance (VarintContinuation cont, Integral i, Bits i) => Get (Varnat 'Bijective cont 'LE i) where- get = go (0 :: i) (0 :: Int)- where- go i n = do- w8 <- FP.anyWord8- let i' = i .|. unsafeShiftL (fromIntegral (clearBit w8 7) + 1) n- if testVarintCont @cont w8 7 then go i' (n+7) else pure (Varnat (i'-1))---- TODO uses fromIntegral's overflow behaviour-instance (VarintContinuation cont, Integral i, Bits i) => Put (Varnat 'Redundant cont 'LE i) where- put (Varnat i) = do- if i < 0b10000000 then- put @Word8 $ fromIntegral i- else- put @Word8 (setVarintCont @cont (fromIntegral i) 7)- <> put @(Varnat 'Redundant cont 'LE i) (Varnat (unsafeShiftR i 7))---- TODO BE. Hard.-instance (VarintContinuation cont, Integral i, Bits i) => Put (Varnat 'Redundant cont 'BE i) where- put (Varnat i) = do- if i < 0b10000000 then- put @Word8 $ fromIntegral i- else- put @(Varnat 'Redundant cont 'LE i) (Varnat (unsafeShiftR i 7))- <> put @Word8 (setVarintCont @cont (fromIntegral (i .&. 0b11111111)) 7)------------------------------------------------------------------------------------class VarintContinuation (cont :: ContinuationBitBehaviour) where- varintContinue :: Bool-instance VarintContinuation 'OnContinues where varintContinue = True-instance VarintContinuation 'OffContinues where varintContinue = False--testVarintCont- :: forall cont a. VarintContinuation cont => Bits a => a -> Int -> Bool-testVarintCont a n = case varintContinue @cont of True -> b- False -> not b- where b = testBit a n--setVarintCont- :: forall cont a. VarintContinuation cont => Bits a => a -> Int -> a-setVarintCont = case varintContinue @cont of True -> setBit- False -> clearBit
− src/Binrep/Type/Vector.hs
@@ -1,25 +0,0 @@--- | Sized vectors.--{-# LANGUAGE NoStarIsType #-}-{-# LANGUAGE UndecidableInstances #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}--module Binrep.Type.Vector where--import Binrep-import Data.Vector.Sized qualified as V-import Data.Vector.Sized ( Vector )-import GHC.TypeNats--instance BLen a => BLen (Vector n a) where- type CBLen (Vector n a) = CBLen a * n- blen = V.sum . V.map blen--instance Put a => Put (Vector n a) where- put = mconcat . V.toList . V.map put--instance (Get a, KnownNat n) => Get (Vector n a) where- get = getVector get--getVector :: KnownNat n => Getter a -> Getter (Vector n a)-getVector g = V.replicateM g
+ src/Binrep/Util/Class.hs view
@@ -0,0 +1,19 @@+module Binrep.Util.Class where++import GHC.TypeLits++-- | Common type error string for when you attempt to use a binrep instance at+-- an empty data type (e.g. 'Data.Void.Void', 'GHC.Generics.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"
+ src/Binrep/Util/Generic.hs view
@@ -0,0 +1,19 @@+module Binrep.Util.Generic where++import GHC.TypeLits++-- | 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"
+ src/Binrep/Via.hs view
@@ -0,0 +1,12 @@+module Binrep.Via where++import Binrep.CBLen qualified as BR+import Binrep.BLen.Simple qualified as BR.Simple+import Binrep.Put.Mason qualified as BR.Mason+import Binrep.Put.Bytezap qualified as BR.Bytezap+import Binrep.Get.Flatparse qualified as BR.Flatparse++-- | Identity newtype for using with @DerivingVia@.+newtype Binreply a = Binreply { unBinreply :: a }+ deriving stock Show+ deriving (BR.IsCBLen, BR.Simple.BLen, BR.Mason.Put, BR.Bytezap.Put, BR.Flatparse.Get) via a
+ src/Bytezap.hs view
@@ -0,0 +1,97 @@+{-# LANGUAGE UnboxedTuples #-}++module Bytezap where++import GHC.Exts+import Data.ByteString qualified as B+import Data.ByteString.Internal qualified as B+import GHC.IO+import Data.Word++-- | 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+ { -- | 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#+ }++-- | Construct a 'Poke'.+poke :: Poke# -> Poke+poke = Poke+{-# INLINE poke #-}++-- | Sequence two 'Poke's left-to-right.+instance Semigroup Poke where+ {-# INLINE (<>) #-}+ Poke l <> Poke r = Poke $ \addr# st# ->+ case l addr# st# of (# st'#, addr'# #) -> r addr'# st'#++-- | The empty 'Poke' simply returns its arguments.+instance Monoid Poke where+ {-# INLINE mempty #-}+ mempty = Poke $ \addr# st# -> (# st#, addr# #)++-- | 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 -> B.ByteString+runPoke len = B.unsafeCreate len . wrapPoke+{-# INLINE runPoke #-}++wrapPoke :: Poke -> Ptr Word8 -> IO ()+wrapPoke (Poke p) (Ptr addr#) =+ IO (\st# -> case p addr# st# of (# l, _r #) -> (# l, () #))+{-# INLINE wrapPoke #-}++-- | 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+ { writeSize :: {-# UNPACK #-} !Int+ , writePoke :: !Poke -- unpack unusable TODO is strict good or not here+ }++-- | Construct a 'Write'.+write :: Int -> Poke# -> Write+write len p = Write len (Poke p)+{-# INLINE write #-}++-- | Sequence the 'Poke's, sum the sizes.+instance Semigroup Write where+ -- TODO feels like this might be INLINE[1] or even INLINE[0]?+ {-# INLINE (<>) #-}+ Write ll lp <> Write rl rp = Write (ll + rl) (lp <> rp)++-- | The empty 'Write' is the empty 'Poke', which writes zero bytes.+instance Monoid Write where+ {-# INLINE mempty #-}+ mempty = Write 0 mempty++-- | Serialize and show the resulting ByteString.+instance Show Write where showsPrec p = showsPrec p . runWrite++runWrite :: Write -> B.ByteString+runWrite (Write len p) = runPoke len p+{-# INLINE runWrite #-}
+ src/Bytezap/Bytes.hs view
@@ -0,0 +1,41 @@+-- | 'ByteString's and primitive byte arrays.++{-# LANGUAGE UnboxedTuples #-}++module Bytezap.Bytes where++import Bytezap++import GHC.Exts+import Data.ByteString qualified as B+import Data.ByteString.Internal qualified as B+import GHC.IO+import Data.Word+import Foreign.ForeignPtr++byteString :: B.ByteString -> Write+byteString (B.BS fptr len) = Write len (pokeForeignPtr fptr len)+{-# INLINE byteString #-}++pokeForeignPtr :: ForeignPtr Word8 -> Int -> Poke+pokeForeignPtr fptr len@(I# len#) = poke $ \addr# st# ->+ case unIO (memcpyForeignPtr (Ptr addr#) fptr len) st# of+ (# st'#, () #) -> (# st'#, addr# `plusAddr#` len# #)+{-# INLINE pokeForeignPtr #-}++memcpyForeignPtr :: Ptr Word8 -> ForeignPtr Word8 -> Int -> IO ()+memcpyForeignPtr ptrTo fptrFrom len =+ B.unsafeWithForeignPtr fptrFrom $ \ptrFrom -> B.memcpy ptrTo ptrFrom len+{-# INLINE memcpyForeignPtr #-}++pokeByteArray# :: ByteArray# -> Int# -> Int# -> Poke+pokeByteArray# arr# off# len# = poke $ \addr# st# ->+ case copyByteArrayToAddr# arr# off# addr# len# st# of+ st'# -> (# st'#, addr# `plusAddr#` len# #)+{-# INLINE pokeByteArray# #-}++-- TODO this seems to work but like, really? wow lol+pokeByteReplicate :: Int -> Word8 -> Poke+pokeByteReplicate n@(I# n#) w8 = poke $ \addr# st# ->+ case unIO (B.memset (Ptr addr#) w8 (fromIntegral n)) st# of+ (# st'#, _ #) -> (# st'#, addr# `plusAddr#` n# #)
+ src/Bytezap/Class.hs view
@@ -0,0 +1,51 @@+module Bytezap.Class where++import Bytezap+import Bytezap.Bytes qualified as W+import Bytezap.Int qualified as W++import Data.ByteString ( ByteString )+import Data.Word+import Data.Int++class Put a where put :: a -> Write++instance Put Write where+ {-# INLINE put #-}+ put = id++instance Put ByteString where+ {-# INLINE put #-}+ put = W.byteString++instance Put Word8 where+ {-# INLINE put #-}+ put = W.w8++instance Put Word16 where+ {-# INLINE put #-}+ put = W.w16++instance Put Word32 where+ {-# INLINE put #-}+ put = W.w32++instance Put Word64 where+ {-# INLINE put #-}+ put = W.w64++instance Put Int8 where+ {-# INLINE put #-}+ put = W.i8++instance Put Int16 where+ {-# INLINE put #-}+ put = W.i16++instance Put Int32 where+ {-# INLINE put #-}+ put = W.i32++instance Put Int64 where+ {-# INLINE put #-}+ put = W.i64
+ src/Bytezap/Int.hs view
@@ -0,0 +1,158 @@+-- | Sized machine integers.++{-# LANGUAGE UnboxedTuples #-}+{-# LANGUAGE CPP #-}++module Bytezap.Int where++import Bytezap+--import Bytezap.Prim.Integer qualified as Prim+import GHC.Exts+import Data.Word+import GHC.Word+import Data.Int+import GHC.Int++w8 :: Word8 -> Write+w8 (W8# a#) = write 1 $ \addr# st# ->+ case writeWord8OffAddr# addr# 0# a# st# of+ st'# -> (# st'#, addr# `plusAddr#` 1# #)+{-# INLINE w8 #-}++w16 :: Word16 -> Write+w16 (W16# a#) = write 2 $ \addr# st# ->+ case writeWord16OffAddr# addr# 0# a# st# of+ st'# -> (# st'#, addr# `plusAddr#` 2# #)+{-# INLINE w16 #-}++w32 :: Word32 -> Write+w32 (W32# a#) = write 4 $ \addr# st# ->+ case writeWord32OffAddr# addr# 0# a# st# of+ st'# -> (# st'#, addr# `plusAddr#` 4# #)+{-# INLINE w32 #-}++w64 :: Word64 -> Write+w64 (W64# a#) = write 8 $ \addr# st# ->+ case writeWord64OffAddr# addr# 0# a# st# of+ st'# -> (# st'#, addr# `plusAddr#` 8# #)+{-# INLINE w64 #-}++{-# INLINE w16le #-}+{-# INLINE w16be #-}+w16le, w16be :: Word16 -> Write+#ifdef WORDS_BIGENDIAN+w16le = w16 . byteSwap16+w16be = w16+#else+w16le = w16+w16be = w16 . byteSwap16+#endif++{-# INLINE w32le #-}+{-# INLINE w32be #-}+w32le, w32be :: Word32 -> Write+#ifdef WORDS_BIGENDIAN+w32le = w32 . byteSwap32+w32be = w32+#else+w32le = w32+w32be = w32 . byteSwap32+#endif++{-# INLINE w64le #-}+{-# INLINE w64be #-}+w64le, w64be :: Word64 -> Write+#ifdef WORDS_BIGENDIAN+w64le = w64 . byteSwap64+w64be = w64+#else+w64le = w64+w64be = w64 . byteSwap64+#endif++i8 :: Int8 -> Write+i8 (I8# a#) = write 1 $ \addr# st# ->+ case writeInt8OffAddr# addr# 0# a# st# of+ st'# -> (# st'#, addr# `plusAddr#` 1# #)+{-# INLINE i8 #-}++i16 :: Int16 -> Write+i16 (I16# a#) = write 2 $ \addr# st# ->+ case writeInt16OffAddr# addr# 0# a# st# of+ st'# -> (# st'#, addr# `plusAddr#` 2# #)+{-# INLINE i16 #-}++i32 :: Int32 -> Write+i32 (I32# a#) = write 4 $ \addr# st# ->+ case writeInt32OffAddr# addr# 0# a# st# of+ st'# -> (# st'#, addr# `plusAddr#` 4# #)+{-# INLINE i32 #-}++i64 :: Int64 -> Write+i64 (I64# a#) = write 8 $ \addr# st# ->+ case writeInt64OffAddr# addr# 0# a# st# of+ st'# -> (# st'#, addr# `plusAddr#` 8# #)+{-# INLINE i64 #-}++byteSwapI16 :: Int16 -> Int16+byteSwapI16 = undefined++byteSwapI32 :: Int32 -> Int32+byteSwapI32 = undefined++byteSwapI64 :: Int64 -> Int64+byteSwapI64 = undefined++{-# INLINE i16le #-}+{-# INLINE i16be #-}+i16le, i16be :: Int16 -> Write+#ifdef WORDS_BIGENDIAN+i16le = i16 . byteSwapI16+i16be = i16+#else+i16le = i16+i16be = i16 . byteSwapI16+#endif++{-# INLINE i32le #-}+{-# INLINE i32be #-}+i32le, i32be :: Int32 -> Write+#ifdef WORDS_BIGENDIAN+i32le = i32 . byteSwapI32+i32be = i32+#else+i32le = i32+i32be = i32 . byteSwapI32+#endif++{-# INLINE i64le #-}+{-# INLINE i64be #-}+i64le, i64be :: Int64 -> Write+#ifdef WORDS_BIGENDIAN+i64le = i64 . byteSwapI64+i64be = i64+#else+i64le = i64+i64be = i64 . byteSwapI64+#endif++-- TODO assumes 64-bit+int# :: Int# -> Write+int# a# = write 8 $ \addr# st# ->+ case writeIntOffAddr# addr# 0# a# st# of+ st'# -> (# st'#, addr# `plusAddr#` 8# #)+{-# INLINE int# #-}++{-++-- | Construct a 'Write' of the following length using the given primitive poke.+writeViaPrim+ :: Int#+ -> (forall s. Addr# -> Int# -> a -> State# s -> State# s)+ -> a -> Write+writeViaPrim len# writeOffPrim a = write (I# len#) $ \addr# os# st# ->+ case writeOffPrim addr# os# a st# of+ st'# -> (# st'#, os# +# len# #)+{-# INLINE writeViaPrim #-}++-}
+ src/Bytezap/Poke/Bytes.hs view
@@ -0,0 +1,33 @@+{-# LANGUAGE UnboxedTuples #-}++module Bytezap.Poke.Bytes where++import Bytezap++import GHC.Exts+import Data.ByteString qualified as B+import Data.ByteString.Internal qualified as B+import GHC.IO+import Data.Word+import Foreign.ForeignPtr++byteString :: B.ByteString -> Poke+byteString (B.BS fptr len) = pokeForeignPtr fptr len+{-# INLINE byteString #-}++pokeForeignPtr :: ForeignPtr Word8 -> Int -> Poke+pokeForeignPtr fptr len@(I# len#) = poke $ \addr# st# ->+ case unIO (memcpyForeignPtr (Ptr addr#) fptr len) st# of+ (# st'#, () #) -> (# st'#, addr# `plusAddr#` len# #)+{-# INLINE pokeForeignPtr #-}++memcpyForeignPtr :: Ptr Word8 -> ForeignPtr Word8 -> Int -> IO ()+memcpyForeignPtr ptrTo fptrFrom len =+ B.unsafeWithForeignPtr fptrFrom $ \ptrFrom -> B.memcpy ptrTo ptrFrom len+{-# INLINE memcpyForeignPtr #-}++pokeByteArray# :: ByteArray# -> Int# -> Int# -> Poke+pokeByteArray# arr# off# len# = poke $ \addr# st# ->+ case copyByteArrayToAddr# arr# off# addr# len# st# of+ st'# -> (# st'#, addr# `plusAddr#` len# #)+{-# INLINE pokeByteArray# #-}
+ src/Bytezap/Poke/Int.hs view
@@ -0,0 +1,141 @@+{-# LANGUAGE UnboxedTuples #-}+{-# LANGUAGE CPP #-}++module Bytezap.Poke.Int where++import Bytezap+import GHC.Exts+import Data.Word+import GHC.Word+import Data.Int+import GHC.Int++w8 :: Word8 -> Poke+w8 (W8# a#) = Poke $ \addr# st# ->+ case writeWord8OffAddr# addr# 0# a# st# of+ st'# -> (# st'#, addr# `plusAddr#` 1# #)+{-# INLINE w8 #-}++w16 :: Word16 -> Poke+w16 (W16# a#) = Poke $ \addr# st# ->+ case writeWord16OffAddr# addr# 0# a# st# of+ st'# -> (# st'#, addr# `plusAddr#` 2# #)+{-# INLINE w16 #-}++w32 :: Word32 -> Poke+w32 (W32# a#) = Poke $ \addr# st# ->+ case writeWord32OffAddr# addr# 0# a# st# of+ st'# -> (# st'#, addr# `plusAddr#` 4# #)+{-# INLINE w32 #-}++w64 :: Word64 -> Poke+w64 (W64# a#) = Poke $ \addr# st# ->+ case writeWord64OffAddr# addr# 0# a# st# of+ st'# -> (# st'#, addr# `plusAddr#` 8# #)+{-# INLINE w64 #-}++{-# INLINE w16le #-}+{-# INLINE w16be #-}+w16le, w16be :: Word16 -> Poke+#ifdef WORDS_BIGENDIAN+w16le = w16 . byteSwap16+w16be = w16+#else+w16le = w16+w16be = w16 . byteSwap16+#endif++{-# INLINE w32le #-}+{-# INLINE w32be #-}+w32le, w32be :: Word32 -> Poke+#ifdef WORDS_BIGENDIAN+w32le = w32 . byteSwap32+w32be = w32+#else+w32le = w32+w32be = w32 . byteSwap32+#endif++{-# INLINE w64le #-}+{-# INLINE w64be #-}+w64le, w64be :: Word64 -> Poke+#ifdef WORDS_BIGENDIAN+w64le = w64 . byteSwap64+w64be = w64+#else+w64le = w64+w64be = w64 . byteSwap64+#endif++i8 :: Int8 -> Poke+i8 (I8# a#) = Poke $ \addr# st# ->+ case writeInt8OffAddr# addr# 0# a# st# of+ st'# -> (# st'#, addr# `plusAddr#` 1# #)+{-# INLINE i8 #-}++i16 :: Int16 -> Poke+i16 (I16# a#) = Poke $ \addr# st# ->+ case writeInt16OffAddr# addr# 0# a# st# of+ st'# -> (# st'#, addr# `plusAddr#` 2# #)+{-# INLINE i16 #-}++i32 :: Int32 -> Poke+i32 (I32# a#) = Poke $ \addr# st# ->+ case writeInt32OffAddr# addr# 0# a# st# of+ st'# -> (# st'#, addr# `plusAddr#` 4# #)+{-# INLINE i32 #-}++i64 :: Int64 -> Poke+i64 (I64# a#) = Poke $ \addr# st# ->+ case writeInt64OffAddr# addr# 0# a# st# of+ st'# -> (# st'#, addr# `plusAddr#` 8# #)+{-# INLINE i64 #-}++byteSwapI16 :: Int16 -> Int16+byteSwapI16 = undefined++byteSwapI32 :: Int32 -> Int32+byteSwapI32 = undefined++byteSwapI64 :: Int64 -> Int64+byteSwapI64 = undefined++{-# INLINE i16le #-}+{-# INLINE i16be #-}+i16le, i16be :: Int16 -> Poke+#ifdef WORDS_BIGENDIAN+i16le = i16 . byteSwapI16+i16be = i16+#else+i16le = i16+i16be = i16 . byteSwapI16+#endif++{-# INLINE i32le #-}+{-# INLINE i32be #-}+i32le, i32be :: Int32 -> Poke+#ifdef WORDS_BIGENDIAN+i32le = i32 . byteSwapI32+i32be = i32+#else+i32le = i32+i32be = i32 . byteSwapI32+#endif++{-# INLINE i64le #-}+{-# INLINE i64be #-}+i64le, i64be :: Int64 -> Poke+#ifdef WORDS_BIGENDIAN+i64le = i64 . byteSwapI64+i64be = i64+#else+i64le = i64+i64be = i64 . byteSwapI64+#endif++-- TODO assumes 64-bit+int# :: Int# -> Poke+int# a# = Poke $ \addr# st# ->+ case writeIntOffAddr# addr# 0# a# st# of+ st'# -> (# st'#, addr# `plusAddr#` 8# #)+{-# INLINE int# #-}
+ src/Bytezap/Text.hs view
@@ -0,0 +1,58 @@+{-# LANGUAGE UnboxedTuples #-}+{-# LANGUAGE CPP #-}++module Bytezap.Text where++import Bytezap+import Bytezap.Int++import Data.Text.Internal++-- unused import warnings due to messy CPP+import Bytezap.Bytes+import Data.Text.Array qualified as A+import GHC.Exts++import Data.Char ( ord )+import Data.Foldable ( foldl' )+import Data.Bits ( shiftR, (.&.) )++textUtf8 :: Text -> Write+{-# INLINE textUtf8 #-}+#if MIN_VERSION_text(2,0,0)+textUtf8 (Text (A.ByteArray arr#) (I# off#) len@(I# len#)) =+ Write len $ pokeByteArray# arr# off# len#+#else+textUtf8 = error "Bytezap.Text.textUtf8: cba for text-1"+#endif++-- TODO adapted from utf8-string+charUtf8 :: Char -> Write+charUtf8 = go . ord+ where+ go oc+ | oc <= 0x7f = w8 $ fromIntegral oc++ | oc <= 0x7ff = w8 (fromIntegral (0xc0 + (oc `shiftR` 6)))+ <> w8 (fromIntegral (0x80 + oc .&. 0x3f))++ | oc <= 0xffff = w8 (fromIntegral (0xe0 + (oc `shiftR` 12)))+ <> w8 (fromIntegral (0x80 + ((oc `shiftR` 6) .&. 0x3f)))+ <> w8 (fromIntegral (0x80 + oc .&. 0x3f))+ | otherwise = w8 (fromIntegral (0xf0 + (oc `shiftR` 18)))+ <> w8 (fromIntegral (0x80 + ((oc `shiftR` 12) .&. 0x3f)))+ <> w8 (fromIntegral (0x80 + ((oc `shiftR` 6) .&. 0x3f)))+ <> w8 (fromIntegral (0x80 + oc .&. 0x3f))+{-# INLINE charUtf8 #-}++-- | TODO+--+-- In a perfect world, functions like this would not exist. But this is not a+-- perfect world. 'String's 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 'String's. 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+stringUtf8 = foldl' (\w c -> w <> charUtf8 c) mempty+{-# INLINE stringUtf8 #-}
src/Data/Aeson/Extra/SizedVector.hs view
@@ -1,6 +1,6 @@ {-# OPTIONS_GHC -fno-warn-orphans #-} -module Data.Aeson.Extra.SizedVector where+module Data.Aeson.Extra.SizedVector() where import Data.Aeson import Data.Vector.Generic.Sized.Internal qualified as VSI@@ -16,4 +16,4 @@ v <- parseJSON j case VS.toSized v of Nothing -> fail "TODO bad size"- Just v' -> return v'+ Just v' -> pure v'
− src/Haskpatch/Format/Bps.hs
@@ -1,46 +0,0 @@-module Haskpatch.Format.Bps where--import Binrep.Type.Magic-import Binrep.Type.Sized-import Binrep.Type.Varint-import Binrep.Type.Common-import Strongweak--import Data.ByteString qualified as B---- | TODO--- * can't do generic because BPS doesn't store command list length, instead--- requiring a dynamic check on every command--- * wonder if this is better or more efficient that using a 'BpsVarint' for--- the length, same as metadata, or storing the end size as a 'BpsVarint'.--- * maybe two diff types of varint, +ve and -ve. unclear from spec--- * perhaps store the varint type(s) as a type var, to allow switching--- between efficient machine ints and safe 'Integer', 'Natural'!-data Bps (s :: Strength) i a = Bps- { bpsMagic :: SW s (Magic "BPS1")- , bpsSourceSize :: SW s (BpsVarint i)- , bpsTargetSize :: SW s (BpsVarint i)-- , bpsMetadata :: BpsMeta a- -- ^ Optional metadata. According to the specification, this should- -- "officially" be XML version 1.0 encoding UTF-8 data, but anything goes.-- , bpsCommands :: [BpsCommand]- , bpsFooter :: BpsFooter s- }--type BpsVarint = Varnat 'Bijective 'OffContinues 'LE--data BpsMeta a--data BpsCommand- = BpsCommandSourceRead- | BpsCommandTargetRead- | BpsCommandSourceCopy- | BpsCommandTargetCopy--data BpsFooter (s :: Strength) = BpsFooter- { bpsFooterSourceChecksum :: SW s (Sized 4 B.ByteString)- , bpsFooterTargetChecksum :: SW s (Sized 4 B.ByteString)- , bpsFooterPatchChecksum :: SW s (Sized 4 B.ByteString)- }
− src/Haskpatch/Format/Vcdiff.hs
@@ -1,57 +0,0 @@--- | https://datatracker.ietf.org/doc/html/rfc3284--module Haskpatch.Format.Vcdiff where--import Binrep.Type.Magic-import Binrep.Type.Varint-import Binrep.Type.Common-import Strongweak--import Numeric.Natural-import Data.ByteString ( ByteString )-import Data.Word ( Word8 )--data Vcdiff (s :: Strength) = Vcdiff- { vcdiffHeader :: Header s- }--data Header (s :: Strength) = Header- { headerMagic :: SW s (Magic '[0xD6, 0xC3, 0xC4, 0x00])- -- ^ First 3 bytes are @VCD@ each with their MSB on.-- , headerIndicator :: SW s (Magic '[0x00])- -- ^ TODO annoying and impacts rest of format. forcing to 0x00 to simplify- }--data Window (s :: Strength) = Window- { windowIndicator :: SW s (Magic '[0x00]) -- TODO- , windowDelta :: Delta s- }--data Delta (s :: Strength) = Delta- { deltaIndicator :: SW s (Magic '[0x00]) -- TODO compression indicators. ignoring- , deltaAddRun :: ByteString- , deltaInstrs :: [InstrCode]- , deltaCopy :: ByteString- }--data InstrCode = InstrCode- { instrCodeTriple1 :: InstrTriple- , instrCodeTriple2 :: InstrTriple- }--data InstrTriple = InstrTriple- { instrTripleInstr :: Instr-- , instrTripleSize :: Word8-- , instrTripleMode :: Word8- -- ^ 0 and meaningless unless instr is a COPY- }---- TODO singletons it-data Instr = Instr0Noop | Instr1Add | Instr2Run | Instr3Copy---- | Apparently from the Sfio library, also similar (but not identical) to BPS's--- varints.-type VcdiffVarint = Varnat 'Redundant 'OnContinues 'BE Natural
− src/Util/Generic.hs
@@ -1,29 +0,0 @@-{-# LANGUAGE AllowAmbiguousTypes #-}--module Util.Generic where--import GHC.Generics---- | 'datatypeName' without the value (only used as a proxy). Lets us push our--- 'undefined's into one place.-datatypeName' :: forall d. Datatype d => String-datatypeName' = datatypeName @d undefined---- | 'conName' without the value (only used as a proxy). Lets us push our--- 'undefined's into one place.-conName' :: forall c. Constructor c => String-conName' = conName @c undefined---- | 'selName' without the value (only used as a proxy). Lets us push our--- 'undefined's into one place.-selName' :: forall s. Selector s => String-selName' = selName @s undefined---- | Get the record name for a selector if present.------ On the type level, a 'Maybe Symbol' is stored for record names. But the--- reification is done using @fromMaybe ""@. So we have to inspect the resulting--- string to determine whether the field uses record syntax or not. (Silly.)-selName'' :: forall s. Selector s => Maybe String-selName'' = case selName' @s of "" -> Nothing- s -> Just s
+ src/Util/TypeNats.hs view
@@ -0,0 +1,18 @@+{-# LANGUAGE AllowAmbiguousTypes #-}++-- | Handy typenat utils.++module Util.TypeNats where++-- natVal''+import GHC.TypeNats ( Natural, KnownNat, natVal' )+import GHC.Exts ( proxy#, Proxy# )++natVal'' :: forall n. KnownNat n => Natural+natVal'' = natVal' (proxy# :: Proxy# n)+{-# INLINE natVal'' #-}++natValInt :: forall n. KnownNat n => Int+natValInt = fromIntegral $ natVal'' @n+{-# INLINE natValInt #-}+
test/ArbitraryOrphans.hs view
@@ -1,10 +1,11 @@ {-# OPTIONS_GHC -fno-warn-orphans #-}-{-# LANGUAGE UndecidableInstances #-} module ArbitraryOrphans() where import Test.QuickCheck ( Arbitrary )-import Binrep.Type.Int ( I(..), IRep )+import Binrep.Type.Int+import Data.Kind --- | Machine integers steal their underlying representation's instance.-deriving via (IRep sign size) instance Arbitrary (IRep sign size) => Arbitrary (I sign size e)+-- TODO 2023-01-26 raehik: why does the following crash GHC+deriving via (a :: Type) instance Arbitrary a => Arbitrary (Endian end a)+--deriving newtype instance Arbitrary a => Arbitrary (Endian end a)
test/Binrep/LawsSpec.hs view
@@ -10,15 +10,16 @@ import ArbitraryOrphans() import Binrep-import Binrep.Generic+import Binrep.Generic ( nullTermCstrPfxTag )+import Binrep.BLen.Simple ( blenGenericNonSum, blenGenericSum ) import Binrep.Type.Int import Binrep.Type.Common ( Endianness(..) )-import Binrep.Type.ByteString-import Data.Word ( Word8 )+import Binrep.Type.NullTerminated+import Data.Word import Data.ByteString qualified as B import GHC.Generics ( Generic ) -import Control.Exception ( evaluate )+import Generic.Data.Function.Traverse spec :: Spec spec = do@@ -28,21 +29,12 @@ \(bs :: B.ByteString) -> runGet (runPut bs) `shouldBe` Right (bs, "") prop "parse-print roundtrip isomorphism (generic, sum tag via nullterm constructor)" $ do \(d :: D) -> runGet (runPut d) `shouldBe` Right (d, "")- prop "serializing a type with an incorrect generic derivation throws an exception" $ do- \(d :: DNoSum) -> do- let evaluateShouldThrow a = evaluate a `shouldThrow` (\case EDerivedSumInstanceWithNonSumCfg -> True)- evaluateShouldThrow (blen d)- evaluateShouldThrow (runPut d)- prop "parsing a type with an incorrect generic derivation fails" $ do- \(bs :: B.ByteString) -> do- let e = EGeneric "DNoSum" $ EGenericSum $ EGenericSumTag $ EBase ENoVoid- runGet @DNoSum bs `shouldBe` Left e -------------------------------------------------------------------------------- -type W1 = (I 'U 'I1 'LE)-type W2LE = (I 'U 'I2 'LE)-type W8BE = (I 'U 'I8 'BE)+type W1 = Word8+type W2LE = Endian 'LE Word16+type W8BE = Endian 'BE Word64 data D = D01Bla Word8 W1 W8BE@@ -52,18 +44,14 @@ deriving stock (Generic, Eq, Show) deriving via (GenericArbitraryU `AndShrinking` D) instance Arbitrary D -dCfg :: Cfg (AsByteString 'C)-dCfg = cfg cSumTagNullTerm--instance BLen D where blen = blenGeneric dCfg-instance Put D where put = putGeneric dCfg-instance Get D where get = getGeneric dCfg+instance BLen D where blen = blenGenericSum $ blen . nullTermCstrPfxTag+instance Put D where put = putGenericSum $ put . nullTermCstrPfxTag+instance Get D where get = getGenericSum $ eqShowPfxTagCfg nullTermCstrPfxTag data DNoSum = DNoSum Word8 W1 W2LE W8BE- | DNoSumBad deriving stock (Generic, Eq, Show) deriving via (GenericArbitraryU `AndShrinking` DNoSum) instance Arbitrary DNoSum -instance BLen DNoSum where blen = blenGeneric cNoSum-instance Put DNoSum where put = putGeneric cNoSum-instance Get DNoSum where get = getGeneric cNoSum+instance BLen DNoSum where blen = blenGenericNonSum+instance Put DNoSum where put = putGenericNonSum+instance Get DNoSum where get = getGenericNonSum