dahdit 0.3.0 → 0.5.0
raw patch · 21 files changed
+1115/−922 lines, 21 filesdep +falsifydep +ghc-typelits-knownnatdep +textdep ~tastydep ~tasty-hunitdep ~vectorPVP ok
version bump matches the API change (PVP)
Dependencies added: falsify, ghc-typelits-knownnat, text
Dependency ranges changed: tasty, tasty-hunit, vector
API changes (from Hackage documentation)
- Dahdit: GetErrorParseNeed :: !String -> !ByteCount -> !ByteCount -> GetError
- Dahdit.BinaryRep: instance (Dahdit.Sizes.ByteSized x, Dahdit.BinaryRep.BinaryRep x a) => Dahdit.Sizes.ByteSized (Dahdit.BinaryRep.ViaBinaryRep a)
- Dahdit.BinaryRep: instance (Dahdit.Sizes.StaticByteSized x, Dahdit.BinaryRep.BinaryRep x a) => Dahdit.Sizes.StaticByteSized (Dahdit.BinaryRep.ViaBinaryRep a)
- Dahdit.BinaryRep: instance Dahdit.BinaryRep.BinaryRep x a => Dahdit.Binary.Binary (Dahdit.BinaryRep.ViaBinaryRep a)
- Dahdit.Codec: ViaBinary :: a -> ViaBinary a
- Dahdit.Codec: ViaCodec :: a -> ViaCodec a
- Dahdit.Codec: [unViaBinary] :: ViaBinary a -> a
- Dahdit.Codec: [unViaCodec] :: ViaCodec a -> a
- Dahdit.Codec: binary :: Binary a => Codec a
- Dahdit.Codec: bindPair :: Codec a -> (a -> Codec b) -> Codec (a, b)
- Dahdit.Codec: bindTag :: (b -> a) -> Codec a -> (a -> Codec b) -> Codec b
- Dahdit.Codec: build :: Get a -> (a -> Put) -> Codec a
- Dahdit.Codec: class HasCodec a
- Dahdit.Codec: codec :: HasCodec a => Codec a
- Dahdit.Codec: instance (GHC.TypeNats.KnownNat n, Dahdit.Binary.Binary a, Dahdit.Sizes.StaticByteSized a, Data.Default.Class.Default a) => Dahdit.Codec.HasCodec (Dahdit.Fancy.StaticSeq n a)
- Dahdit.Codec: instance (GHC.TypeNats.KnownNat n, Dahdit.LiftedPrim.LiftedPrim a, Data.Default.Class.Default a) => Dahdit.Codec.HasCodec (Dahdit.Fancy.StaticArray n a)
- Dahdit.Codec: instance Dahdit.Binary.Binary a => Dahdit.Codec.HasCodec (Dahdit.Codec.ViaBinary a)
- Dahdit.Codec: instance Dahdit.Codec.HasCodec Dahdit.Fancy.BoolByte
- Dahdit.Codec: instance Dahdit.Codec.HasCodec Dahdit.Fancy.TermBytes
- Dahdit.Codec: instance Dahdit.Codec.HasCodec Dahdit.Nums.FloatBE
- Dahdit.Codec: instance Dahdit.Codec.HasCodec Dahdit.Nums.FloatLE
- Dahdit.Codec: instance Dahdit.Codec.HasCodec Dahdit.Nums.Int16BE
- Dahdit.Codec: instance Dahdit.Codec.HasCodec Dahdit.Nums.Int16LE
- Dahdit.Codec: instance Dahdit.Codec.HasCodec Dahdit.Nums.Int24BE
- Dahdit.Codec: instance Dahdit.Codec.HasCodec Dahdit.Nums.Int24LE
- Dahdit.Codec: instance Dahdit.Codec.HasCodec Dahdit.Nums.Int32BE
- Dahdit.Codec: instance Dahdit.Codec.HasCodec Dahdit.Nums.Int32LE
- Dahdit.Codec: instance Dahdit.Codec.HasCodec Dahdit.Nums.Word16BE
- Dahdit.Codec: instance Dahdit.Codec.HasCodec Dahdit.Nums.Word16LE
- Dahdit.Codec: instance Dahdit.Codec.HasCodec Dahdit.Nums.Word24BE
- Dahdit.Codec: instance Dahdit.Codec.HasCodec Dahdit.Nums.Word24LE
- Dahdit.Codec: instance Dahdit.Codec.HasCodec Dahdit.Nums.Word32BE
- Dahdit.Codec: instance Dahdit.Codec.HasCodec Dahdit.Nums.Word32LE
- Dahdit.Codec: instance Dahdit.Codec.HasCodec GHC.Int.Int8
- Dahdit.Codec: instance Dahdit.Codec.HasCodec GHC.Word.Word8
- Dahdit.Codec: instance Dahdit.Codec.HasCodec a => Dahdit.Binary.Binary (Dahdit.Codec.ViaCodec a)
- Dahdit.Codec: instance Dahdit.Sizes.ByteSized a => Dahdit.Sizes.ByteSized (Dahdit.Codec.ViaCodec a)
- Dahdit.Codec: instance GHC.Base.Applicative (Dahdit.Codec.Codec' x)
- Dahdit.Codec: instance GHC.Base.Functor (Dahdit.Codec.Codec' x)
- Dahdit.Codec: instance GHC.TypeLits.KnownSymbol s => Dahdit.Codec.HasCodec (Dahdit.Fancy.ExactBytes s)
- Dahdit.Codec: newtype ViaBinary a
- Dahdit.Codec: newtype ViaCodec a
- Dahdit.Codec: parse :: Codec a -> Get a
- Dahdit.Codec: produce :: Codec a -> a -> Put
- Dahdit.Codec: type Codec a = Codec' a a
- Dahdit.Fancy: TermBytes :: ShortByteString -> TermBytes
- Dahdit.Fancy: [unTermBytes] :: TermBytes -> ShortByteString
- Dahdit.Fancy: instance (GHC.TypeNats.KnownNat n, Dahdit.Sizes.StaticByteSized a) => Dahdit.Sizes.ByteSized (Dahdit.Fancy.StaticArray n a)
- Dahdit.Fancy: instance (GHC.TypeNats.KnownNat n, Dahdit.Sizes.StaticByteSized a) => Dahdit.Sizes.ByteSized (Dahdit.Fancy.StaticSeq n a)
- Dahdit.Fancy: instance Dahdit.Binary.Binary Dahdit.Fancy.TermBytes
- Dahdit.Fancy: instance Dahdit.Sizes.ByteSized Dahdit.Fancy.BoolByte
- Dahdit.Fancy: instance Dahdit.Sizes.ByteSized Dahdit.Fancy.TermBytes
- Dahdit.Fancy: instance Data.Default.Class.Default (Dahdit.Fancy.ExactBytes s)
- Dahdit.Fancy: instance Data.Default.Class.Default Dahdit.Fancy.TermBytes
- Dahdit.Fancy: instance Data.String.IsString Dahdit.Fancy.TermBytes
- Dahdit.Fancy: instance GHC.Classes.Eq (Dahdit.Fancy.ExactBytes s)
- Dahdit.Fancy: instance GHC.Classes.Eq Dahdit.Fancy.TermBytes
- Dahdit.Fancy: instance GHC.Classes.Ord Dahdit.Fancy.TermBytes
- Dahdit.Fancy: instance GHC.Show.Show (Dahdit.Fancy.ExactBytes s)
- Dahdit.Fancy: instance GHC.Show.Show Dahdit.Fancy.TermBytes
- Dahdit.Fancy: instance GHC.TypeLits.KnownSymbol s => Dahdit.Binary.Binary (Dahdit.Fancy.ExactBytes s)
- Dahdit.Fancy: instance GHC.TypeLits.KnownSymbol s => Dahdit.Sizes.ByteSized (Dahdit.Fancy.ExactBytes s)
- Dahdit.Fancy: instance GHC.TypeLits.KnownSymbol s => Dahdit.Sizes.StaticByteSized (Dahdit.Fancy.ExactBytes s)
- Dahdit.Fancy: instance GHC.TypeNats.KnownNat n => Dahdit.Sizes.ByteSized (Dahdit.Fancy.StaticBytes n)
- Dahdit.Fancy: newtype TermBytes
- Dahdit.Generic: instance (Dahdit.Generic.GByteSized a, Dahdit.Generic.GByteSized b) => Dahdit.Generic.GByteSized (a GHC.Generics.:*: b)
- Dahdit.Generic: instance (GHC.Generics.Generic t, Dahdit.Generic.GBinary (GHC.Generics.Rep t)) => Dahdit.Binary.Binary (Dahdit.Generic.ViaGeneric t)
- Dahdit.Generic: instance (GHC.Generics.Generic t, Dahdit.Generic.GByteSized (GHC.Generics.Rep t)) => Dahdit.Sizes.ByteSized (Dahdit.Generic.ViaGeneric t)
- Dahdit.Generic: instance (GHC.Generics.Generic t, Dahdit.Generic.GByteSized (GHC.Generics.Rep t)) => Dahdit.Sizes.ByteSized (Dahdit.Generic.ViaStaticGeneric t)
- Dahdit.Generic: instance (GHC.Generics.Generic t, Dahdit.Generic.GStaticByteSized (GHC.Generics.Rep t)) => Dahdit.Sizes.StaticByteSized (Dahdit.Generic.ViaStaticGeneric t)
- Dahdit.Generic: instance Dahdit.Sizes.ByteSized a => Dahdit.Generic.GByteSized (GHC.Generics.K1 i a)
- Dahdit.Iface: class BinaryTarget z
- Dahdit.Iface: class MutBinaryTarget m z
- Dahdit.Iface: instance (Control.Monad.Primitive.PrimBase m, s GHC.Types.~ Control.Monad.Primitive.PrimState m) => Dahdit.Iface.MutBinaryTarget m (Data.Array.Byte.MutableByteArray s)
- Dahdit.Iface: instance (Control.Monad.Primitive.PrimBase m, s GHC.Types.~ Control.Monad.Primitive.PrimState m) => Dahdit.Iface.MutBinaryTarget m (Data.Vector.Storable.Mutable.MVector s GHC.Word.Word8)
- Dahdit.Iface: instance Dahdit.Iface.BinaryTarget (Data.Vector.Storable.Vector GHC.Word.Word8)
- Dahdit.Iface: instance Dahdit.Iface.BinaryTarget Data.Array.Byte.ByteArray
- Dahdit.Iface: instance Dahdit.Iface.BinaryTarget Data.ByteString.Internal.ByteString
- Dahdit.Iface: instance Dahdit.Iface.BinaryTarget Data.ByteString.Short.Internal.ShortByteString
- Dahdit.Internal: instance (Dahdit.Internal.SwapEndian x, GHC.Real.Integral x, GHC.Real.Integral y) => Dahdit.Internal.SwapEndian (Dahdit.Internal.ViaFromIntegral x y)
- Dahdit.Internal: instance Dahdit.Internal.EndianPair GHC.Int.Int8 GHC.Int.Int8
- Dahdit.Internal: instance Dahdit.Internal.EndianPair GHC.Word.Word8 GHC.Word.Word8
- Dahdit.Internal: instance GHC.Num.Num y => GHC.Num.Num (Dahdit.Internal.ViaFromIntegral x y)
- Dahdit.LiftedPrim: instance (Dahdit.LiftedPrim.LiftedPrim le, Dahdit.Internal.EndianPair le be) => Dahdit.LiftedPrim.LiftedPrim (Dahdit.Internal.ViaEndianPair le be)
- Dahdit.LiftedPrim: instance (GHC.Real.Integral x, Dahdit.LiftedPrim.LiftedPrim x, GHC.Real.Integral y) => Dahdit.LiftedPrim.LiftedPrim (Dahdit.Internal.ViaFromIntegral x y)
- Dahdit.LiftedPrimArray: instance Dahdit.Sizes.ByteSized (Dahdit.LiftedPrimArray.LiftedPrimArray a)
- Dahdit.Mem: IxPtr :: Ptr Word8 -> IxPtr s
- Dahdit.Mem: [unIxPtr] :: IxPtr s -> Ptr Word8
- Dahdit.Mem: allocBAMem :: PrimMonad m => ByteCount -> ByteCount -> m (MutableByteArray (PrimState m), Maybe (IO ()))
- Dahdit.Mem: allocPtrMem :: PrimMonad m => ByteCount -> ByteCount -> m (IxPtr (PrimState m), Maybe (IO ()))
- Dahdit.Mem: freezeBAMem :: PrimMonad m => MutableByteArray (PrimState m) -> ByteCount -> ByteCount -> m ByteArray
- Dahdit.Mem: freezeBSMem :: PrimMonad m => IxPtr (PrimState m) -> ByteCount -> ByteCount -> m ByteString
- Dahdit.Mem: freezeSBSMem :: PrimMonad m => MutableByteArray (PrimState m) -> ByteCount -> ByteCount -> m ShortByteString
- Dahdit.Mem: freezeVecMem :: PrimMonad m => IxPtr (PrimState m) -> ByteCount -> ByteCount -> m (Vector Word8)
- Dahdit.Mem: instance Control.Monad.Primitive.PrimMonad m => Dahdit.Mem.WriteMem Dahdit.Mem.IxPtr m
- Dahdit.Mem: instance Dahdit.Mem.ReadMem (GHC.Ptr.Ptr GHC.Word.Word8)
- Dahdit.Mem: instance Dahdit.Mem.ReadMem Data.Array.Byte.ByteArray
- Dahdit.Mem: instance GHC.Classes.Eq (Dahdit.Mem.IxPtr s)
- Dahdit.Mem: instance GHC.Classes.Ord (Dahdit.Mem.IxPtr s)
- Dahdit.Mem: instance GHC.Show.Show (Dahdit.Mem.IxPtr s)
- Dahdit.Mem: mutAllocBAMem :: PrimMonad m => MutableByteArray (PrimState m) -> ByteCount -> ByteCount -> m (MutableByteArray (PrimState m), Maybe (IO ()))
- Dahdit.Mem: mutAllocVecMem :: PrimMonad m => MVector (PrimState m) Word8 -> ByteCount -> ByteCount -> m (IxPtr (PrimState m), Maybe (IO ()))
- Dahdit.Mem: mutFreezeBAMem :: PrimMonad m => MutableByteArray (PrimState m) -> ByteCount -> ByteCount -> m ByteCount
- Dahdit.Mem: mutFreezeVecMem :: PrimMonad m => IxPtr (PrimState m) -> ByteCount -> ByteCount -> m ByteCount
- Dahdit.Mem: newtype IxPtr s
- Dahdit.Nums: instance Dahdit.Internal.EndianPair Dahdit.Nums.DoubleLE Dahdit.Nums.DoubleBE
- Dahdit.Nums: instance Dahdit.Internal.EndianPair Dahdit.Nums.FloatLE Dahdit.Nums.FloatBE
- Dahdit.Nums: instance Dahdit.Internal.EndianPair Dahdit.Nums.Int16LE Dahdit.Nums.Int16BE
- Dahdit.Nums: instance Dahdit.Internal.EndianPair Dahdit.Nums.Int24LE Dahdit.Nums.Int24BE
- Dahdit.Nums: instance Dahdit.Internal.EndianPair Dahdit.Nums.Int32LE Dahdit.Nums.Int32BE
- Dahdit.Nums: instance Dahdit.Internal.EndianPair Dahdit.Nums.Int64LE Dahdit.Nums.Int64BE
- Dahdit.Nums: instance Dahdit.Internal.EndianPair Dahdit.Nums.Word16LE Dahdit.Nums.Word16BE
- Dahdit.Nums: instance Dahdit.Internal.EndianPair Dahdit.Nums.Word24LE Dahdit.Nums.Word24BE
- Dahdit.Nums: instance Dahdit.Internal.EndianPair Dahdit.Nums.Word32LE Dahdit.Nums.Word32BE
- Dahdit.Nums: instance Dahdit.Internal.EndianPair Dahdit.Nums.Word64LE Dahdit.Nums.Word64BE
- Dahdit.Run: GetErrorParseNeed :: !String -> !ByteCount -> !ByteCount -> GetError
- Dahdit.Run: instance Control.Monad.Error.Class.MonadError Dahdit.Run.GetError (Dahdit.Run.GetEff s r)
- Dahdit.Run: instance Control.Monad.Fail.MonadFail (Dahdit.Run.GetEff s r)
- Dahdit.Run: instance Control.Monad.Reader.Class.MonadReader (Dahdit.Run.GetEnv s r) (Dahdit.Run.GetEff s r)
- Dahdit.Run: instance GHC.Base.Applicative (Dahdit.Run.GetEff s r)
- Dahdit.Run: instance GHC.Base.Applicative (Dahdit.Run.GetRun s r)
- Dahdit.Run: instance GHC.Base.Functor (Dahdit.Run.GetEff s r)
- Dahdit.Run: instance GHC.Base.Functor (Dahdit.Run.GetRun s r)
- Dahdit.Run: instance GHC.Base.Monad (Dahdit.Run.GetEff s r)
- Dahdit.Run: instance GHC.Base.Monad (Dahdit.Run.GetRun s r)
- Dahdit.Run: instance GHC.Base.Monad m => GHC.Base.Applicative (Dahdit.Run.PutRun q m)
- Dahdit.Run: instance GHC.Base.Monad m => GHC.Base.Functor (Dahdit.Run.PutRun q m)
- Dahdit.Run: instance GHC.Base.Monad m => GHC.Base.Monad (Dahdit.Run.PutRun q m)
- Dahdit.Sizes: ViaStaticByteSized :: a -> ViaStaticByteSized a
- Dahdit.Sizes: [unViaStaticByteSized] :: ViaStaticByteSized a -> a
- Dahdit.Sizes: byteSize :: ByteSized a => a -> ByteCount
- Dahdit.Sizes: byteSizeFoldable :: (Foldable f, ByteSized a) => f a -> ByteCount
- Dahdit.Sizes: class ByteSized a
- Dahdit.Sizes: instance (Dahdit.Sizes.ByteSized a, Dahdit.Sizes.ByteSized b) => Dahdit.Sizes.ByteSized (a, b)
- Dahdit.Sizes: instance (Dahdit.Sizes.ByteSized a, Dahdit.Sizes.ByteSized b, Dahdit.Sizes.ByteSized c) => Dahdit.Sizes.ByteSized (a, b, c)
- Dahdit.Sizes: instance (Dahdit.Sizes.ByteSized a, Dahdit.Sizes.ByteSized b, Dahdit.Sizes.ByteSized c, Dahdit.Sizes.ByteSized d) => Dahdit.Sizes.ByteSized (a, b, c, d)
- Dahdit.Sizes: instance (Dahdit.Sizes.ByteSized a, Dahdit.Sizes.ByteSized b, Dahdit.Sizes.ByteSized c, Dahdit.Sizes.ByteSized d, Dahdit.Sizes.ByteSized e) => Dahdit.Sizes.ByteSized (a, b, c, d, e)
- Dahdit.Sizes: instance (Dahdit.Sizes.ByteSized b, Dahdit.Sizes.ByteSized a) => Dahdit.Sizes.ByteSized (Data.Either.Either b a)
- Dahdit.Sizes: instance (Dahdit.Sizes.ByteSized k, Dahdit.Sizes.ByteSized v) => Dahdit.Sizes.ByteSized (Data.Map.Internal.Map k v)
- Dahdit.Sizes: instance Dahdit.Sizes.ByteSized ()
- Dahdit.Sizes: instance Dahdit.Sizes.ByteSized Dahdit.Nums.DoubleBE
- Dahdit.Sizes: instance Dahdit.Sizes.ByteSized Dahdit.Nums.DoubleLE
- Dahdit.Sizes: instance Dahdit.Sizes.ByteSized Dahdit.Nums.FloatBE
- Dahdit.Sizes: instance Dahdit.Sizes.ByteSized Dahdit.Nums.FloatLE
- Dahdit.Sizes: instance Dahdit.Sizes.ByteSized Dahdit.Nums.Int16BE
- Dahdit.Sizes: instance Dahdit.Sizes.ByteSized Dahdit.Nums.Int16LE
- Dahdit.Sizes: instance Dahdit.Sizes.ByteSized Dahdit.Nums.Int24BE
- Dahdit.Sizes: instance Dahdit.Sizes.ByteSized Dahdit.Nums.Int24LE
- Dahdit.Sizes: instance Dahdit.Sizes.ByteSized Dahdit.Nums.Int32BE
- Dahdit.Sizes: instance Dahdit.Sizes.ByteSized Dahdit.Nums.Int32LE
- Dahdit.Sizes: instance Dahdit.Sizes.ByteSized Dahdit.Nums.Int64BE
- Dahdit.Sizes: instance Dahdit.Sizes.ByteSized Dahdit.Nums.Int64LE
- Dahdit.Sizes: instance Dahdit.Sizes.ByteSized Dahdit.Nums.Word16BE
- Dahdit.Sizes: instance Dahdit.Sizes.ByteSized Dahdit.Nums.Word16LE
- Dahdit.Sizes: instance Dahdit.Sizes.ByteSized Dahdit.Nums.Word24BE
- Dahdit.Sizes: instance Dahdit.Sizes.ByteSized Dahdit.Nums.Word24LE
- Dahdit.Sizes: instance Dahdit.Sizes.ByteSized Dahdit.Nums.Word32BE
- Dahdit.Sizes: instance Dahdit.Sizes.ByteSized Dahdit.Nums.Word32LE
- Dahdit.Sizes: instance Dahdit.Sizes.ByteSized Dahdit.Nums.Word64BE
- Dahdit.Sizes: instance Dahdit.Sizes.ByteSized Dahdit.Nums.Word64LE
- Dahdit.Sizes: instance Dahdit.Sizes.ByteSized Data.ByteString.Short.Internal.ShortByteString
- Dahdit.Sizes: instance Dahdit.Sizes.ByteSized Data.IntSet.Internal.IntSet
- Dahdit.Sizes: instance Dahdit.Sizes.ByteSized Data.ShortWord.Int24
- Dahdit.Sizes: instance Dahdit.Sizes.ByteSized Data.ShortWord.Word24
- Dahdit.Sizes: instance Dahdit.Sizes.ByteSized GHC.Int.Int16
- Dahdit.Sizes: instance Dahdit.Sizes.ByteSized GHC.Int.Int32
- Dahdit.Sizes: instance Dahdit.Sizes.ByteSized GHC.Int.Int64
- Dahdit.Sizes: instance Dahdit.Sizes.ByteSized GHC.Int.Int8
- Dahdit.Sizes: instance Dahdit.Sizes.ByteSized GHC.Types.Bool
- Dahdit.Sizes: instance Dahdit.Sizes.ByteSized GHC.Types.Char
- Dahdit.Sizes: instance Dahdit.Sizes.ByteSized GHC.Types.Double
- Dahdit.Sizes: instance Dahdit.Sizes.ByteSized GHC.Types.Float
- Dahdit.Sizes: instance Dahdit.Sizes.ByteSized GHC.Types.Int
- Dahdit.Sizes: instance Dahdit.Sizes.ByteSized GHC.Word.Word16
- Dahdit.Sizes: instance Dahdit.Sizes.ByteSized GHC.Word.Word32
- Dahdit.Sizes: instance Dahdit.Sizes.ByteSized GHC.Word.Word64
- Dahdit.Sizes: instance Dahdit.Sizes.ByteSized GHC.Word.Word8
- Dahdit.Sizes: instance Dahdit.Sizes.ByteSized a => Dahdit.Sizes.ByteSized (Data.Sequence.Internal.Seq a)
- Dahdit.Sizes: instance Dahdit.Sizes.ByteSized a => Dahdit.Sizes.ByteSized (Data.Set.Internal.Set a)
- Dahdit.Sizes: instance Dahdit.Sizes.ByteSized a => Dahdit.Sizes.ByteSized (GHC.Maybe.Maybe a)
- Dahdit.Sizes: instance Dahdit.Sizes.ByteSized a => Dahdit.Sizes.ByteSized [a]
- Dahdit.Sizes: instance Dahdit.Sizes.ByteSized v => Dahdit.Sizes.ByteSized (Data.IntMap.Internal.IntMap v)
- Dahdit.Sizes: instance Dahdit.Sizes.StaticByteSized a => Dahdit.Sizes.ByteSized (Dahdit.Sizes.ViaStaticByteSized a)
- Dahdit.Sizes: instance Dahdit.Sizes.StaticByteSized le => Dahdit.Sizes.ByteSized (Dahdit.Internal.ViaEndianPair le be)
- Dahdit.Sizes: instance Dahdit.Sizes.StaticByteSized le => Dahdit.Sizes.StaticByteSized (Dahdit.Internal.ViaEndianPair le be)
- Dahdit.Sizes: instance Dahdit.Sizes.StaticByteSized x => Dahdit.Sizes.ByteSized (Dahdit.Internal.ViaFromIntegral x y)
- Dahdit.Sizes: instance Dahdit.Sizes.StaticByteSized x => Dahdit.Sizes.StaticByteSized (Dahdit.Internal.ViaFromIntegral x y)
- Dahdit.Sizes: newtype ViaStaticByteSized a
+ Dahdit: GetErrorGlobalCap :: !Text -> !ByteCount -> !ByteCount -> GetError
+ Dahdit: GetErrorLocalCap :: !Text -> !ByteCount -> !ByteCount -> GetError
+ Dahdit: GetErrorRemaining :: !ByteCount -> GetError
+ Dahdit: GetIncRequest :: !ByteCount -> !ByteCount -> !ByteCount -> GetIncRequest
+ Dahdit: [girAbsPos] :: GetIncRequest -> !ByteCount
+ Dahdit: [girBaseOff] :: GetIncRequest -> !ByteCount
+ Dahdit: [girNeedLength] :: GetIncRequest -> !ByteCount
+ Dahdit: data GetIncRequest
+ Dahdit: getText :: ByteCount -> Get Text
+ Dahdit: putText :: Text -> Put
+ Dahdit: type GetIncCb z m = GetIncRequest -> m (Maybe z)
+ Dahdit.Binary: byteSize :: Binary a => a -> ByteCount
+ Dahdit.Binary: byteSizeFoldable :: (Foldable f, Binary a) => f a -> ByteCount
+ Dahdit.BinaryRep: instance (Dahdit.Sizes.StaticByteSized x, Dahdit.BinaryRep.BinaryRep x a) => Dahdit.Sizes.StaticByteSized (Dahdit.BinaryRep.ViaBinaryRep x a)
+ Dahdit.BinaryRep: instance Dahdit.BinaryRep.BinaryRep x a => Dahdit.Binary.Binary (Dahdit.BinaryRep.ViaBinaryRep x a)
+ Dahdit.Fancy: TermBytes16 :: ShortByteString -> TermBytes16
+ Dahdit.Fancy: TermBytes8 :: ShortByteString -> TermBytes8
+ Dahdit.Fancy: [unTermBytes16] :: TermBytes16 -> ShortByteString
+ Dahdit.Fancy: [unTermBytes8] :: TermBytes8 -> ShortByteString
+ Dahdit.Fancy: instance (Dahdit.Fancy.SymLen n s, GHC.TypeLits.KnownSymbol s, GHC.TypeNats.KnownNat n) => Dahdit.Binary.Binary (Dahdit.Fancy.ExactBytes n s)
+ Dahdit.Fancy: instance (Dahdit.Fancy.SymLen n s, GHC.TypeLits.KnownSymbol s, GHC.TypeNats.KnownNat n) => Dahdit.Sizes.StaticByteSized (Dahdit.Fancy.ExactBytes n s)
+ Dahdit.Fancy: instance (Dahdit.Fancy.SymLen n s, m GHC.Types.~ (n GHC.TypeNats.+ 1), t GHC.Types.~ GHC.TypeLits.ConsSymbol c s) => Dahdit.Fancy.SymLen m t
+ Dahdit.Fancy: instance Dahdit.Binary.Binary Dahdit.Fancy.TermBytes16
+ Dahdit.Fancy: instance Dahdit.Binary.Binary Dahdit.Fancy.TermBytes8
+ Dahdit.Fancy: instance Dahdit.Fancy.SymLen 0 ""
+ Dahdit.Fancy: instance Data.Default.Class.Default (Dahdit.Fancy.ExactBytes n s)
+ Dahdit.Fancy: instance Data.Default.Class.Default Dahdit.Fancy.TermBytes16
+ Dahdit.Fancy: instance Data.Default.Class.Default Dahdit.Fancy.TermBytes8
+ Dahdit.Fancy: instance Data.String.IsString Dahdit.Fancy.TermBytes16
+ Dahdit.Fancy: instance Data.String.IsString Dahdit.Fancy.TermBytes8
+ Dahdit.Fancy: instance GHC.Classes.Eq (Dahdit.Fancy.ExactBytes n s)
+ Dahdit.Fancy: instance GHC.Classes.Eq Dahdit.Fancy.TermBytes16
+ Dahdit.Fancy: instance GHC.Classes.Eq Dahdit.Fancy.TermBytes8
+ Dahdit.Fancy: instance GHC.Classes.Ord Dahdit.Fancy.TermBytes16
+ Dahdit.Fancy: instance GHC.Classes.Ord Dahdit.Fancy.TermBytes8
+ Dahdit.Fancy: instance GHC.Show.Show (Dahdit.Fancy.ExactBytes n s)
+ Dahdit.Fancy: instance GHC.Show.Show Dahdit.Fancy.TermBytes16
+ Dahdit.Fancy: instance GHC.Show.Show Dahdit.Fancy.TermBytes8
+ Dahdit.Fancy: newtype TermBytes16
+ Dahdit.Fancy: newtype TermBytes8
+ Dahdit.Funs: getText :: ByteCount -> Get Text
+ Dahdit.Funs: putText :: Text -> Put
+ Dahdit.Generic: instance (Dahdit.Generic.GByteSized a, Dahdit.Generic.GByteSized b, o GHC.Types.~ (n GHC.TypeNats.+ m)) => Dahdit.Generic.GByteSized (a GHC.Generics.:*: b)
+ Dahdit.Generic: instance (Dahdit.Generic.GStaticByteSized a, Dahdit.Generic.GStaticByteSized b, Dahdit.Generic.GStaticSize a GHC.Types.~ Dahdit.Generic.GStaticSize b) => Dahdit.Generic.GStaticByteSized (a GHC.Generics.:+: b)
+ Dahdit.Generic: instance (GHC.Generics.Generic t, Dahdit.Generic.GByteSized (GHC.Generics.Rep t), Dahdit.Generic.GBinary (GHC.Generics.Rep t)) => Dahdit.Binary.Binary (Dahdit.Generic.ViaGeneric t)
+ Dahdit.Generic: instance Dahdit.Binary.Binary a => Dahdit.Generic.GByteSized (GHC.Generics.K1 i a)
+ Dahdit.Generic: instance Dahdit.Generic.GStaticByteSized (GHC.Generics.Rep t) => Dahdit.Sizes.StaticByteSized (Dahdit.Generic.ViaStaticGeneric t)
+ Dahdit.Iface: class (PrimMonad m) => BinaryGetTarget z m
+ Dahdit.Iface: class (BinaryGetTarget z m) => BinaryPutTarget z m
+ Dahdit.Iface: class (BinaryGetTarget z m) => MutBinaryPutTarget z m
+ Dahdit.Iface: decodeEnd :: (Binary a, BinaryGetTarget z m) => z -> m (Either GetError a, ByteCount)
+ Dahdit.Iface: decodeFileEnd :: Binary a => FilePath -> IO (Either GetError a, ByteCount)
+ Dahdit.Iface: decodeInc :: (Binary a, BinaryGetTarget z m) => Maybe ByteCount -> GetIncCb z m -> m (Either GetError a, ByteCount, ByteCount)
+ Dahdit.Iface: getEnd :: Get a -> Get a
+ Dahdit.Iface: getTargetInc :: BinaryGetTarget z m => Maybe ByteCount -> Get a -> GetIncCb z m -> m (Either GetError a, ByteCount, ByteCount)
+ Dahdit.Iface: instance Control.Monad.Primitive.MonadPrim s m => Dahdit.Iface.BinaryGetTarget (Data.Array.Byte.MutableByteArray s) m
+ Dahdit.Iface: instance Control.Monad.Primitive.MonadPrim s m => Dahdit.Iface.MutBinaryPutTarget (Data.Array.Byte.MutableByteArray s) m
+ Dahdit.Iface: instance Control.Monad.Primitive.PrimMonad m => Dahdit.Iface.BinaryGetTarget Data.Array.Byte.ByteArray m
+ Dahdit.Iface: instance Control.Monad.Primitive.PrimMonad m => Dahdit.Iface.BinaryGetTarget Data.ByteString.Short.Internal.ShortByteString m
+ Dahdit.Iface: instance Control.Monad.Primitive.PrimMonad m => Dahdit.Iface.BinaryPutTarget Data.Array.Byte.ByteArray m
+ Dahdit.Iface: instance Control.Monad.Primitive.PrimMonad m => Dahdit.Iface.BinaryPutTarget Data.ByteString.Short.Internal.ShortByteString m
+ Dahdit.Iface: instance Dahdit.Iface.BinaryGetTarget (Data.Vector.Storable.Mutable.IOVector GHC.Word.Word8) GHC.Types.IO
+ Dahdit.Iface: instance Dahdit.Iface.BinaryGetTarget (Data.Vector.Storable.Vector GHC.Word.Word8) GHC.Types.IO
+ Dahdit.Iface: instance Dahdit.Iface.BinaryGetTarget Data.ByteString.Internal.ByteString GHC.Types.IO
+ Dahdit.Iface: instance Dahdit.Iface.BinaryGetTarget Data.Text.Internal.Text GHC.Types.IO
+ Dahdit.Iface: instance Dahdit.Iface.BinaryGetTarget GHC.Base.String GHC.Types.IO
+ Dahdit.Iface: instance Dahdit.Iface.BinaryPutTarget (Data.Vector.Storable.Vector GHC.Word.Word8) GHC.Types.IO
+ Dahdit.Iface: instance Dahdit.Iface.BinaryPutTarget Data.ByteString.Internal.ByteString GHC.Types.IO
+ Dahdit.Iface: instance Dahdit.Iface.BinaryPutTarget Data.Text.Internal.Text GHC.Types.IO
+ Dahdit.Iface: instance Dahdit.Iface.BinaryPutTarget GHC.Base.String GHC.Types.IO
+ Dahdit.Iface: instance Dahdit.Iface.MutBinaryPutTarget (Data.Vector.Storable.Mutable.IOVector GHC.Word.Word8) GHC.Types.IO
+ Dahdit.Internal: instance (Dahdit.Internal.SwapEndian x, GHC.Real.Integral x, GHC.Real.Integral y) => Dahdit.Internal.SwapEndian (Dahdit.Internal.ViaFromIntegral n x y)
+ Dahdit.Internal: instance Dahdit.Internal.EndianPair 1 GHC.Int.Int8 GHC.Int.Int8
+ Dahdit.Internal: instance Dahdit.Internal.EndianPair 1 GHC.Word.Word8 GHC.Word.Word8
+ Dahdit.Internal: instance GHC.Num.Num y => GHC.Num.Num (Dahdit.Internal.ViaFromIntegral n x y)
+ Dahdit.LiftedPrim: instance (Dahdit.LiftedPrim.LiftedPrim le, Dahdit.Internal.EndianPair n le be, n GHC.Types.~ Dahdit.Sizes.StaticSize le) => Dahdit.LiftedPrim.LiftedPrim (Dahdit.Internal.ViaEndianPair n le be)
+ Dahdit.LiftedPrim: instance (GHC.Real.Integral x, Dahdit.LiftedPrim.LiftedPrim x, GHC.Real.Integral y, n GHC.Types.~ Dahdit.Sizes.StaticSize x) => Dahdit.LiftedPrim.LiftedPrim (Dahdit.Internal.ViaFromIntegral n x y)
+ Dahdit.Mem: MemPtr :: !ForeignPtr Word8 -> !ByteCount -> !ByteCount -> MemPtr s
+ Dahdit.Mem: [mpForeign] :: MemPtr s -> !ForeignPtr Word8
+ Dahdit.Mem: [mpLength] :: MemPtr s -> !ByteCount
+ Dahdit.Mem: [mpOffset] :: MemPtr s -> !ByteCount
+ Dahdit.Mem: class (PrimMonad m) => MutableMem r w m | w m -> r
+ Dahdit.Mem: data MemPtr s
+ Dahdit.Mem: emptyMemPtr :: IO (MemPtr RealWorld)
+ Dahdit.Mem: instance Control.Monad.Primitive.MonadPrim s m => Dahdit.Mem.MutableMem Data.Array.Byte.ByteArray (Data.Array.Byte.MutableByteArray s) m
+ Dahdit.Mem: instance Control.Monad.Primitive.PrimMonad m => Dahdit.Mem.ReadMem Data.Array.Byte.ByteArray m
+ Dahdit.Mem: instance Dahdit.Mem.MutableMem (Data.Vector.Storable.Vector GHC.Word.Word8) (Data.Vector.Storable.Mutable.IOVector GHC.Word.Word8) GHC.Types.IO
+ Dahdit.Mem: instance Dahdit.Mem.ReadMem (Dahdit.Mem.MemPtr GHC.Prim.RealWorld) GHC.Types.IO
+ Dahdit.Mem: instance Dahdit.Mem.WriteMem Dahdit.Mem.MemPtr GHC.Types.IO
+ Dahdit.Mem: instance GHC.Classes.Eq (Dahdit.Mem.MemPtr s)
+ Dahdit.Mem: instance GHC.Classes.Ord (Dahdit.Mem.MemPtr s)
+ Dahdit.Mem: instance GHC.Show.Show (Dahdit.Mem.MemPtr s)
+ Dahdit.Mem: mutViewVecMem :: IOVector Word8 -> MemPtr RealWorld
+ Dahdit.Mem: unsafeFreezeMem :: MutableMem r w m => w -> m r
+ Dahdit.Mem: unsafeThawMem :: MutableMem r w m => r -> m w
+ Dahdit.Mem: unsafeUseFrozenMem :: MutableMem r w m => w -> (r -> m a) -> m a
+ Dahdit.Mem: unsafeUseThawedMem :: MutableMem r w m => r -> (w -> m a) -> m a
+ Dahdit.Mem: withBAMem :: MonadPrim s m => ByteCount -> (MutableByteArray s -> m ByteCount) -> m ByteArray
+ Dahdit.Mem: withBSMem :: ByteCount -> (MemPtr RealWorld -> IO ByteCount) -> IO ByteString
+ Dahdit.Mem: withSBSMem :: MonadPrim s m => ByteCount -> (MutableByteArray s -> m ByteCount) -> m ShortByteString
+ Dahdit.Mem: withVecMem :: ByteCount -> (MemPtr RealWorld -> IO ByteCount) -> IO (Vector Word8)
+ Dahdit.Nums: instance Dahdit.Internal.EndianPair 2 Dahdit.Nums.Int16LE Dahdit.Nums.Int16BE
+ Dahdit.Nums: instance Dahdit.Internal.EndianPair 2 Dahdit.Nums.Word16LE Dahdit.Nums.Word16BE
+ Dahdit.Nums: instance Dahdit.Internal.EndianPair 3 Dahdit.Nums.Int24LE Dahdit.Nums.Int24BE
+ Dahdit.Nums: instance Dahdit.Internal.EndianPair 3 Dahdit.Nums.Word24LE Dahdit.Nums.Word24BE
+ Dahdit.Nums: instance Dahdit.Internal.EndianPair 4 Dahdit.Nums.FloatLE Dahdit.Nums.FloatBE
+ Dahdit.Nums: instance Dahdit.Internal.EndianPair 4 Dahdit.Nums.Int32LE Dahdit.Nums.Int32BE
+ Dahdit.Nums: instance Dahdit.Internal.EndianPair 4 Dahdit.Nums.Word32LE Dahdit.Nums.Word32BE
+ Dahdit.Nums: instance Dahdit.Internal.EndianPair 8 Dahdit.Nums.DoubleLE Dahdit.Nums.DoubleBE
+ Dahdit.Nums: instance Dahdit.Internal.EndianPair 8 Dahdit.Nums.Int64LE Dahdit.Nums.Int64BE
+ Dahdit.Nums: instance Dahdit.Internal.EndianPair 8 Dahdit.Nums.Word64LE Dahdit.Nums.Word64BE
+ Dahdit.Proxy: proxyForRepF :: f t -> Rep t a -> Proxy (Rep t)
+ Dahdit.Run: GetErrorGlobalCap :: !Text -> !ByteCount -> !ByteCount -> GetError
+ Dahdit.Run: GetErrorLocalCap :: !Text -> !ByteCount -> !ByteCount -> GetError
+ Dahdit.Run: GetErrorRemaining :: !ByteCount -> GetError
+ Dahdit.Run: GetIncChunk :: !ByteCount -> !ByteCount -> !r -> GetIncChunk r
+ Dahdit.Run: GetIncEnv :: !MutVar s ByteCount -> !MutVar s ByteCount -> !MutVar s (Seq ByteCount) -> !MutVar s (GetIncChunk r) -> !MutVar s (Seq ByteCount) -> GetIncEnv s r
+ Dahdit.Run: GetIncRequest :: !ByteCount -> !ByteCount -> !ByteCount -> GetIncRequest
+ Dahdit.Run: GetIncSuspend :: !GetIncRequest -> !Maybe z -> x -> GetIncSuspend z x
+ Dahdit.Run: [gicArray] :: GetIncChunk r -> !r
+ Dahdit.Run: [gicLocalCap] :: GetIncChunk r -> !ByteCount
+ Dahdit.Run: [gicLocalOff] :: GetIncChunk r -> !ByteCount
+ Dahdit.Run: [gieCurChunk] :: GetIncEnv s r -> !MutVar s (GetIncChunk r)
+ Dahdit.Run: [gieGlobalAbs] :: GetIncEnv s r -> !MutVar s ByteCount
+ Dahdit.Run: [gieGlobalCap] :: GetIncEnv s r -> !MutVar s (Seq ByteCount)
+ Dahdit.Run: [gieGlobalRel] :: GetIncEnv s r -> !MutVar s ByteCount
+ Dahdit.Run: [gieLookAhead] :: GetIncEnv s r -> !MutVar s (Seq ByteCount)
+ Dahdit.Run: [girAbsPos] :: GetIncRequest -> !ByteCount
+ Dahdit.Run: [girBaseOff] :: GetIncRequest -> !ByteCount
+ Dahdit.Run: [girNeedLength] :: GetIncRequest -> !ByteCount
+ Dahdit.Run: data GetIncChunk r
+ Dahdit.Run: data GetIncEnv s r
+ Dahdit.Run: data GetIncRequest
+ Dahdit.Run: data GetIncSuspend z x
+ Dahdit.Run: instance Control.Monad.Error.Class.MonadError Dahdit.Run.GetError (Dahdit.Run.GetIncM s r m)
+ Dahdit.Run: instance Control.Monad.Free.Class.MonadFree (Dahdit.Run.GetIncSuspendChunk r) (Dahdit.Run.GetIncM s r m)
+ Dahdit.Run: instance Control.Monad.Trans.Class.MonadTrans (Dahdit.Run.GetIncM s r)
+ Dahdit.Run: instance GHC.Base.Applicative (Dahdit.Run.GetIncM s r m)
+ Dahdit.Run: instance GHC.Base.Applicative (Dahdit.Run.PutRun q m)
+ Dahdit.Run: instance GHC.Base.Functor (Dahdit.Run.GetIncM s r m)
+ Dahdit.Run: instance GHC.Base.Functor (Dahdit.Run.GetIncSuspend z)
+ Dahdit.Run: instance GHC.Base.Functor (Dahdit.Run.PutRun q m)
+ Dahdit.Run: instance GHC.Base.Monad (Dahdit.Run.GetIncM s r m)
+ Dahdit.Run: instance GHC.Base.Monad (Dahdit.Run.PutRun q m)
+ Dahdit.Run: instance GHC.Classes.Eq Dahdit.Run.GetIncRequest
+ Dahdit.Run: instance GHC.Classes.Ord Dahdit.Run.GetIncRequest
+ Dahdit.Run: instance GHC.Show.Show Dahdit.Run.GetIncRequest
+ Dahdit.Run: newGetIncEnv :: MonadPrim s m => Maybe ByteCount -> GetIncChunk r -> m (GetIncEnv s r)
+ Dahdit.Run: runGetIncInternal :: (MonadPrim s m, ReadMem r m) => Get a -> GetIncEnv s r -> GetIncCbChunk r m -> m (Either GetError a, ByteCount, ByteCount)
+ Dahdit.Run: type GetIncCb z m = GetIncRequest -> m (Maybe z)
+ Dahdit.Sizes: instance (Dahdit.Sizes.StaticByteSized le, n GHC.Types.~ Dahdit.Sizes.StaticSize le) => Dahdit.Sizes.StaticByteSized (Dahdit.Internal.ViaEndianPair n le be)
+ Dahdit.Sizes: instance (Dahdit.Sizes.StaticByteSized x, n GHC.Types.~ Dahdit.Sizes.StaticSize x) => Dahdit.Sizes.StaticByteSized (Dahdit.Internal.ViaFromIntegral n x y)
+ Dahdit.Sizes: type StaticSize a :: Nat;
+ Dahdit.Sizes: }
- Dahdit: GetErrorFail :: !String -> GetError
+ Dahdit: GetErrorFail :: !Text -> GetError
- Dahdit: GetErrorScopedMismatch :: !ByteCount -> !ByteCount -> GetError
+ Dahdit: GetErrorScopedMismatch :: !ScopeMode -> !ByteCount -> !ByteCount -> GetError
- Dahdit: prettyGetError :: GetError -> String
+ Dahdit: prettyGetError :: GetError -> Text
- Dahdit.BinaryRep: ViaBinaryRep :: a -> ViaBinaryRep a
+ Dahdit.BinaryRep: ViaBinaryRep :: a -> ViaBinaryRep x a
- Dahdit.BinaryRep: [unViaBinaryRep] :: ViaBinaryRep a -> a
+ Dahdit.BinaryRep: [unViaBinaryRep] :: ViaBinaryRep x a -> a
- Dahdit.BinaryRep: class Binary x => BinaryRep x a | a -> x
+ Dahdit.BinaryRep: class (Binary x) => BinaryRep x a | a -> x
- Dahdit.BinaryRep: newtype ViaBinaryRep a
+ Dahdit.BinaryRep: newtype ViaBinaryRep x a
- Dahdit.Fancy: ExactBytes :: () -> ExactBytes (s :: Symbol)
+ Dahdit.Fancy: ExactBytes :: () -> ExactBytes (n :: Nat) (s :: Symbol)
- Dahdit.Fancy: [unExactBytes] :: ExactBytes (s :: Symbol) -> ()
+ Dahdit.Fancy: [unExactBytes] :: ExactBytes (n :: Nat) (s :: Symbol) -> ()
- Dahdit.Fancy: newtype ExactBytes (s :: Symbol)
+ Dahdit.Fancy: newtype ExactBytes (n :: Nat) (s :: Symbol)
- Dahdit.Free: GetFFail :: !String -> GetF a
+ Dahdit.Free: GetFFail :: !Text -> GetF a
- Dahdit.Iface: decode :: (Binary a, BinaryTarget z) => z -> (Either GetError a, ByteCount)
+ Dahdit.Iface: decode :: (Binary a, BinaryGetTarget z m) => z -> m (Either GetError a, ByteCount)
- Dahdit.Iface: encode :: (Binary a, ByteSized a, BinaryTarget z) => a -> z
+ Dahdit.Iface: encode :: (Binary a, BinaryPutTarget z m) => a -> m z
- Dahdit.Iface: encodeFile :: (Binary a, ByteSized a) => a -> FilePath -> IO ()
+ Dahdit.Iface: encodeFile :: Binary a => a -> FilePath -> IO ()
- Dahdit.Iface: getTarget :: BinaryTarget z => Get a -> z -> (Either GetError a, ByteCount)
+ Dahdit.Iface: getTarget :: BinaryGetTarget z m => Get a -> z -> m (Either GetError a, ByteCount)
- Dahdit.Iface: getTargetOffset :: BinaryTarget z => ByteCount -> Get a -> z -> (Either GetError a, ByteCount)
+ Dahdit.Iface: getTargetOffset :: BinaryGetTarget z m => ByteCount -> Get a -> z -> m (Either GetError a, ByteCount)
- Dahdit.Iface: mutEncode :: (Binary a, ByteSized a, MutBinaryTarget m z) => a -> z -> m ByteCount
+ Dahdit.Iface: mutEncode :: (Binary a, MutBinaryPutTarget z m) => a -> z -> m ByteCount
- Dahdit.Iface: mutPutTarget :: MutBinaryTarget m z => Put -> z -> m ByteCount
+ Dahdit.Iface: mutPutTarget :: MutBinaryPutTarget z m => Put -> z -> m ByteCount
- Dahdit.Iface: mutPutTargetOffset :: MutBinaryTarget m z => ByteCount -> Put -> z -> m ByteCount
+ Dahdit.Iface: mutPutTargetOffset :: MutBinaryPutTarget z m => ByteCount -> Put -> z -> m ByteCount
- Dahdit.Iface: mutPutTargetOffsetUnsafe :: MutBinaryTarget m z => ByteCount -> Put -> ByteCount -> z -> m ByteCount
+ Dahdit.Iface: mutPutTargetOffsetUnsafe :: MutBinaryPutTarget z m => ByteCount -> Put -> ByteCount -> z -> m ByteCount
- Dahdit.Iface: putTarget :: BinaryTarget z => Put -> z
+ Dahdit.Iface: putTarget :: BinaryPutTarget z m => Put -> m z
- Dahdit.Iface: putTargetUnsafe :: BinaryTarget z => Put -> ByteCount -> z
+ Dahdit.Iface: putTargetUnsafe :: BinaryPutTarget z m => Put -> ByteCount -> m z
- Dahdit.Internal: ViaEndianPair :: be -> ViaEndianPair le be
+ Dahdit.Internal: ViaEndianPair :: be -> ViaEndianPair (n :: Nat) le be
- Dahdit.Internal: ViaFromIntegral :: y -> ViaFromIntegral x y
+ Dahdit.Internal: ViaFromIntegral :: y -> ViaFromIntegral (n :: Nat) x y
- Dahdit.Internal: [unViaEndianPair] :: ViaEndianPair le be -> be
+ Dahdit.Internal: [unViaEndianPair] :: ViaEndianPair (n :: Nat) le be -> be
- Dahdit.Internal: [unViaFromIntegral] :: ViaFromIntegral x y -> y
+ Dahdit.Internal: [unViaFromIntegral] :: ViaFromIntegral (n :: Nat) x y -> y
- Dahdit.Internal: class (Num le, Num be) => EndianPair le be | le -> be, be -> le
+ Dahdit.Internal: class (Num le, Num be) => EndianPair (n :: Nat) le be | le -> n, be -> n, le -> be, be -> le
- Dahdit.Internal: class Num w => SwapEndian w
+ Dahdit.Internal: class (Num w) => SwapEndian w
- Dahdit.Internal: newtype ViaEndianPair le be
+ Dahdit.Internal: newtype ViaEndianPair (n :: Nat) le be
- Dahdit.Internal: newtype ViaFromIntegral x y
+ Dahdit.Internal: newtype ViaFromIntegral (n :: Nat) x y
- Dahdit.Internal: toBigEndian :: EndianPair le be => le -> be
+ Dahdit.Internal: toBigEndian :: EndianPair n le be => le -> be
- Dahdit.Internal: toLittleEndian :: EndianPair le be => be -> le
+ Dahdit.Internal: toLittleEndian :: EndianPair n le be => be -> le
- Dahdit.LiftedPrim: class StaticByteSized a => LiftedPrim a
+ Dahdit.LiftedPrim: class (StaticByteSized a) => LiftedPrim a
- Dahdit.Mem: class ReadMem r
+ Dahdit.Mem: class (PrimMonad m) => ReadMem r m
- Dahdit.Mem: class PrimMonad m => WriteMem q m
+ Dahdit.Mem: class (PrimMonad m) => WriteMem q m
- Dahdit.Mem: cloneArrayMemInBytes :: ReadMem r => r -> ByteCount -> ByteCount -> ByteArray
+ Dahdit.Mem: cloneArrayMemInBytes :: ReadMem r m => r -> ByteCount -> ByteCount -> m ByteArray
- Dahdit.Mem: indexMemInBytes :: (ReadMem r, LiftedPrim a) => r -> ByteCount -> a
+ Dahdit.Mem: indexMemInBytes :: (ReadMem r m, LiftedPrim a) => r -> ByteCount -> m a
- Dahdit.Mem: readSBSMem :: ReadMem r => r -> ByteCount -> ByteCount -> ShortByteString
+ Dahdit.Mem: readSBSMem :: ReadMem r m => r -> ByteCount -> ByteCount -> m ShortByteString
- Dahdit.Mem: viewBSMem :: ByteString -> Ptr Word8
+ Dahdit.Mem: viewBSMem :: ByteString -> MemPtr RealWorld
- Dahdit.Mem: viewVecMem :: Vector Word8 -> Ptr Word8
+ Dahdit.Mem: viewVecMem :: Vector Word8 -> MemPtr RealWorld
- Dahdit.Run: GetErrorFail :: !String -> GetError
+ Dahdit.Run: GetErrorFail :: !Text -> GetError
- Dahdit.Run: GetErrorScopedMismatch :: !ByteCount -> !ByteCount -> GetError
+ Dahdit.Run: GetErrorScopedMismatch :: !ScopeMode -> !ByteCount -> !ByteCount -> GetError
- Dahdit.Run: prettyGetError :: GetError -> String
+ Dahdit.Run: prettyGetError :: GetError -> Text
- Dahdit.Run: runGetInternal :: ReadMem r => ByteCount -> Get a -> ByteCount -> r -> (Either GetError a, ByteCount)
+ Dahdit.Run: runGetInternal :: ReadMem r m => ByteCount -> Get a -> ByteCount -> r -> m (Either GetError a, ByteCount)
- Dahdit.Run: runPutInternal :: (PrimBase m, WriteMem q m) => ByteCount -> Put -> ByteCount -> (ByteCount -> ByteCount -> m (q (PrimState m), Maybe (IO ()))) -> (q (PrimState m) -> ByteCount -> ByteCount -> m z) -> m z
+ Dahdit.Run: runPutInternal :: WriteMem q m => ByteCount -> Put -> ByteCount -> q (PrimState m) -> m ByteCount
- Dahdit.Sizes: class ByteSized a => StaticByteSized a
+ Dahdit.Sizes: class (KnownNat (StaticSize a)) => StaticByteSized a where {
Files
- LICENSE +0/−30
- README.md +8/−1
- dahdit.cabal +11/−8
- src/Dahdit.hs +3/−1
- src/Dahdit/Binary.hs +57/−6
- src/Dahdit/BinaryRep.hs +7/−8
- src/Dahdit/Codec.hs +0/−130
- src/Dahdit/Fancy.hs +62/−33
- src/Dahdit/Free.hs +8/−6
- src/Dahdit/Funs.hs +22/−12
- src/Dahdit/Generic.hs +45/−35
- src/Dahdit/Iface.hs +165/−54
- src/Dahdit/Internal.hs +12/−11
- src/Dahdit/LiftedPrim.hs +21/−21
- src/Dahdit/LiftedPrimArray.hs +12/−15
- src/Dahdit/Mem.hs +103/−96
- src/Dahdit/Nums.hs +10/−10
- src/Dahdit/Proxy.hs +5/−0
- src/Dahdit/Run.hs +293/−202
- src/Dahdit/Sizes.hs +50/−192
- test/Main.hs +221/−51
− LICENSE
@@ -1,30 +0,0 @@-Copyright Eric Conlon (c) 2022--All rights reserved.--Redistribution and use in source and binary forms, with or without-modification, are permitted provided that the following conditions are met:-- * Redistributions of source code must retain the above copyright- notice, this list of conditions and the following disclaimer.-- * Redistributions in binary form must reproduce the above- copyright notice, this list of conditions and the following- disclaimer in the documentation and/or other materials provided- with the distribution.-- * Neither the name of Eric Conlon nor the names of other- contributors may be used to endorse or promote products derived- from this software without specific prior written permission.--THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
README.md view
@@ -10,7 +10,14 @@ * It uses `ByteArray` internally to avoid generating new or retaining references to old pinned memory. * Examining `Put` can yield required byte size without serializing. * Derivation uses `via` and not `anyclass` for better control of derived instances.-* Optionally, types implementing `Binary` can also implement or derive `ByteSized` for size calculation.+* Types implementing `Binary` can implement `byteSized` for size calculation (or it will reflect on `put`). * Known-statically-sized types can implement `StaticByteSized` for size speedups. * Provides several additional types representing fixed-length strings or sequences (using `TypeLits`).++## Static sizes++You may find it necessary to discharge simple `KnownNat` constraints with a plugin like `ghc-typelits-knownnat`.+Add that package to your dependencies and add this to the top of the necessary files:++ {-# OPTIONS_GHC -fplugin GHC.TypeLits.KnownNat.Solver #-}
dahdit.cabal view
@@ -1,11 +1,11 @@ cabal-version: 1.12 --- This file has been generated from package.yaml by hpack version 0.35.1.+-- This file has been generated from package.yaml by hpack version 0.36.0. -- -- see: https://github.com/sol/hpack name: dahdit-version: 0.3.0+version: 0.5.0 synopsis: Binary parsing and serialization with integrated size description: Please see the README on GitHub at <https://github.com/ejconlon/dahdit#readme> category: Data@@ -15,7 +15,6 @@ maintainer: ejconlon@gmail.com copyright: (c) 2022 Eric Conlon license: BSD3-license-file: LICENSE build-type: Simple tested-with: GHC == 9.2.7@@ -31,7 +30,6 @@ Dahdit Dahdit.Binary Dahdit.BinaryRep- Dahdit.Codec Dahdit.Fancy Dahdit.Free Dahdit.Funs@@ -83,10 +81,12 @@ , data-default ==0.7.* , data-sword ==0.2.* , free ==5.1.*+ , ghc-typelits-knownnat ==0.7.* , mtl ==2.2.* , primitive >=0.7 && <0.9+ , text >=1.2 && <2.1 , transformers ==0.5.*- , vector ==0.12.*+ , vector >=0.12 && <0.14 default-language: Haskell2010 test-suite dahdit-test@@ -130,11 +130,14 @@ , dahdit , data-default ==0.7.* , data-sword ==0.2.*+ , falsify ==0.2.* , free ==5.1.*+ , ghc-typelits-knownnat ==0.7.* , mtl ==2.2.* , primitive >=0.7 && <0.9- , tasty- , tasty-hunit+ , tasty ==1.4.*+ , tasty-hunit ==0.10.*+ , text >=1.2 && <2.1 , transformers ==0.5.*- , vector ==0.12.*+ , vector >=0.12 && <0.14 default-language: Haskell2010
src/Dahdit.hs view
@@ -10,6 +10,8 @@ , Proxy (..) , GetError (..) , prettyGetError+ , GetIncRequest (..)+ , GetIncCb , runCount , module Dahdit.Binary , module Dahdit.BinaryRep@@ -37,7 +39,7 @@ import Dahdit.LiftedPrimArray import Dahdit.Nums import Dahdit.Proxy-import Dahdit.Run (GetError (..), prettyGetError, runCount)+import Dahdit.Run (GetError (..), GetIncCb, GetIncRequest (..), prettyGetError, runCount) import Dahdit.Sizes import Data.ByteString (ByteString) import Data.ByteString.Short (ShortByteString)
src/Dahdit/Binary.hs view
@@ -1,5 +1,6 @@ module Dahdit.Binary ( Binary (..)+ , byteSizeFoldable ) where @@ -76,9 +77,11 @@ , Word64BE (..) , Word64LE (..) )-import Dahdit.Sizes (ElemCount (..))+import Dahdit.Run (runCount)+import Dahdit.Sizes (ByteCount (..), ElemCount (..)) import Data.ByteString.Internal (c2w, w2c) import Data.Coerce (coerce)+import Data.Foldable (foldMap') import Data.Int (Int16, Int32, Int64, Int8) import Data.IntMap (IntMap) import qualified Data.IntMap as IntMap@@ -86,6 +89,7 @@ import qualified Data.IntSet as IntSet import Data.Map.Strict (Map) import qualified Data.Map.Strict as Map+import Data.Semigroup (Sum (..)) import Data.Sequence (Seq (..)) import qualified Data.Sequence as Seq import Data.Set (Set)@@ -94,100 +98,125 @@ import Data.Word (Word16, Word32, Word64, Word8) class Binary a where+ byteSize :: a -> ByteCount+ byteSize = runCount . put get :: Get a put :: a -> Put -- Basic types instance Binary () where+ byteSize _ = 0 get = pure () put _ = pure () instance Binary Word8 where+ byteSize _ = 1 get = getWord8 put = putWord8 instance Binary Int8 where+ byteSize _ = 1 get = getInt8 put = putInt8 instance Binary Word16LE where+ byteSize _ = 2 get = getWord16LE put = putWord16LE instance Binary Int16LE where+ byteSize _ = 2 get = getInt16LE put = putInt16LE instance Binary Word24LE where+ byteSize _ = 3 get = getWord24LE put = putWord24LE instance Binary Int24LE where+ byteSize _ = 3 get = getInt24LE put = putInt24LE instance Binary Word32LE where+ byteSize _ = 4 get = getWord32LE put = putWord32LE instance Binary Int32LE where+ byteSize _ = 4 get = getInt32LE put = putInt32LE instance Binary Word64LE where+ byteSize _ = 8 get = getWord64LE put = putWord64LE instance Binary Int64LE where+ byteSize _ = 8 get = getInt64LE put = putInt64LE instance Binary FloatLE where+ byteSize _ = 4 get = getFloatLE put = putFloatLE instance Binary DoubleLE where+ byteSize _ = 8 get = getDoubleLE put = putDoubleLE instance Binary Word16BE where+ byteSize _ = 2 get = getWord16BE put = putWord16BE instance Binary Int16BE where+ byteSize _ = 2 get = getInt16BE put = putInt16BE instance Binary Word24BE where+ byteSize _ = 3 get = getWord24BE put = putWord24BE instance Binary Int24BE where+ byteSize _ = 3 get = getInt24BE put = putInt24BE instance Binary Word32BE where+ byteSize _ = 4 get = getWord32BE put = putWord32BE instance Binary Int32BE where+ byteSize _ = 4 get = getInt32BE put = putInt32BE instance Binary Word64BE where+ byteSize _ = 8 get = getWord64BE put = putWord64BE instance Binary Int64BE where+ byteSize _ = 8 get = getInt64BE put = putInt64BE instance Binary FloatBE where+ byteSize _ = 4 get = getFloatBE put = putFloatBE instance Binary DoubleBE where+ byteSize _ = 8 get = getDoubleBE put = putDoubleBE @@ -212,46 +241,58 @@ deriving via DoubleLE instance Binary Double instance Binary Bool where+ byteSize _ = 1 get = fmap (/= 0) getWord8 put b = putWord8 (if b then 1 else 0) instance Binary Char where+ byteSize _ = 1 get = fmap w2c getWord8 put = putWord8 . c2w instance Binary Int where+ byteSize _ = 8 get = fmap fromIntegral getInt64LE put = putInt64LE . fromIntegral -instance Binary a => Binary [a] where+instance (Binary a) => Binary [a] where+ byteSize as = 8 + byteSizeFoldable as get = do ec <- get @Int getList (coerce ec) get put s = put @Int (length s) *> putList put s -instance Binary a => Binary (Seq a) where+instance (Binary a) => Binary (Seq a) where+ byteSize as = 8 + byteSizeFoldable as get = do ec <- get @Int getSeq (coerce ec) get put s = put @Int (Seq.length s) *> putSeq put s -instance Binary a => Binary (Set a) where+instance (Binary a) => Binary (Set a) where+ byteSize = byteSize . Set.toAscList get = fmap Set.fromDistinctAscList get put = put . Set.toAscList instance (Binary k, Binary v) => Binary (Map k v) where+ byteSize = byteSize . Map.toAscList get = fmap Map.fromDistinctAscList get put = put . Map.toAscList instance Binary IntSet where+ byteSize = byteSize . IntSet.toAscList get = fmap IntSet.fromDistinctAscList get put = put . IntSet.toAscList -instance Binary v => Binary (IntMap v) where+instance (Binary v) => Binary (IntMap v) where+ byteSize = byteSize . IntMap.toAscList get = fmap IntMap.fromDistinctAscList get put = put . IntMap.toAscList -instance Binary a => Binary (Maybe a) where+instance (Binary a) => Binary (Maybe a) where+ byteSize = \case+ Nothing -> 1+ Just a -> 1 + byteSize a get = do tag <- get @Int case tag of@@ -263,6 +304,9 @@ Just a -> put @Int 1 *> put a instance (Binary b, Binary a) => Binary (Either b a) where+ byteSize = \case+ Left b -> 1 + byteSize b+ Right a -> 1 + byteSize a get = do tag <- get @Int case tag of@@ -274,6 +318,7 @@ Right a -> put @Int 1 *> put a instance (Binary a, Binary b) => Binary (a, b) where+ byteSize (a, b) = byteSize a + byteSize b get = do a <- get b <- get@@ -281,6 +326,7 @@ put (a, b) = put a *> put b instance (Binary a, Binary b, Binary c) => Binary (a, b, c) where+ byteSize (a, b, c) = byteSize a + byteSize b + byteSize c get = do a <- get b <- get@@ -289,6 +335,7 @@ put (a, b, c) = put a *> put b *> put c instance (Binary a, Binary b, Binary c, Binary d) => Binary (a, b, c, d) where+ byteSize (a, b, c, d) = byteSize a + byteSize b + byteSize c + byteSize d get = do a <- get b <- get@@ -298,6 +345,7 @@ put (a, b, c, d) = put a *> put b *> put c *> put d instance (Binary a, Binary b, Binary c, Binary d, Binary e) => Binary (a, b, c, d, e) where+ byteSize (a, b, c, d, e) = byteSize a + byteSize b + byteSize c + byteSize d + byteSize e get = do a <- get b <- get@@ -306,3 +354,6 @@ e <- get pure (a, b, c, d, e) put (a, b, c, d, e) = put a *> put b *> put c *> put d *> put e++byteSizeFoldable :: (Foldable f, Binary a) => f a -> ByteCount+byteSizeFoldable = getSum . foldMap' (Sum . byteSize)
src/Dahdit/BinaryRep.hs view
@@ -9,10 +9,10 @@ where import Dahdit.Binary (Binary (..))-import Dahdit.Sizes (ByteSized (..), StaticByteSized (..))+import Dahdit.Sizes (StaticByteSized (..)) import Data.Proxy (Proxy (..)) -class Binary x => BinaryRep x a | a -> x where+class (Binary x) => BinaryRep x a | a -> x where fromBinaryRep :: x -> Either String a toBinaryRep :: a -> x @@ -32,14 +32,13 @@ fromBinaryRep = Right . ViaIntegral . fromIntegral toBinaryRep = fromIntegral . unViaIntegral -newtype ViaBinaryRep a = ViaBinaryRep {unViaBinaryRep :: a}--instance (ByteSized x, BinaryRep x a) => ByteSized (ViaBinaryRep a) where- byteSize = byteSize . toBinaryRep . unViaBinaryRep+newtype ViaBinaryRep x a = ViaBinaryRep {unViaBinaryRep :: a} -instance (StaticByteSized x, BinaryRep x a) => StaticByteSized (ViaBinaryRep a) where+instance (StaticByteSized x, BinaryRep x a) => StaticByteSized (ViaBinaryRep x a) where+ type StaticSize (ViaBinaryRep x a) = StaticSize x staticByteSize _ = staticByteSize (Proxy :: Proxy x) -instance BinaryRep x a => Binary (ViaBinaryRep a) where+instance (BinaryRep x a) => Binary (ViaBinaryRep x a) where+ byteSize = byteSize . toBinaryRep . unViaBinaryRep get = get >>= either fail (pure . ViaBinaryRep) . fromBinaryRep put = put . toBinaryRep . unViaBinaryRep
− src/Dahdit/Codec.hs
@@ -1,130 +0,0 @@--- Experimental - bidirectional codecs--- See https://hackage.haskell.org/package/codec--- And https://blog.poisson.chat/posts/2016-10-12-bidirectional-serialization.html-module Dahdit.Codec- ( Codec- , build- , binary- , parse- , produce- , bindPair- , bindTag- , HasCodec (..)- , ViaBinary (..)- , ViaCodec (..)- )-where--import Dahdit.Binary (Binary (..))-import Dahdit.Fancy (BoolByte, ExactBytes, StaticArray, StaticSeq, TermBytes)-import Dahdit.Free (Get, Put)-import Dahdit.LiftedPrim (LiftedPrim)-import Dahdit.Nums (FloatBE, FloatLE, Int16BE, Int16LE, Int24BE, Int24LE, Int32BE, Int32LE, Word16BE, Word16LE, Word24BE, Word24LE, Word32BE, Word32LE)-import Dahdit.Sizes (ByteSized (..), StaticByteSized)-import Data.Coerce (coerce)-import Data.Default (Default)-import Data.Int (Int8)-import Data.Word (Word8)-import GHC.TypeLits (KnownNat, KnownSymbol)--data Codec' x a = Codec'- { parse' :: Get a- , produce' :: x -> Put- }--instance Functor (Codec' x) where- fmap f c = c {parse' = fmap f (parse' c)}--instance Applicative (Codec' x) where- pure a = Codec' (pure a) (const (pure ()))-- f <*> a =- Codec'- { parse' = parse' f <*> parse' a- , produce' = \x -> produce' f x *> produce' a x- }--type Codec a = Codec' a a--build :: Get a -> (a -> Put) -> Codec a-build = Codec'--binary :: Binary a => Codec a-binary = build get put--parse :: Codec a -> Get a-parse = parse'--produce :: Codec a -> a -> Put-produce = produce'--bindPair :: Codec a -> (a -> Codec b) -> Codec (a, b)-bindPair c f =- Codec'- (parse c >>= \a -> fmap (a,) (parse (f a)))- (\(a, b) -> produce c a *> produce (f a) b)--bindTag :: (b -> a) -> Codec a -> (a -> Codec b) -> Codec b-bindTag t c f =- Codec'- (parse c >>= parse . f)- (\b -> let a = t b in produce c a *> produce (f a) b)--class HasCodec a where- codec :: Codec a--newtype ViaBinary a = ViaBinary {unViaBinary :: a}--instance Binary a => HasCodec (ViaBinary a) where- codec = coerce (binary @a)--deriving via (ViaBinary Word8) instance HasCodec Word8--deriving via (ViaBinary Int8) instance HasCodec Int8--deriving via (ViaBinary Word16LE) instance HasCodec Word16LE--deriving via (ViaBinary Int16LE) instance HasCodec Int16LE--deriving via (ViaBinary Word24LE) instance HasCodec Word24LE--deriving via (ViaBinary Int24LE) instance HasCodec Int24LE--deriving via (ViaBinary Word32LE) instance HasCodec Word32LE--deriving via (ViaBinary Int32LE) instance HasCodec Int32LE--deriving via (ViaBinary FloatLE) instance HasCodec FloatLE--deriving via (ViaBinary Word16BE) instance HasCodec Word16BE--deriving via (ViaBinary Int16BE) instance HasCodec Int16BE--deriving via (ViaBinary Word24BE) instance HasCodec Word24BE--deriving via (ViaBinary Int24BE) instance HasCodec Int24BE--deriving via (ViaBinary Word32BE) instance HasCodec Word32BE--deriving via (ViaBinary Int32BE) instance HasCodec Int32BE--deriving via (ViaBinary FloatBE) instance HasCodec FloatBE--deriving via (ViaBinary TermBytes) instance HasCodec TermBytes--deriving via (ViaBinary (StaticSeq n a)) instance (KnownNat n, Binary a, StaticByteSized a, Default a) => HasCodec (StaticSeq n a)--deriving via (ViaBinary (StaticArray n a)) instance (KnownNat n, LiftedPrim a, Default a) => HasCodec (StaticArray n a)--deriving via (ViaBinary BoolByte) instance HasCodec BoolByte--deriving via (ViaBinary (ExactBytes s)) instance KnownSymbol s => HasCodec (ExactBytes s)--newtype ViaCodec a = ViaCodec {unViaCodec :: a}--instance ByteSized a => ByteSized (ViaCodec a) where- byteSize = byteSize . unViaCodec--instance HasCodec a => Binary (ViaCodec a) where- get = coerce (parse (codec @a))- put = coerce (produce (codec @a))
src/Dahdit/Fancy.hs view
@@ -1,5 +1,10 @@+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE NoStarIsType #-}+{-# OPTIONS_GHC -fplugin GHC.TypeLits.KnownNat.Solver #-}+ module Dahdit.Fancy- ( TermBytes (..)+ ( TermBytes8 (..)+ , TermBytes16 (..) , StaticBytes (..) , mkStaticBytes , normStaticBytes@@ -28,7 +33,7 @@ import Dahdit.LiftedPrim (LiftedPrim) import Dahdit.LiftedPrimArray (LiftedPrimArray, replicateLiftedPrimArray) import Dahdit.Proxy (proxyForNatF)-import Dahdit.Sizes (ByteCount (..), ByteSized (..), StaticByteSized (..), ViaStaticByteSized (..))+import Dahdit.Sizes (ByteCount (..), StaticByteSized (..), byteSizeViaStatic) import Data.ByteString.Internal (c2w) import qualified Data.ByteString.Short as BSS import Data.ByteString.Short.Internal (ShortByteString (..))@@ -40,7 +45,7 @@ import qualified Data.Sequence as Seq import Data.String (IsString) import Data.Word (Word8)-import GHC.TypeLits (KnownNat, KnownSymbol, Nat, Symbol, natVal, symbolVal)+import GHC.TypeLits (ConsSymbol, KnownNat, KnownSymbol, Nat, Symbol, natVal, symbolVal, type (*), type (+)) getUntilNull :: Get (ByteCount, [Word8]) getUntilNull = go 0 []@@ -55,30 +60,49 @@ mkSBS n bs = let !(ByteArray ba) = byteArrayFromListN (coerce n) bs in SBS ba -- | Bytes terminated with null byte.+newtype TermBytes8 = TermBytes8 {unTermBytes8 :: ShortByteString}+ deriving stock (Show)+ deriving newtype (Eq, Ord, IsString)++instance Default TermBytes8 where+ def = TermBytes8 BSS.empty++instance Binary TermBytes8 where+ byteSize (TermBytes8 sbs) = ByteCount (BSS.length sbs + 1)++ get = do+ (i, acc) <- getUntilNull+ let sbs = mkSBS i acc+ pure (TermBytes8 sbs)++ put (TermBytes8 sbs) = do+ putByteString sbs+ putWord8 0++-- | Bytes terminated with null byte. -- NOTE: Terminated with TWO null bytes if the string is even length -- to align to Word16 boundaries, as required for RIFF format, for example.-newtype TermBytes = TermBytes {unTermBytes :: ShortByteString}+newtype TermBytes16 = TermBytes16 {unTermBytes16 :: ShortByteString} deriving stock (Show) deriving newtype (Eq, Ord, IsString) -instance Default TermBytes where- def = TermBytes BSS.empty+instance Default TermBytes16 where+ def = TermBytes16 BSS.empty -instance ByteSized TermBytes where- byteSize (TermBytes sbs) =- let bc = byteSize sbs + 1+instance Binary TermBytes16 where+ byteSize (TermBytes16 sbs) =+ let bc = ByteCount (BSS.length sbs + 1) in if even bc then bc else bc + 1 -instance Binary TermBytes where get = do (i, acc) <- getUntilNull unless (odd i) $ do w <- getWord8 unless (w == 0) (fail "TermBytes missing word pad") let sbs = mkSBS i acc- pure (TermBytes sbs)+ pure (TermBytes16 sbs) - put (TermBytes sbs) = do+ put (TermBytes16 sbs) = do putByteString sbs putWord8 0 unless (odd (BSS.length sbs)) (putWord8 0)@@ -88,9 +112,7 @@ deriving stock (Show) deriving newtype (IsString) -deriving via (ViaStaticByteSized (StaticBytes n)) instance KnownNat n => ByteSized (StaticBytes n)--mkStaticBytes :: KnownNat n => Proxy n -> ShortByteString -> StaticBytes n+mkStaticBytes :: (KnownNat n) => Proxy n -> ShortByteString -> StaticBytes n mkStaticBytes prox sbs = let n = fromInteger (natVal prox) in if BSS.length sbs == n@@ -103,16 +125,16 @@ then x1 else x1 <> BSS.replicate (n - l) 0 -normStaticBytes :: KnownNat n => StaticBytes n -> StaticBytes n+normStaticBytes :: (KnownNat n) => StaticBytes n -> StaticBytes n normStaticBytes sb@(StaticBytes sbs) = mkStaticBytes (proxyForNatF sb) sbs -instance KnownNat n => Eq (StaticBytes n) where+instance (KnownNat n) => Eq (StaticBytes n) where x == y = let StaticBytes x' = normStaticBytes x StaticBytes y' = normStaticBytes y in x' == y' -instance KnownNat n => Ord (StaticBytes n) where+instance (KnownNat n) => Ord (StaticBytes n) where compare x y = let StaticBytes x' = normStaticBytes x StaticBytes y' = normStaticBytes y@@ -121,25 +143,26 @@ instance Default (StaticBytes n) where def = StaticBytes BSS.empty -instance KnownNat n => StaticByteSized (StaticBytes n) where- staticByteSize _ = fromInteger (natVal (Proxy :: Proxy n))+instance (KnownNat n) => StaticByteSized (StaticBytes n) where+ type StaticSize (StaticBytes n) = n -instance KnownNat n => Binary (StaticBytes n) where+instance (KnownNat n) => Binary (StaticBytes n) where+ byteSize = byteSizeViaStatic get = fmap StaticBytes (getByteString (fromInteger (natVal (Proxy :: Proxy n)))) put fb@(StaticBytes sbs) = putFixedString 0 (fromInteger (natVal fb)) sbs newtype StaticSeq (n :: Nat) a = StaticSeq {unStaticSeq :: Seq a} deriving stock (Show) deriving newtype (Eq, Functor, Foldable)- deriving (ByteSized) via (ViaStaticByteSized (StaticSeq n a)) instance (KnownNat n, Default a) => Default (StaticSeq n a) where def = StaticSeq (Seq.replicate (fromInteger (natVal (Proxy :: Proxy n))) def) instance (KnownNat n, StaticByteSized a) => StaticByteSized (StaticSeq n a) where- staticByteSize _ = fromInteger (natVal (Proxy :: Proxy n)) * staticByteSize (Proxy :: Proxy a)+ type StaticSize (StaticSeq n a) = n * StaticSize a instance (KnownNat n, Binary a, StaticByteSized a, Default a) => Binary (StaticSeq n a) where+ byteSize = byteSizeViaStatic get = fmap StaticSeq (getStaticSeq (fromInteger (natVal (Proxy :: Proxy n))) get) put = unsafePutStaticSeqN (fromInteger (natVal (Proxy :: Proxy n))) (Just def) put . unStaticSeq @@ -147,45 +170,51 @@ deriving stock (Show) deriving newtype (Eq) -deriving via (ViaStaticByteSized (StaticArray n a)) instance (KnownNat n, StaticByteSized a) => ByteSized (StaticArray n a)- instance (KnownNat n, LiftedPrim a, Default a) => Default (StaticArray n a) where def = StaticArray (replicateLiftedPrimArray (fromInteger (natVal (Proxy :: Proxy n))) def) instance (KnownNat n, StaticByteSized a) => StaticByteSized (StaticArray n a) where- staticByteSize _ = fromInteger (natVal (Proxy :: Proxy n)) * staticByteSize (Proxy :: Proxy a)+ type StaticSize (StaticArray n a) = n * StaticSize a instance (KnownNat n, LiftedPrim a, Default a) => Binary (StaticArray n a) where+ byteSize = byteSizeViaStatic get = fmap StaticArray (getStaticArray (fromInteger (natVal (Proxy :: Proxy n)))) put = unsafePutStaticArrayN (fromInteger (natVal (Proxy :: Proxy n))) (Just def) . unStaticArray newtype BoolByte = BoolByte {unBoolByte :: Bool} deriving stock (Show) deriving newtype (Eq)- deriving (ByteSized) via (ViaStaticByteSized BoolByte) instance Default BoolByte where def = BoolByte False instance StaticByteSized BoolByte where+ type StaticSize BoolByte = 1 staticByteSize _ = 1 instance Binary BoolByte where+ byteSize = byteSizeViaStatic get = fmap (BoolByte . (/= 0)) getWord8 put (BoolByte b) = putWord8 (if b then 1 else 0) -newtype ExactBytes (s :: Symbol) = ExactBytes {unExactBytes :: ()}+newtype ExactBytes (n :: Nat) (s :: Symbol) = ExactBytes {unExactBytes :: ()} deriving stock (Show) deriving newtype (Eq)- deriving (ByteSized) via (ViaStaticByteSized (ExactBytes s)) -instance Default (ExactBytes s) where+instance Default (ExactBytes n s) where def = ExactBytes () -instance KnownSymbol s => StaticByteSized (ExactBytes s) where- staticByteSize _ = coerce (length (symbolVal (Proxy :: Proxy s)))+class SymLen (n :: Nat) (s :: Symbol) | s -> n -instance KnownSymbol s => Binary (ExactBytes s) where+instance {-# OVERLAPPING #-} SymLen 0 ""++instance (SymLen n s, m ~ n + 1, t ~ ConsSymbol c s) => SymLen m t++instance (SymLen n s, KnownSymbol s, KnownNat n) => StaticByteSized (ExactBytes n s) where+ type StaticSize (ExactBytes n s) = n++instance (SymLen n s, KnownSymbol s, KnownNat n) => Binary (ExactBytes n s) where+ byteSize = byteSizeViaStatic get = do let s = symbolVal (Proxy :: Proxy s) bc = coerce (length s)
src/Dahdit/Free.hs view
@@ -46,16 +46,18 @@ import Data.Primitive (ByteArray) import Data.Proxy (Proxy (..)) import Data.Sequence (Seq)+import Data.Text (Text)+import qualified Data.Text as T import Data.Word (Word8) data GetStaticSeqF a where- GetStaticSeqF :: StaticByteSized z => !ElemCount -> Get z -> (Seq z -> a) -> GetStaticSeqF a+ GetStaticSeqF :: (StaticByteSized z) => !ElemCount -> Get z -> (Seq z -> a) -> GetStaticSeqF a instance Functor GetStaticSeqF where fmap f (GetStaticSeqF n g k) = GetStaticSeqF n g (f . k) data GetStaticArrayF a where- GetStaticArrayF :: LiftedPrim z => !ElemCount -> Proxy z -> (LiftedPrimArray z -> a) -> GetStaticArrayF a+ GetStaticArrayF :: (LiftedPrim z) => !ElemCount -> Proxy z -> (LiftedPrimArray z -> a) -> GetStaticArrayF a instance Functor GetStaticArrayF where fmap f (GetStaticArrayF n p k) = GetStaticArrayF n p (f . k)@@ -108,23 +110,23 @@ | GetFSkip !ByteCount a | GetFLookAhead !(GetLookAheadF a) | GetFRemainingSize (ByteCount -> a)- | GetFFail !String+ | GetFFail !Text deriving stock (Functor) newtype Get a = Get {unGet :: F GetF a} deriving newtype (Functor, Applicative, Monad) instance MonadFail Get where- fail msg = Get (F (\_ y -> y (GetFFail msg)))+ fail msg = Get (F (\_ y -> y (GetFFail (T.pack msg)))) data PutStaticSeqF a where- PutStaticSeqF :: StaticByteSized z => !ElemCount -> !(Maybe z) -> (z -> Put) -> !(Seq z) -> a -> PutStaticSeqF a+ PutStaticSeqF :: (StaticByteSized z) => !ElemCount -> !(Maybe z) -> (z -> Put) -> !(Seq z) -> a -> PutStaticSeqF a instance Functor PutStaticSeqF where fmap f (PutStaticSeqF n z p s k) = PutStaticSeqF n z p s (f k) data PutStaticArrayF a where- PutStaticArrayF :: LiftedPrim z => !ElemCount -> !(Maybe z) -> !(LiftedPrimArray z) -> a -> PutStaticArrayF a+ PutStaticArrayF :: (LiftedPrim z) => !ElemCount -> !(Maybe z) -> !(LiftedPrimArray z) -> a -> PutStaticArrayF a instance Functor PutStaticArrayF where fmap f (PutStaticArrayF n z a k) = PutStaticArrayF n z a (f k)
src/Dahdit/Funs.hs view
@@ -21,6 +21,7 @@ , getInt64BE , getFloatBE , getDoubleBE+ , getText , getByteString , getSkip , getExact@@ -63,6 +64,7 @@ , putInt64BE , putFloatBE , putDoubleBE+ , putText , putByteString , putFixedString , putList@@ -77,7 +79,7 @@ ) where -import Control.Monad (replicateM_, unless)+import Control.Monad (replicateM_, unless, (>=>)) import Control.Monad.Free.Church (F (..)) import Dahdit.Free ( Get (..)@@ -130,6 +132,8 @@ import Data.Proxy (Proxy (..)) import Data.Sequence (Seq (..)) import qualified Data.Sequence as Seq+import Data.Text (Text)+import qualified Data.Text.Encoding as TE import Data.Word (Word8) getWord8 :: Get Word8@@ -198,6 +202,9 @@ getDoubleBE :: Get DoubleBE getDoubleBE = Get (F (\x y -> y (GetFDoubleBE x))) +getText :: ByteCount -> Get Text+getText = getByteString >=> either (fail . ("Invalid UTF-8: " ++) . show) pure . TE.decodeUtf8' . BSS.fromShort+ getByteString :: ByteCount -> Get ShortByteString getByteString bc = Get (F (\x y -> y (GetFShortByteString bc x))) @@ -233,17 +240,17 @@ go (acc :|> x) (i + 1) -- | Get Seq of statically-sized elements-getStaticSeq :: StaticByteSized a => ElemCount -> Get a -> Get (Seq a)+getStaticSeq :: (StaticByteSized a) => ElemCount -> Get a -> Get (Seq a) getStaticSeq n g = Get (F (\x y -> y (GetFStaticSeq (GetStaticSeqF n g x)))) -- | Get PrimArray of statically-sized elements-getStaticArray :: LiftedPrim a => ElemCount -> Get (LiftedPrimArray a)+getStaticArray :: (LiftedPrim a) => ElemCount -> Get (LiftedPrimArray a) getStaticArray n = Get (F (\x y -> y (GetFStaticArray (GetStaticArrayF n (Proxy :: Proxy a) x)))) getByteArray :: ByteCount -> Get ByteArray getByteArray bc = Get (F (\x y -> y (GetFByteArray bc x))) -getLiftedPrimArray :: LiftedPrim a => Proxy a -> ElemCount -> Get (LiftedPrimArray a)+getLiftedPrimArray :: (LiftedPrim a) => Proxy a -> ElemCount -> Get (LiftedPrimArray a) getLiftedPrimArray prox ec = let bc = staticByteSize prox * coerce ec in fmap LiftedPrimArray (getByteArray bc)@@ -268,7 +275,7 @@ x <- g go (acc :|> x) -getRemainingStaticSeq :: StaticByteSized a => Get a -> Get (Seq a)+getRemainingStaticSeq :: (StaticByteSized a) => Get a -> Get (Seq a) getRemainingStaticSeq g = do let ebc = staticByteSize (proxyForF g) bc <- getRemainingSize@@ -277,7 +284,7 @@ then getStaticSeq (coerce (div bc ebc)) g else fail ("Leftover bytes for remaining static seq (have " ++ show (unByteCount left) ++ ", need " ++ show (unByteCount ebc) ++ ")") -getRemainingStaticArray :: LiftedPrim a => Proxy a -> Get (LiftedPrimArray a)+getRemainingStaticArray :: (LiftedPrim a) => Proxy a -> Get (LiftedPrimArray a) getRemainingStaticArray prox = do let ebc = staticByteSize prox bc <- getRemainingSize@@ -289,7 +296,7 @@ getRemainingByteArray :: Get ByteArray getRemainingByteArray = getRemainingSize >>= getByteArray -getRemainingLiftedPrimArray :: LiftedPrim a => Proxy a -> Get (LiftedPrimArray a)+getRemainingLiftedPrimArray :: (LiftedPrim a) => Proxy a -> Get (LiftedPrimArray a) getRemainingLiftedPrimArray prox = do let ebc = staticByteSize prox bc <- getRemainingSize@@ -380,6 +387,9 @@ putDoubleBE :: DoubleBE -> Put putDoubleBE d = PutM (F (\x y -> y (PutFDoubleBE d (x ())))) +putText :: Text -> Put+putText = putByteString . BSS.toShort . TE.encodeUtf8+ putByteString :: ShortByteString -> Put putByteString sbs = let bc = coerce (BSS.length sbs)@@ -405,21 +415,21 @@ putSeq = traverse_ -- | Put Seq of statically-sized elements-putStaticSeq :: StaticByteSized a => (a -> Put) -> Seq a -> Put+putStaticSeq :: (StaticByteSized a) => (a -> Put) -> Seq a -> Put putStaticSeq p s = let n = coerce (Seq.length s) in unsafePutStaticSeqN n Nothing p s -unsafePutStaticSeqN :: StaticByteSized a => ElemCount -> Maybe a -> (a -> Put) -> Seq a -> Put+unsafePutStaticSeqN :: (StaticByteSized a) => ElemCount -> Maybe a -> (a -> Put) -> Seq a -> Put unsafePutStaticSeqN n mz p s = PutM (F (\x y -> y (PutFStaticSeq (PutStaticSeqF n mz p s (x ()))))) -- | Put Array of statically-sized elements-putStaticArray :: LiftedPrim a => LiftedPrimArray a -> Put+putStaticArray :: (LiftedPrim a) => LiftedPrimArray a -> Put putStaticArray a = let ec = lengthLiftedPrimArray a in unsafePutStaticArrayN ec Nothing a -unsafePutStaticArrayN :: LiftedPrim a => ElemCount -> Maybe a -> LiftedPrimArray a -> Put+unsafePutStaticArrayN :: (LiftedPrim a) => ElemCount -> Maybe a -> LiftedPrimArray a -> Put unsafePutStaticArrayN n mz a = PutM (F (\x y -> y (PutFStaticArray (PutStaticArrayF n mz a (x ()))))) putByteArray :: ByteArray -> Put@@ -430,7 +440,7 @@ putLiftedPrimArray :: LiftedPrimArray a -> Put putLiftedPrimArray = putByteArray . unLiftedPrimArray -putStaticHint :: StaticByteSized a => (a -> Put) -> a -> Put+putStaticHint :: (StaticByteSized a) => (a -> Put) -> a -> Put putStaticHint p a = let bc = staticByteSize (proxyForFun p) in PutM (F (\x y -> y (PutFStaticHint (PutStaticHintF bc (p a) (x ())))))
src/Dahdit/Generic.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE UndecidableInstances #-}+{-# OPTIONS_GHC -fplugin GHC.TypeLits.KnownNat.Solver #-} module Dahdit.Generic ( ViaGeneric (..)@@ -11,19 +12,35 @@ import Dahdit.Free (Get, Put) import Dahdit.Funs (putStaticHint) import Dahdit.Nums (Word16LE, Word32LE)-import Dahdit.Sizes (ByteCount, ByteSized (..), StaticByteSized (..))+import Dahdit.Proxy (proxyForRepF)+import Dahdit.Sizes (ByteCount, StaticByteSized (..)) import Data.Bits (Bits (..)) import Data.Kind (Type) import Data.Proxy (Proxy (..)) import Data.Word (Word8) import GHC.Generics (C1, Generic (..), K1 (..), M1 (..), U1 (..), (:*:) (..), (:+:) (..))+import GHC.TypeLits (KnownNat, Nat, natVal, type (+)) --- | Use: deriving (ByteSized, Binary) via (ViaGeneric Foo)+-- | Use: deriving (Binary) via (ViaGeneric Foo) newtype ViaGeneric a = ViaGeneric {unViaGeneric :: a} --- | Use: deriving (ByteSized, StaticByteSized, Binary) via (ViaStaticGeneric Foo)+instance (Generic t, GByteSized (Rep t), GBinary (Rep t)) => Binary (ViaGeneric t) where+ byteSize = gbyteSize . from . unViaGeneric+ get = fmap (ViaGeneric . to) gget+ put = gput . from . unViaGeneric++-- | Use: deriving (StaticByteSized, Binary) via (ViaStaticGeneric Foo) newtype ViaStaticGeneric a = ViaStaticGeneric {unViaStaticGeneric :: a} +instance (Generic t, GStaticByteSized (Rep t), GBinary (Rep t)) => Binary (ViaStaticGeneric t) where+ byteSize sg = gstaticByteSize (proxyForRepF sg (from (unViaStaticGeneric sg)))+ get = fmap (ViaStaticGeneric . to) gget+ put = putStaticHint (gput . from . unViaStaticGeneric)++instance (GStaticByteSized (Rep t)) => StaticByteSized (ViaStaticGeneric t) where+ type StaticSize (ViaStaticGeneric t) = GStaticSize (Rep t)+ staticByteSize _ = gstaticByteSize (Proxy :: Proxy (Rep t))+ -- ByteSized: class GByteSized f where@@ -34,11 +51,11 @@ gbyteSize _ = 0 -- Product-instance (GByteSized a, GByteSized b) => GByteSized (a :*: b) where+instance (GByteSized a, GByteSized b, o ~ n + m) => GByteSized (a :*: b) where gbyteSize (x :*: y) = gbyteSize x + gbyteSize y -- Metadata-instance GByteSized a => GByteSized (M1 i c a) where+instance (GByteSized a) => GByteSized (M1 i c a) where gbyteSize = gbyteSize . unM1 -- Sum@@ -49,34 +66,35 @@ R1 b -> gbyteSize b -- Field-instance ByteSized a => GByteSized (K1 i a) where+instance (Binary a) => GByteSized (K1 i a) where gbyteSize = byteSize . unK1 -instance (Generic t, GByteSized (Rep t)) => ByteSized (ViaGeneric t) where- byteSize = gbyteSize . from . unViaGeneric--instance (Generic t, GByteSized (Rep t)) => ByteSized (ViaStaticGeneric t) where- byteSize = gbyteSize . from . unViaStaticGeneric- -- StaticByteSized: -class GByteSized f => GStaticByteSized (f :: Type -> Type) where+class (KnownNat (GStaticSize f)) => GStaticByteSized (f :: Type -> Type) where+ type GStaticSize f :: Nat gstaticByteSize :: Proxy f -> ByteCount+ gstaticByteSize = fromInteger . natVal . gstaticByteProxy +gstaticByteProxy :: Proxy f -> Proxy (GStaticSize f)+gstaticByteProxy _ = Proxy+ instance GStaticByteSized U1 where- gstaticByteSize _ = 0+ type GStaticSize U1 = 0 instance (GStaticByteSized a, GStaticByteSized b) => GStaticByteSized (a :*: b) where- gstaticByteSize _ = gstaticByteSize (Proxy :: Proxy a) + gstaticByteSize (Proxy :: Proxy b)+ type GStaticSize (a :*: b) = GStaticSize a + GStaticSize b -instance GStaticByteSized a => GStaticByteSized (M1 i c a) where- gstaticByteSize _ = gstaticByteSize (Proxy :: Proxy a)+instance (GStaticByteSized a) => GStaticByteSized (M1 i c a) where+ type GStaticSize (M1 i c a) = GStaticSize a -instance StaticByteSized a => GStaticByteSized (K1 i a) where- gstaticByteSize _ = staticByteSize (Proxy :: Proxy a)+-- GHC BUG: KnownNat is not actually redundant+instance (StaticByteSized a) => GStaticByteSized (K1 i a) where+ type GStaticSize (K1 i a) = StaticSize a -instance (Generic t, GStaticByteSized (Rep t)) => StaticByteSized (ViaStaticGeneric t) where- staticByteSize _ = gstaticByteSize (Proxy :: Proxy (Rep t))+-- This one line is the reason all the nat constraints are threaded through this codebase+instance (GStaticByteSized a, GStaticByteSized b, GStaticSize a ~ GStaticSize b) => GStaticByteSized (a :+: b) where+ type GStaticSize (a :+: b) = GStaticSize a -- Binary: @@ -92,22 +110,14 @@ gget = liftA2 (:*:) gget gget gput (x :*: y) = gput x *> gput y -instance GBinary a => GBinary (M1 i c a) where+instance (GBinary a) => GBinary (M1 i c a) where gget = fmap M1 gget gput = gput . unM1 -instance Binary a => GBinary (K1 i a) where+instance (Binary a) => GBinary (K1 i a) where gget = fmap K1 get gput = put . unK1 -instance (Generic t, GBinary (Rep t)) => Binary (ViaGeneric t) where- get = fmap (ViaGeneric . to) gget- put = gput . from . unViaGeneric--instance (Generic t, GStaticByteSized (Rep t), GBinary (Rep t)) => Binary (ViaStaticGeneric t) where- get = fmap (ViaStaticGeneric . to) gget- put = putStaticHint (gput . from . unViaStaticGeneric)- -- Everything that follows is borrowed from the binary package, which -- borrows from the cereal package! @@ -141,7 +151,7 @@ where size = unTagged (sumSize :: Tagged (a :+: b)) -sizeError :: Show size => String -> size -> error+sizeError :: (Show size) => String -> size -> error sizeError s size = error ("Can't " ++ s ++ " a type with " ++ show size ++ " constructors") checkGetSum@@ -172,7 +182,7 @@ sizeL = size `shiftR` 1 sizeR = size - sizeL -instance GBinary a => GSumBinary (C1 c a) where+instance (GBinary a) => GSumBinary (C1 c a) where getSum _ _ = gget putSum !code _ x = put code <> gput x @@ -187,7 +197,7 @@ instance SumSize (C1 c a) where sumSize = Tagged 1 -sumSizeFor :: SumSize f => f a -> Tagged f+sumSizeFor :: (SumSize f) => f a -> Tagged f sumSizeFor = const sumSize taggedBytes :: Tagged f -> ByteCount@@ -197,5 +207,5 @@ | size - 1 <= (maxBound :: Word32LE) = 4 | otherwise = sizeError "size" size -sumSizeBytes :: SumSize f => f a -> ByteCount+sumSizeBytes :: (SumSize f) => f a -> ByteCount sumSizeBytes = taggedBytes . sumSizeFor
src/Dahdit/Iface.hs view
@@ -1,141 +1,252 @@ module Dahdit.Iface- ( BinaryTarget (..)+ ( BinaryGetTarget (..) , getTarget+ , BinaryPutTarget (..) , putTarget- , MutBinaryTarget (..)+ , MutBinaryPutTarget (..) , mutPutTargetOffset , mutPutTarget+ , getEnd , decode+ , decodeInc+ , decodeEnd , decodeFile+ , decodeFileEnd , encode , encodeFile , mutEncode ) where -import Control.Monad.Primitive (PrimBase, PrimMonad (..))-import Control.Monad.ST (runST)+import Control.Monad (unless, (>=>))+import Control.Monad.Primitive (MonadPrim, PrimMonad (..), RealWorld) import Dahdit.Binary (Binary (..)) import Dahdit.Free (Get, Put)-import Dahdit.Mem (allocBAMem, allocPtrMem, freezeBAMem, freezeBSMem, freezeSBSMem, freezeVecMem, mutAllocBAMem, mutAllocVecMem, mutFreezeBAMem, mutFreezeVecMem, viewBSMem, viewSBSMem, viewVecMem)-import Dahdit.Run (GetError, runCount, runGetInternal, runPutInternal)-import Dahdit.Sizes (ByteCount (..), ByteSized (..))+import Dahdit.Funs (getRemainingSize)+import Dahdit.Mem (MemPtr (..), MutableMem (..), emptyMemPtr, mutViewVecMem, viewBSMem, viewSBSMem, viewVecMem, withBAMem, withBSMem, withSBSMem, withVecMem)+import Dahdit.Run (GetError, GetIncCb, GetIncChunk (..), newGetIncEnv, runCount, runGetIncInternal, runGetInternal, runPutInternal)+import Dahdit.Sizes (ByteCount (..)) import Data.ByteString (ByteString) import qualified Data.ByteString as BS+import qualified Data.ByteString.Char8 as BSC import Data.ByteString.Short (ShortByteString)-import qualified Data.ByteString.Short as BSS import Data.Coerce (coerce)-import Data.Primitive.ByteArray (ByteArray, MutableByteArray, sizeofByteArray)+import Data.Primitive.ByteArray (ByteArray, MutableByteArray, emptyByteArray, sizeofByteArray)+import Data.Text (Text)+import qualified Data.Text.Encoding as TE import Data.Vector.Storable (Vector) import qualified Data.Vector.Storable as VS-import Data.Vector.Storable.Mutable (MVector)+import Data.Vector.Storable.Mutable (IOVector) import Data.Word (Word8) --- | Abstracts over the sources we can read from / sinks we can render to.-class BinaryTarget z where- -- | Put an action to the sink with the given length.- -- Prefer 'putTarget' to safely count capacity, or use 'encode' to use byte size.- putTargetUnsafe :: Put -> ByteCount -> z-+-- | Abstracts over the sources we can read from.+class (PrimMonad m) => BinaryGetTarget z m where -- | Get a value from the source given a starting offset, returning a result and final offset. -- On error, the offset will indicate where in the source the error occurred.- getTargetOffset :: ByteCount -> Get a -> z -> (Either GetError a, ByteCount)+ getTargetOffset :: ByteCount -> Get a -> z -> m (Either GetError a, ByteCount) + -- | Get a value incrementally from sources yielded by the given callback, returning a+ -- result, final offset in the whole stream, and final offset in the current chunk.+ -- Takes an optional maximum capacity.+ getTargetInc :: Maybe ByteCount -> Get a -> GetIncCb z m -> m (Either GetError a, ByteCount, ByteCount)+ -- | Get a value from the source, returning a result and final offset.-getTarget :: BinaryTarget z => Get a -> z -> (Either GetError a, ByteCount)+getTarget :: (BinaryGetTarget z m) => Get a -> z -> m (Either GetError a, ByteCount) getTarget = getTargetOffset 0 +-- | Abstracts over the immutable sinks we can render to.+class (BinaryGetTarget z m) => BinaryPutTarget z m where+ -- | Put an action to the sink with the given length.+ -- Prefer 'putTarget' to safely count capacity, or use 'encode' to use byte size.+ putTargetUnsafe :: Put -> ByteCount -> m z+ -- | Put an action to the sink with calculated capacity.-putTarget :: BinaryTarget z => Put -> z+putTarget :: (BinaryPutTarget z m) => Put -> m z putTarget p = putTargetUnsafe p (runCount p) -class MutBinaryTarget m z where+class (BinaryGetTarget z m) => MutBinaryPutTarget z m where mutPutTargetOffsetUnsafe :: ByteCount -> Put -> ByteCount -> z -> m ByteCount -mutPutTargetOffset :: MutBinaryTarget m z => ByteCount -> Put -> z -> m ByteCount+mutPutTargetOffset :: (MutBinaryPutTarget z m) => ByteCount -> Put -> z -> m ByteCount mutPutTargetOffset off p = mutPutTargetOffsetUnsafe off p (runCount p) -mutPutTarget :: MutBinaryTarget m z => Put -> z -> m ByteCount+mutPutTarget :: (MutBinaryPutTarget z m) => Put -> z -> m ByteCount mutPutTarget = mutPutTargetOffset 0 -instance BinaryTarget ShortByteString where+instance BinaryGetTarget String IO where+ getTargetOffset = runGetString+ getTargetInc = runGetIncString++instance BinaryPutTarget String IO where+ putTargetUnsafe = runPutString++instance BinaryGetTarget Text IO where+ getTargetOffset = runGetText+ getTargetInc = runGetIncText++instance BinaryPutTarget Text IO where+ putTargetUnsafe = runPutText++instance (PrimMonad m) => BinaryGetTarget ShortByteString m where getTargetOffset = runGetSBS+ getTargetInc = runGetIncSBS++instance (PrimMonad m) => BinaryPutTarget ShortByteString m where putTargetUnsafe = runPutSBS -instance BinaryTarget ByteString where+instance BinaryGetTarget ByteString IO where getTargetOffset = runGetBS+ getTargetInc = runGetIncBS++instance BinaryPutTarget ByteString IO where putTargetUnsafe = runPutBS -instance BinaryTarget ByteArray where+instance (PrimMonad m) => BinaryGetTarget ByteArray m where getTargetOffset = runGetBA+ getTargetInc = runGetIncBA++instance (PrimMonad m) => BinaryPutTarget ByteArray m where putTargetUnsafe = runPutBA -instance BinaryTarget (Vector Word8) where+instance BinaryGetTarget (Vector Word8) IO where getTargetOffset = runGetVec+ getTargetInc = runGetIncVec++instance BinaryPutTarget (Vector Word8) IO where putTargetUnsafe = runPutVec -instance (PrimBase m, s ~ PrimState m) => MutBinaryTarget m (MutableByteArray s) where+instance (MonadPrim s m) => BinaryGetTarget (MutableByteArray s) m where+ getTargetOffset bc g z = unsafeUseFrozenMem z (getTargetOffset bc g)+ getTargetInc mbc g cb = getTargetInc mbc g (cb >=> maybe (pure Nothing) (fmap Just . unsafeFreezeMem))++instance (MonadPrim s m) => MutBinaryPutTarget (MutableByteArray s) m where mutPutTargetOffsetUnsafe = runMutPutBA -instance (PrimBase m, s ~ PrimState m) => MutBinaryTarget m (MVector s Word8) where+instance BinaryGetTarget (IOVector Word8) IO where+ getTargetOffset bc g z = unsafeUseFrozenMem z (getTargetOffset bc g)+ getTargetInc mbc g cb = getTargetInc mbc g (cb >=> maybe (pure Nothing) (fmap Just . unsafeFreezeMem))++instance MutBinaryPutTarget (IOVector Word8) IO where mutPutTargetOffsetUnsafe = runMutPutVec +-- | Wrapper that asserts a get action has consumed to the end.+getEnd :: Get a -> Get a+getEnd getter = do+ a <- getter+ b <- getRemainingSize+ unless (b == 0) (fail ("Expected end of input but had bytes remaining: " ++ show (unByteCount b)))+ pure a+ -- | Decode a value from a source returning a result and consumed byte count.-decode :: (Binary a, BinaryTarget z) => z -> (Either GetError a, ByteCount)+decode :: (Binary a, BinaryGetTarget z m) => z -> m (Either GetError a, ByteCount) decode = getTarget get +-- | Decode a value incrementally from sources yielded by a callback.+decodeInc :: (Binary a, BinaryGetTarget z m) => Maybe ByteCount -> GetIncCb z m -> m (Either GetError a, ByteCount, ByteCount)+decodeInc mayCap = getTargetInc mayCap get++-- | 'decode' but expect the end of input.+decodeEnd :: (Binary a, BinaryGetTarget z m) => z -> m (Either GetError a, ByteCount)+decodeEnd = getTarget (getEnd get)+ -- | Decode a value from a file.-decodeFile :: Binary a => FilePath -> IO (Either GetError a, ByteCount)+decodeFile :: (Binary a) => FilePath -> IO (Either GetError a, ByteCount) decodeFile = runGetFile get +-- | 'decodeFile' but expect the end of file.+decodeFileEnd :: (Binary a) => FilePath -> IO (Either GetError a, ByteCount)+decodeFileEnd = runGetFile (getEnd get)+ -- | Encode a value to a sink.-encode :: (Binary a, ByteSized a, BinaryTarget z) => a -> z+encode :: (Binary a, BinaryPutTarget z m) => a -> m z encode a = putTargetUnsafe (put a) (byteSize a) -- | Encode a value to a file.-encodeFile :: (Binary a, ByteSized a) => a -> FilePath -> IO ()+encodeFile :: (Binary a) => a -> FilePath -> IO () encodeFile a = runPutFile (put a) (byteSize a) -- | Encode a value to a mutable buffer, returning number of bytes filled.-mutEncode :: (Binary a, ByteSized a, MutBinaryTarget m z) => a -> z -> m ByteCount+mutEncode :: (Binary a, MutBinaryPutTarget z m) => a -> z -> m ByteCount mutEncode a = mutPutTargetOffsetUnsafe 0 (put a) (byteSize a) -runGetBA :: ByteCount -> Get a -> ByteArray -> (Either GetError a, ByteCount)+runGetString :: ByteCount -> Get a -> String -> IO (Either GetError a, ByteCount)+runGetString off act = runGetBS off act . BSC.pack++runGetText :: ByteCount -> Get a -> Text -> IO (Either GetError a, ByteCount)+runGetText off act = runGetBS off act . TE.encodeUtf8++runGetBA :: (PrimMonad m) => ByteCount -> Get a -> ByteArray -> m (Either GetError a, ByteCount) runGetBA off act ba = runGetInternal off act (coerce (sizeofByteArray ba)) ba -runGetSBS :: ByteCount -> Get a -> ShortByteString -> (Either GetError a, ByteCount)-runGetSBS off act sbs = runGetInternal off act (coerce (BSS.length sbs)) (viewSBSMem sbs)+runGetSBS :: (PrimMonad m) => ByteCount -> Get a -> ShortByteString -> m (Either GetError a, ByteCount)+runGetSBS off act = runGetBA off act . viewSBSMem -runGetBS :: ByteCount -> Get a -> ByteString -> (Either GetError a, ByteCount)+runGetBS :: ByteCount -> Get a -> ByteString -> IO (Either GetError a, ByteCount) runGetBS off act bs = runGetInternal off act (coerce (BS.length bs)) (viewBSMem bs) -runGetVec :: ByteCount -> Get a -> Vector Word8 -> (Either GetError a, ByteCount)+runGetVec :: ByteCount -> Get a -> Vector Word8 -> IO (Either GetError a, ByteCount) runGetVec off act vec = runGetInternal off act (coerce (VS.length vec)) (viewVecMem vec) runGetFile :: Get a -> FilePath -> IO (Either GetError a, ByteCount) runGetFile act fp = do bs <- BS.readFile fp- pure (runGetBS 0 act bs)+ runGetBS 0 act bs -runPutBA :: Put -> ByteCount -> ByteArray-runPutBA act len = runST (runPutInternal 0 act len allocBAMem freezeBAMem)+runGetIncString :: Maybe ByteCount -> Get a -> GetIncCb String IO -> IO (Either GetError a, ByteCount, ByteCount)+runGetIncString mayCap g cb = runGetIncBS mayCap g (fmap (fmap BSC.pack) . cb) -runPutSBS :: Put -> ByteCount -> ShortByteString-runPutSBS act len = runST (runPutInternal 0 act len allocBAMem freezeSBSMem)+runGetIncText :: Maybe ByteCount -> Get a -> GetIncCb Text IO -> IO (Either GetError a, ByteCount, ByteCount)+runGetIncText mayCap g cb = runGetIncBS mayCap g (fmap (fmap TE.encodeUtf8) . cb) -runPutBS :: Put -> ByteCount -> ByteString-runPutBS act len = runST (runPutInternal 0 act len allocPtrMem freezeBSMem)+runGetIncBA :: (PrimMonad m) => Maybe ByteCount -> Get a -> GetIncCb ByteArray m -> m (Either GetError a, ByteCount, ByteCount)+runGetIncBA mayCap act cb = do+ env <- newGetIncEnv mayCap (GetIncChunk 0 0 emptyByteArray)+ let view s = GetIncChunk 0 (coerce (sizeofByteArray s)) s+ let cb' = fmap (fmap view) . cb+ runGetIncInternal act env cb' -runPutVec :: Put -> ByteCount -> Vector Word8-runPutVec act len = runST (runPutInternal 0 act len allocPtrMem freezeVecMem)+runGetIncSBS :: (PrimMonad m) => Maybe ByteCount -> Get a -> GetIncCb ShortByteString m -> m (Either GetError a, ByteCount, ByteCount)+runGetIncSBS mayCap act cb = runGetIncBA mayCap act (fmap (fmap viewSBSMem) . cb) +runGetIncMemPtr :: Maybe ByteCount -> Get a -> GetIncCb (MemPtr RealWorld) IO -> IO (Either GetError a, ByteCount, ByteCount)+runGetIncMemPtr mayCap act cb = do+ mem <- emptyMemPtr+ env <- newGetIncEnv mayCap (GetIncChunk 0 0 mem)+ let view mem'@(MemPtr _ off len) = GetIncChunk 0 (len - off) mem'+ let cb' = fmap (fmap view) . cb+ runGetIncInternal act env cb'++runGetIncBS :: Maybe ByteCount -> Get a -> GetIncCb ByteString IO -> IO (Either GetError a, ByteCount, ByteCount)+runGetIncBS mayCap act cb = runGetIncMemPtr mayCap act (fmap (fmap viewBSMem) . cb)++runGetIncVec :: Maybe ByteCount -> Get a -> GetIncCb (Vector Word8) IO -> IO (Either GetError a, ByteCount, ByteCount)+runGetIncVec mayCap act cb = runGetIncMemPtr mayCap act (fmap (fmap viewVecMem) . cb)++runPutString :: Put -> ByteCount -> IO String+runPutString act len = fmap BSC.unpack (runPutBS act len)++runPutText :: Put -> ByteCount -> IO Text+runPutText act len = fmap TE.decodeUtf8 (runPutBS act len)++runPutBA :: (PrimMonad m) => Put -> ByteCount -> m ByteArray+runPutBA act len = withBAMem len (runPutInternal 0 act len)++runPutSBS :: (PrimMonad m) => Put -> ByteCount -> m ShortByteString+runPutSBS act len = withSBSMem len (runPutInternal 0 act len)++runPutBS :: Put -> ByteCount -> IO ByteString+runPutBS act len = withBSMem len (runPutInternal 0 act len)++runPutVec :: Put -> ByteCount -> IO (Vector Word8)+runPutVec act len = withVecMem len (runPutInternal 0 act len)+ runPutFile :: Put -> ByteCount -> FilePath -> IO ()-runPutFile act cap fp =- let bs = runPutBS act cap- in BS.writeFile fp bs+runPutFile act cap fp = do+ bs <- runPutBS act cap+ BS.writeFile fp bs -runMutPutBA :: PrimBase m => ByteCount -> Put -> ByteCount -> MutableByteArray (PrimState m) -> m ByteCount-runMutPutBA off act len marr = runPutInternal off act len (mutAllocBAMem marr) mutFreezeBAMem+runMutPutBA :: (MonadPrim s m) => ByteCount -> Put -> ByteCount -> MutableByteArray s -> m ByteCount+runMutPutBA = runPutInternal -runMutPutVec :: PrimBase m => ByteCount -> Put -> ByteCount -> MVector (PrimState m) Word8 -> m ByteCount-runMutPutVec off act len mvec = runPutInternal off act len (mutAllocVecMem mvec) mutFreezeVecMem+runMutPutVec :: ByteCount -> Put -> ByteCount -> IOVector Word8 -> IO ByteCount+runMutPutVec off act len mvec = runPutInternal off act len (mutViewVecMem mvec)
src/Dahdit/Internal.hs view
@@ -5,15 +5,16 @@ import Data.ShortWord (Int24, Word24) import Data.Word (Word16, Word32, Word64, Word8) import GHC.Float (castDoubleToWord64, castFloatToWord32, castWord32ToFloat, castWord64ToDouble)+import GHC.TypeLits (Nat) -newtype ViaFromIntegral x y = ViaFromIntegral {unViaFromIntegral :: y}+newtype ViaFromIntegral (n :: Nat) x y = ViaFromIntegral {unViaFromIntegral :: y} deriving newtype (Num) -- Types that can swap endianness - swapEndian is its own inverse-class Num w => SwapEndian w where+class (Num w) => SwapEndian w where swapEndian :: w -> w -instance (SwapEndian x, Integral x, Integral y) => SwapEndian (ViaFromIntegral x y) where+instance (SwapEndian x, Integral x, Integral y) => SwapEndian (ViaFromIntegral n x y) where swapEndian = ViaFromIntegral . fromIntegral @x @y . swapEndian . fromIntegral @y @x . unViaFromIntegral instance SwapEndian Word8 where@@ -27,28 +28,28 @@ let (!b0, !b1) = unMkWord16LE w in mkWord16LE b1 b0 -deriving via (ViaFromIntegral Word16 Int16) instance SwapEndian Int16+deriving via (ViaFromIntegral n Word16 Int16) instance SwapEndian Int16 instance SwapEndian Word24 where swapEndian w = let (!b0, !b1, !b2) = unMkWord24LE w in mkWord24LE b2 b1 b0 -deriving via (ViaFromIntegral Word24 Int24) instance SwapEndian Int24+deriving via (ViaFromIntegral n Word24 Int24) instance SwapEndian Int24 instance SwapEndian Word32 where swapEndian w = let (!b0, !b1, !b2, !b3) = unMkWord32LE w in mkWord32LE b3 b2 b1 b0 -deriving via (ViaFromIntegral Word32 Int32) instance SwapEndian Int32+deriving via (ViaFromIntegral n Word32 Int32) instance SwapEndian Int32 instance SwapEndian Word64 where swapEndian w = let (!b0, !b1, !b2, !b3, !b4, !b5, !b6, !b7) = unMkWord64LE w in mkWord64LE b7 b6 b5 b4 b3 b2 b1 b0 -deriving via (ViaFromIntegral Word64 Int64) instance SwapEndian Int64+deriving via (ViaFromIntegral n Word64 Int64) instance SwapEndian Int64 instance SwapEndian Float where swapEndian w =@@ -128,16 +129,16 @@ unMkDoubleLE :: Double -> (Word8, Word8, Word8, Word8, Word8, Word8, Word8, Word8) unMkDoubleLE f = unMkWord64LE (castDoubleToWord64 f) -class (Num le, Num be) => EndianPair le be | le -> be, be -> le where+class (Num le, Num be) => EndianPair (n :: Nat) le be | le -> n, be -> n, le -> be, be -> le where toLittleEndian :: be -> le toBigEndian :: le -> be -newtype ViaEndianPair le be = ViaEndianPair {unViaEndianPair :: be}+newtype ViaEndianPair (n :: Nat) le be = ViaEndianPair {unViaEndianPair :: be} -instance EndianPair Word8 Word8 where+instance EndianPair 1 Word8 Word8 where toLittleEndian = id toBigEndian = id -instance EndianPair Int8 Int8 where+instance EndianPair 1 Int8 Int8 where toLittleEndian = id toBigEndian = id
src/Dahdit/LiftedPrim.hs view
@@ -52,13 +52,13 @@ -- | This is a stripped-down version of 'Prim' that is possible for a human to implement. -- It's all about reading and writing structures from lifted byte arrays and pointers.-class StaticByteSized a => LiftedPrim a where+class (StaticByteSized a) => LiftedPrim a where indexArrayLiftedInBytes :: ByteArray -> ByteCount -> a- writeArrayLiftedInBytes :: PrimMonad m => MutableByteArray (PrimState m) -> ByteCount -> a -> m ()+ writeArrayLiftedInBytes :: (PrimMonad m) => MutableByteArray (PrimState m) -> ByteCount -> a -> m () indexPtrLiftedInBytes :: Ptr Word8 -> ByteCount -> a- writePtrLiftedInBytes :: PrimMonad m => Ptr Word8 -> ByteCount -> a -> m ()+ writePtrLiftedInBytes :: (PrimMonad m) => Ptr Word8 -> ByteCount -> a -> m () -indexArrayLiftedInElems :: LiftedPrim a => Proxy a -> ByteArray -> ElemCount -> a+indexArrayLiftedInElems :: (LiftedPrim a) => Proxy a -> ByteArray -> ElemCount -> a indexArrayLiftedInElems prox arr pos = indexArrayLiftedInBytes arr (coerce pos * staticByteSize prox) @@ -66,7 +66,7 @@ writeArrayLiftedInElems arr pos val = writeArrayLiftedInBytes arr (coerce pos * staticByteSize (proxyFor val)) val -indexPtrLiftedInElems :: LiftedPrim a => Proxy a -> Ptr Word8 -> ElemCount -> a+indexPtrLiftedInElems :: (LiftedPrim a) => Proxy a -> Ptr Word8 -> ElemCount -> a indexPtrLiftedInElems prox ptr pos = indexPtrLiftedInBytes ptr (coerce pos * staticByteSize prox) @@ -87,7 +87,7 @@ writePtrLiftedInBytes ptr = writeOffPtr (coerce ptr) . coerce -- | NOTE: Relies on same byte width of both types!-instance (Integral x, LiftedPrim x, Integral y) => LiftedPrim (ViaFromIntegral x y) where+instance (Integral x, LiftedPrim x, Integral y, n ~ StaticSize x) => LiftedPrim (ViaFromIntegral n x y) where indexArrayLiftedInBytes arr off = ViaFromIntegral (fromIntegral (indexArrayLiftedInBytes arr off :: x)) writeArrayLiftedInBytes arr off val = let x = fromIntegral (unViaFromIntegral val) :: x in writeArrayLiftedInBytes arr off x indexPtrLiftedInBytes ptr = ViaFromIntegral . fromIntegral @x @y . indexPtrLiftedInBytes ptr@@ -287,39 +287,39 @@ *> writeOffPtr ptr (coerce off + 6) b6 *> writeOffPtr ptr (coerce off + 7) b7 -instance (LiftedPrim le, EndianPair le be) => LiftedPrim (ViaEndianPair le be) where+instance (LiftedPrim le, EndianPair n le be, n ~ StaticSize le) => LiftedPrim (ViaEndianPair n le be) where indexArrayLiftedInBytes arr off = ViaEndianPair (toBigEndian (indexArrayLiftedInBytes arr off)) writeArrayLiftedInBytes arr off = writeArrayLiftedInBytes arr off . toLittleEndian . unViaEndianPair indexPtrLiftedInBytes ptr off = ViaEndianPair (toBigEndian (indexPtrLiftedInBytes ptr off)) writePtrLiftedInBytes ptr off = writePtrLiftedInBytes ptr off . toLittleEndian . unViaEndianPair -deriving via (ViaFromIntegral Word16LE Int16LE) instance LiftedPrim Int16LE+deriving via (ViaFromIntegral 2 Word16LE Int16LE) instance LiftedPrim Int16LE -deriving via (ViaFromIntegral Word24LE Int24LE) instance LiftedPrim Int24LE+deriving via (ViaFromIntegral 3 Word24LE Int24LE) instance LiftedPrim Int24LE -deriving via (ViaFromIntegral Word32LE Int32LE) instance LiftedPrim Int32LE+deriving via (ViaFromIntegral 4 Word32LE Int32LE) instance LiftedPrim Int32LE -deriving via (ViaFromIntegral Word64LE Int64LE) instance LiftedPrim Int64LE+deriving via (ViaFromIntegral 8 Word64LE Int64LE) instance LiftedPrim Int64LE -deriving via (ViaEndianPair Word16LE Word16BE) instance LiftedPrim Word16BE+deriving via (ViaEndianPair 2 Word16LE Word16BE) instance LiftedPrim Word16BE -deriving via (ViaEndianPair Int16LE Int16BE) instance LiftedPrim Int16BE+deriving via (ViaEndianPair 2 Int16LE Int16BE) instance LiftedPrim Int16BE -deriving via (ViaEndianPair Word24LE Word24BE) instance LiftedPrim Word24BE+deriving via (ViaEndianPair 3 Word24LE Word24BE) instance LiftedPrim Word24BE -deriving via (ViaEndianPair Int24LE Int24BE) instance LiftedPrim Int24BE+deriving via (ViaEndianPair 3 Int24LE Int24BE) instance LiftedPrim Int24BE -deriving via (ViaEndianPair Word32LE Word32BE) instance LiftedPrim Word32BE+deriving via (ViaEndianPair 4 Word32LE Word32BE) instance LiftedPrim Word32BE -deriving via (ViaEndianPair Int32LE Int32BE) instance LiftedPrim Int32BE+deriving via (ViaEndianPair 4 Int32LE Int32BE) instance LiftedPrim Int32BE -deriving via (ViaEndianPair Word64LE Word64BE) instance LiftedPrim Word64BE+deriving via (ViaEndianPair 8 Word64LE Word64BE) instance LiftedPrim Word64BE -deriving via (ViaEndianPair Int64LE Int64BE) instance LiftedPrim Int64BE+deriving via (ViaEndianPair 8 Int64LE Int64BE) instance LiftedPrim Int64BE -deriving via (ViaEndianPair FloatLE FloatBE) instance LiftedPrim FloatBE+deriving via (ViaEndianPair 4 FloatLE FloatBE) instance LiftedPrim FloatBE -deriving via (ViaEndianPair DoubleLE DoubleBE) instance LiftedPrim DoubleBE+deriving via (ViaEndianPair 8 DoubleLE DoubleBE) instance LiftedPrim DoubleBE -- | Fill a byte array with the given value setByteArrayLifted :: (PrimMonad m, LiftedPrim a) => MutableByteArray (PrimState m) -> ByteCount -> ByteCount -> a -> m ()
src/Dahdit/LiftedPrimArray.hs view
@@ -25,7 +25,7 @@ , writeArrayLiftedInElems ) import Dahdit.Proxy (proxyFor, proxyForF)-import Dahdit.Sizes (ByteCount (..), ByteSized (..), ElemCount (..), StaticByteSized (..))+import Dahdit.Sizes (ByteCount (..), ElemCount (..), StaticByteSized (..)) import Data.Coerce (coerce) import Data.Default (Default (..)) import Data.Foldable (for_)@@ -52,34 +52,31 @@ instance Default (LiftedPrimArray a) where def = emptyLiftedPrimArray -instance ByteSized (LiftedPrimArray a) where- byteSize = sizeofLiftedPrimArray- newtype MutableLiftedPrimArray m a = MutableLiftedPrimArray {unMutableLiftedPrimArray :: MutableByteArray m} deriving newtype (Eq) emptyLiftedPrimArray :: LiftedPrimArray a emptyLiftedPrimArray = LiftedPrimArray emptyByteArray -indexLiftedPrimArray :: LiftedPrim a => LiftedPrimArray a -> ElemCount -> a+indexLiftedPrimArray :: (LiftedPrim a) => LiftedPrimArray a -> ElemCount -> a indexLiftedPrimArray (LiftedPrimArray arr) = indexArrayLiftedInElems Proxy arr writeLiftedPrimArray :: (LiftedPrim a, PrimMonad m) => MutableLiftedPrimArray (PrimState m) a -> ElemCount -> a -> m () writeLiftedPrimArray (MutableLiftedPrimArray arr) = writeArrayLiftedInElems arr -freezeLiftedPrimArray :: PrimMonad m => MutableLiftedPrimArray (PrimState m) a -> ElemCount -> ElemCount -> m (LiftedPrimArray a)+freezeLiftedPrimArray :: (PrimMonad m) => MutableLiftedPrimArray (PrimState m) a -> ElemCount -> ElemCount -> m (LiftedPrimArray a) freezeLiftedPrimArray (MutableLiftedPrimArray arr) off len = fmap LiftedPrimArray (freezeByteArray arr (coerce off) (coerce len)) -unsafeFreezeLiftedPrimArray :: PrimMonad m => MutableLiftedPrimArray (PrimState m) a -> m (LiftedPrimArray a)+unsafeFreezeLiftedPrimArray :: (PrimMonad m) => MutableLiftedPrimArray (PrimState m) a -> m (LiftedPrimArray a) unsafeFreezeLiftedPrimArray (MutableLiftedPrimArray arr) = fmap LiftedPrimArray (unsafeFreezeByteArray arr) -thawLiftedPrimArray :: PrimMonad m => LiftedPrimArray a -> ElemCount -> ElemCount -> m (MutableLiftedPrimArray (PrimState m) a)+thawLiftedPrimArray :: (PrimMonad m) => LiftedPrimArray a -> ElemCount -> ElemCount -> m (MutableLiftedPrimArray (PrimState m) a) thawLiftedPrimArray (LiftedPrimArray arr) off len = fmap MutableLiftedPrimArray (thawByteArray arr (coerce off) (coerce len)) -unsafeThawLiftedPrimArray :: PrimMonad m => LiftedPrimArray a -> m (MutableLiftedPrimArray (PrimState m) a)+unsafeThawLiftedPrimArray :: (PrimMonad m) => LiftedPrimArray a -> m (MutableLiftedPrimArray (PrimState m) a) unsafeThawLiftedPrimArray (LiftedPrimArray arr) = fmap MutableLiftedPrimArray (unsafeThawByteArray arr) -liftedPrimArrayFromListN :: LiftedPrim a => ElemCount -> [a] -> LiftedPrimArray a+liftedPrimArrayFromListN :: (LiftedPrim a) => ElemCount -> [a] -> LiftedPrimArray a liftedPrimArrayFromListN n xs = LiftedPrimArray $ runByteArray $ do let elemSize = staticByteSize (proxyForF xs) len = coerce n * coerce elemSize@@ -91,22 +88,22 @@ modifySTRef' offRef (elemSize +) pure arr -liftedPrimArrayFromList :: LiftedPrim a => [a] -> LiftedPrimArray a+liftedPrimArrayFromList :: (LiftedPrim a) => [a] -> LiftedPrimArray a liftedPrimArrayFromList xs = liftedPrimArrayFromListN (coerce (length xs)) xs -generateLiftedPrimArray :: LiftedPrim a => ElemCount -> (ElemCount -> a) -> LiftedPrimArray a+generateLiftedPrimArray :: (LiftedPrim a) => ElemCount -> (ElemCount -> a) -> LiftedPrimArray a generateLiftedPrimArray n f = liftedPrimArrayFromListN n (fmap f [0 .. n - 1]) sizeofLiftedPrimArray :: LiftedPrimArray a -> ByteCount sizeofLiftedPrimArray (LiftedPrimArray arr) = coerce (sizeofByteArray arr) -lengthLiftedPrimArray :: LiftedPrim a => LiftedPrimArray a -> ElemCount+lengthLiftedPrimArray :: (LiftedPrim a) => LiftedPrimArray a -> ElemCount lengthLiftedPrimArray pa@(LiftedPrimArray arr) = let elemSize = coerce (staticByteSize (proxyForF pa)) arrSize = sizeofByteArray arr in coerce (div arrSize elemSize) -cloneLiftedPrimArray :: LiftedPrim a => LiftedPrimArray a -> ElemCount -> ElemCount -> LiftedPrimArray a+cloneLiftedPrimArray :: (LiftedPrim a) => LiftedPrimArray a -> ElemCount -> ElemCount -> LiftedPrimArray a cloneLiftedPrimArray pa@(LiftedPrimArray arr) off len = let elemSize = staticByteSize (proxyForF pa) byteOff = coerce off * elemSize@@ -114,7 +111,7 @@ arr' = cloneByteArray arr (coerce byteOff) (coerce byteLen) in LiftedPrimArray arr' -replicateLiftedPrimArray :: LiftedPrim a => ElemCount -> a -> LiftedPrimArray a+replicateLiftedPrimArray :: (LiftedPrim a) => ElemCount -> a -> LiftedPrimArray a replicateLiftedPrimArray len val = LiftedPrimArray $ runByteArray $ do let elemSize = staticByteSize (proxyFor val) byteLen = coerce len * elemSize
src/Dahdit/Mem.hs view
@@ -1,103 +1,118 @@ module Dahdit.Mem- ( IxPtr (..)+ ( MemPtr (..)+ , emptyMemPtr+ , MutableMem (..) , ReadMem (..) , readSBSMem , viewSBSMem , viewBSMem , viewVecMem+ , mutViewVecMem , WriteMem (..) , writeSBSMem- , allocBAMem- , allocPtrMem- , freezeBAMem- , freezeSBSMem- , freezeBSMem- , freezeVecMem- , mutAllocBAMem- , mutFreezeBAMem- , mutAllocVecMem- , mutFreezeVecMem+ , withBAMem+ , withSBSMem+ , withVecMem+ , withBSMem ) where -import Control.Monad.Primitive (PrimMonad (..), unsafeIOToPrim)-import Control.Monad.ST (runST)+import Control.Monad.Primitive (MonadPrim, PrimMonad (..), RealWorld) import Dahdit.LiftedPrim (LiftedPrim (..), setByteArrayLifted) import Dahdit.Proxy (proxyFor) import Dahdit.Sizes (ByteCount (..), staticByteSize) import Data.ByteString (ByteString) import qualified Data.ByteString.Internal as BSI import Data.ByteString.Short.Internal (ShortByteString (..))-import qualified Data.ByteString.Unsafe as BSU import Data.Coerce (coerce) import Data.Foldable (for_)-import Data.Primitive.ByteArray (ByteArray (..), MutableByteArray, cloneByteArray, copyByteArray, copyByteArrayToPtr, freezeByteArray, newByteArray, sizeofMutableByteArray, unsafeFreezeByteArray)+import Data.Primitive.ByteArray (ByteArray (..), MutableByteArray, cloneByteArray, copyByteArray, copyByteArrayToPtr, freezeByteArray, newByteArray, unsafeFreezeByteArray, unsafeThawByteArray) import Data.Primitive.Ptr (copyPtrToMutableByteArray)-import Data.Vector.Storable (MVector, Vector)+import Data.Vector.Storable (Vector) import qualified Data.Vector.Storable as VS+import Data.Vector.Storable.Mutable (IOVector) import qualified Data.Vector.Storable.Mutable as VSM import Data.Word (Word8)-import Foreign.ForeignPtr (newForeignPtr)-import Foreign.ForeignPtr.Unsafe (unsafeForeignPtrToPtr)-import Foreign.Marshal.Alloc (callocBytes, finalizerFree, free)+import Foreign.ForeignPtr (ForeignPtr, mallocForeignPtrBytes, withForeignPtr) import Foreign.Ptr (Ptr, plusPtr) --- | A wrapper over 'Ptr' with an additional phantom type index to align with 'ST' state.-newtype IxPtr s = IxPtr {unIxPtr :: Ptr Word8}- deriving stock (Show)- deriving newtype (Eq, Ord)+data MemPtr s = MemPtr+ { mpForeign :: !(ForeignPtr Word8)+ , mpOffset :: !ByteCount+ , mpLength :: !ByteCount+ }+ deriving stock (Eq, Ord, Show) -class ReadMem r where- indexMemInBytes :: LiftedPrim a => r -> ByteCount -> a- cloneArrayMemInBytes :: r -> ByteCount -> ByteCount -> ByteArray+emptyMemPtr :: IO (MemPtr RealWorld)+emptyMemPtr = allocPtrMem 0 -instance ReadMem ByteArray where- indexMemInBytes = indexArrayLiftedInBytes- cloneArrayMemInBytes arr off len = cloneByteArray arr (coerce off) (coerce len)+withMemPtr :: MemPtr RealWorld -> (Ptr Word8 -> IO a) -> IO a+withMemPtr (MemPtr fp off _) f = withForeignPtr fp (\ptr -> f (plusPtr ptr (coerce off))) -clonePtr :: Ptr Word8 -> ByteCount -> ByteCount -> ByteArray-clonePtr ptr off len = runST $ do- let wptr = coerce (plusPtr ptr (coerce off)) :: Ptr Word8+class (PrimMonad m) => MutableMem r w m | w m -> r where+ unsafeThawMem :: r -> m w+ unsafeUseThawedMem :: r -> (w -> m a) -> m a+ unsafeUseThawedMem r f = unsafeThawMem r >>= f+ unsafeFreezeMem :: w -> m r+ unsafeUseFrozenMem :: w -> (r -> m a) -> m a+ unsafeUseFrozenMem w f = unsafeFreezeMem w >>= f++instance (MonadPrim s m) => MutableMem ByteArray (MutableByteArray s) m where+ unsafeThawMem = unsafeThawByteArray+ unsafeFreezeMem = unsafeFreezeByteArray++instance MutableMem (VS.Vector Word8) (IOVector Word8) IO where+ unsafeThawMem = VS.unsafeThaw+ unsafeFreezeMem = VS.unsafeFreeze++class (PrimMonad m) => ReadMem r m where+ indexMemInBytes :: (LiftedPrim a) => r -> ByteCount -> m a+ cloneArrayMemInBytes :: r -> ByteCount -> ByteCount -> m ByteArray++instance (PrimMonad m) => ReadMem ByteArray m where+ indexMemInBytes arr off = pure (indexArrayLiftedInBytes arr off)+ cloneArrayMemInBytes arr off len = pure (cloneByteArray arr (coerce off) (coerce len))++cloneMemPtr :: MemPtr RealWorld -> ByteCount -> ByteCount -> IO ByteArray+cloneMemPtr mem off len = do marr <- newByteArray (coerce len)- copyPtrToMutableByteArray marr 0 wptr (coerce len)+ withMemPtr mem $ \ptr -> do+ let wptr = plusPtr ptr (coerce off) :: Ptr Word8+ copyPtrToMutableByteArray marr 0 wptr (coerce len) unsafeFreezeByteArray marr -instance ReadMem (Ptr Word8) where- indexMemInBytes = indexPtrLiftedInBytes- cloneArrayMemInBytes = clonePtr+instance ReadMem (MemPtr RealWorld) IO where+ indexMemInBytes mem off = withMemPtr mem (\ptr -> pure (indexPtrLiftedInBytes ptr off))+ cloneArrayMemInBytes = cloneMemPtr -readSBSMem :: ReadMem r => r -> ByteCount -> ByteCount -> ShortByteString-readSBSMem mem off len = let !(ByteArray frozArr) = cloneArrayMemInBytes mem off len in SBS frozArr+readSBSMem :: (ReadMem r m) => r -> ByteCount -> ByteCount -> m ShortByteString+readSBSMem mem off len = do+ ByteArray frozArr <- cloneArrayMemInBytes mem off len+ pure (SBS frozArr) viewSBSMem :: ShortByteString -> ByteArray viewSBSMem (SBS harr) = ByteArray harr -viewBSMem :: ByteString -> Ptr Word8-viewBSMem bs =- let (fp, _) = BSI.toForeignPtr0 bs- in unsafeForeignPtrToPtr fp+viewBSMem :: ByteString -> MemPtr RealWorld+viewBSMem bs = let (fp, off, len) = BSI.toForeignPtr bs in MemPtr fp (coerce off) (coerce len) -viewVecMem :: Vector Word8 -> Ptr Word8-viewVecMem vec =- let (fp, _) = VS.unsafeToForeignPtr0 vec- in unsafeForeignPtrToPtr fp+viewVecMem :: Vector Word8 -> MemPtr RealWorld+viewVecMem vec = let (fp, off, len) = VS.unsafeToForeignPtr vec in MemPtr fp (coerce off) (coerce len) -mutViewVecMem :: MVector s Word8 -> Ptr Word8-mutViewVecMem mvec =- let (fp, _) = VSM.unsafeToForeignPtr0 mvec- in unsafeForeignPtrToPtr fp+mutViewVecMem :: IOVector Word8 -> MemPtr RealWorld+mutViewVecMem mvec = let (fp, off, len) = VSM.unsafeToForeignPtr mvec in MemPtr fp (coerce off) (coerce len) -class PrimMonad m => WriteMem q m where- writeMemInBytes :: LiftedPrim a => a -> q (PrimState m) -> ByteCount -> m ()+class (PrimMonad m) => WriteMem q m where+ writeMemInBytes :: (LiftedPrim a) => a -> q (PrimState m) -> ByteCount -> m () copyArrayMemInBytes :: ByteArray -> ByteCount -> ByteCount -> q (PrimState m) -> ByteCount -> m ()- setMemInBytes :: LiftedPrim a => ByteCount -> a -> q (PrimState m) -> ByteCount -> m ()+ setMemInBytes :: (LiftedPrim a) => ByteCount -> a -> q (PrimState m) -> ByteCount -> m () -instance PrimMonad m => WriteMem MutableByteArray m where+instance (PrimMonad m) => WriteMem MutableByteArray m where writeMemInBytes val mem off = writeArrayLiftedInBytes mem off val copyArrayMemInBytes arr arrOff arrLen mem off = copyByteArray mem (coerce off) arr (coerce arrOff) (coerce arrLen) setMemInBytes len val mem off = setByteArrayLifted mem off len val -copyPtr :: PrimMonad m => ByteArray -> ByteCount -> ByteCount -> Ptr Word8 -> ByteCount -> m ()+copyPtr :: (PrimMonad m) => ByteArray -> ByteCount -> ByteCount -> Ptr Word8 -> ByteCount -> m () copyPtr arr arrOff arrLen ptr off = let wptr = coerce (plusPtr ptr (coerce off)) :: Ptr Word8 in copyByteArrayToPtr wptr arr (coerce arrOff) (coerce arrLen)@@ -109,54 +124,46 @@ for_ [0 .. elemLen - 1] $ \pos -> writePtrLiftedInBytes ptr (off + pos * elemSize) val -instance PrimMonad m => WriteMem IxPtr m where- writeMemInBytes val mem off = writePtrLiftedInBytes (unIxPtr mem) off val- copyArrayMemInBytes arr arrOff arrLen = copyPtr arr arrOff arrLen . unIxPtr- setMemInBytes len val = setPtr len val . unIxPtr+instance WriteMem MemPtr IO where+ writeMemInBytes val mem off = withMemPtr mem (\ptr -> writePtrLiftedInBytes ptr off val)+ copyArrayMemInBytes arr arrOff arrLen mem off = withMemPtr mem (\ptr -> copyPtr arr arrOff arrLen ptr off)+ setMemInBytes len val mem off = withMemPtr mem (\ptr -> setPtr len val ptr off) -writeSBSMem :: WriteMem q m => ShortByteString -> ByteCount -> q (PrimState m) -> ByteCount -> m ()+writeSBSMem :: (WriteMem q m) => ShortByteString -> ByteCount -> q (PrimState m) -> ByteCount -> m () writeSBSMem (SBS harr) = copyArrayMemInBytes (ByteArray harr) 0 -freezeBAMem :: PrimMonad m => MutableByteArray (PrimState m) -> ByteCount -> ByteCount -> m ByteArray-freezeBAMem marr (ByteCount startOff) (ByteCount endOff) =- if startOff == 0 && endOff == sizeofMutableByteArray marr+withBAMem :: (MonadPrim s m) => ByteCount -> (MutableByteArray s -> m ByteCount) -> m ByteArray+withBAMem len use = do+ marr <- newByteArray (coerce len)+ len' <- use marr+ if len' == len then unsafeFreezeByteArray marr- else freezeByteArray marr startOff (endOff - startOff)--freezeSBSMem :: PrimMonad m => MutableByteArray (PrimState m) -> ByteCount -> ByteCount -> m ShortByteString-freezeSBSMem marr startOff endOff = fmap (\(ByteArray harr) -> SBS harr) (freezeBAMem marr startOff endOff)--freezeBSMem :: PrimMonad m => IxPtr (PrimState m) -> ByteCount -> ByteCount -> m ByteString-freezeBSMem (IxPtr ptr) startOff endOff =- unsafeIOToPrim $- BSU.unsafePackCStringFinalizer- (plusPtr ptr (unByteCount startOff))- (unByteCount (endOff - startOff))- (free ptr)--freezeVecMem :: PrimMonad m => IxPtr (PrimState m) -> ByteCount -> ByteCount -> m (Vector Word8)-freezeVecMem (IxPtr ptr) _ len = unsafeIOToPrim (fmap (\fp -> VS.unsafeFromForeignPtr0 fp (coerce len)) (newForeignPtr finalizerFree ptr))+ else freezeByteArray marr 0 (coerce len') -allocPtrMem :: PrimMonad m => ByteCount -> ByteCount -> m (IxPtr (PrimState m), Maybe (IO ()))-allocPtrMem off len = do- let cap = off + len- ptr <- unsafeIOToPrim (callocBytes (unByteCount cap))- pure (IxPtr ptr, Just (free ptr))+withSBSMem :: (MonadPrim s m) => ByteCount -> (MutableByteArray s -> m ByteCount) -> m ShortByteString+withSBSMem len use = fmap (\(ByteArray arr) -> SBS arr) (withBAMem len use) -allocBAMem :: PrimMonad m => ByteCount -> ByteCount -> m (MutableByteArray (PrimState m), Maybe (IO ()))-allocBAMem off len = do- let cap = off + len- arr <- newByteArray (unByteCount cap)- pure (arr, Nothing)+allocPtrMem :: ByteCount -> IO (MemPtr RealWorld)+allocPtrMem len = do+ fp <- mallocForeignPtrBytes (coerce len)+ pure (MemPtr fp 0 len) -mutAllocBAMem :: PrimMonad m => MutableByteArray (PrimState m) -> ByteCount -> ByteCount -> m (MutableByteArray (PrimState m), Maybe (IO ()))-mutAllocBAMem u _ _ = pure (u, Nothing)+freezeVecMem :: MemPtr RealWorld -> ByteCount -> Vector Word8+freezeVecMem (MemPtr fp off _) len =+ VS.unsafeFromForeignPtr fp (coerce off) (coerce (off + len)) -mutFreezeBAMem :: PrimMonad m => MutableByteArray (PrimState m) -> ByteCount -> ByteCount -> m ByteCount-mutFreezeBAMem _ _ = pure+freezeBSMem :: MemPtr RealWorld -> ByteCount -> ByteString+freezeBSMem (MemPtr fp off _) len =+ BSI.fromForeignPtr fp (coerce off) (coerce (off + len)) -mutAllocVecMem :: PrimMonad m => MVector (PrimState m) Word8 -> ByteCount -> ByteCount -> m (IxPtr (PrimState m), Maybe (IO ()))-mutAllocVecMem u _ _ = pure (IxPtr (mutViewVecMem u), Nothing)+withVecMem :: ByteCount -> (MemPtr RealWorld -> IO ByteCount) -> IO (Vector Word8)+withVecMem len use = do+ mem <- allocPtrMem len+ len' <- use mem+ pure (freezeVecMem mem len') -mutFreezeVecMem :: PrimMonad m => IxPtr (PrimState m) -> ByteCount -> ByteCount -> m ByteCount-mutFreezeVecMem _ _ = pure+withBSMem :: ByteCount -> (MemPtr RealWorld -> IO ByteCount) -> IO ByteString+withBSMem len use = do+ mem <- allocPtrMem len+ len' <- use mem+ pure (freezeBSMem mem len')
src/Dahdit/Nums.hs view
@@ -126,42 +126,42 @@ deriving stock (Show) deriving newtype (Eq, Ord, Num, Real, Fractional, Floating, RealFrac, Default) -instance EndianPair Word16LE Word16BE where+instance EndianPair 2 Word16LE Word16BE where toLittleEndian = Word16LE . swapEndian . unWord16BE toBigEndian = Word16BE . swapEndian . unWord16LE -instance EndianPair Int16LE Int16BE where+instance EndianPair 2 Int16LE Int16BE where toLittleEndian = Int16LE . swapEndian . unInt16BE toBigEndian = Int16BE . swapEndian . unInt16LE -instance EndianPair Word24LE Word24BE where+instance EndianPair 3 Word24LE Word24BE where toLittleEndian = Word24LE . swapEndian . unWord24BE toBigEndian = Word24BE . swapEndian . unWord24LE -instance EndianPair Int24LE Int24BE where+instance EndianPair 3 Int24LE Int24BE where toLittleEndian = Int24LE . swapEndian . unInt24BE toBigEndian = Int24BE . swapEndian . unInt24LE -instance EndianPair Word32LE Word32BE where+instance EndianPair 4 Word32LE Word32BE where toLittleEndian = Word32LE . swapEndian . unWord32BE toBigEndian = Word32BE . swapEndian . unWord32LE -instance EndianPair Int32LE Int32BE where+instance EndianPair 4 Int32LE Int32BE where toLittleEndian = Int32LE . swapEndian . unInt32BE toBigEndian = Int32BE . swapEndian . unInt32LE -instance EndianPair Word64LE Word64BE where+instance EndianPair 8 Word64LE Word64BE where toLittleEndian = Word64LE . swapEndian . unWord64BE toBigEndian = Word64BE . swapEndian . unWord64LE -instance EndianPair Int64LE Int64BE where+instance EndianPair 8 Int64LE Int64BE where toLittleEndian = Int64LE . swapEndian . unInt64BE toBigEndian = Int64BE . swapEndian . unInt64LE -instance EndianPair FloatLE FloatBE where+instance EndianPair 4 FloatLE FloatBE where toLittleEndian = FloatLE . swapEndian . unFloatBE toBigEndian = FloatBE . swapEndian . unFloatLE -instance EndianPair DoubleLE DoubleBE where+instance EndianPair 8 DoubleLE DoubleBE where toLittleEndian = DoubleLE . swapEndian . unDoubleBE toBigEndian = DoubleBE . swapEndian . unDoubleLE
src/Dahdit/Proxy.hs view
@@ -1,12 +1,14 @@ module Dahdit.Proxy ( proxyFor , proxyForF+ , proxyForRepF , proxyForFun , proxyForNatF ) where import Data.Proxy (Proxy (..))+import GHC.Generics (Generic (..)) import GHC.TypeLits (Nat) proxyFor :: a -> Proxy a@@ -14,6 +16,9 @@ proxyForF :: f a -> Proxy a proxyForF _ = Proxy++proxyForRepF :: f t -> Rep t a -> Proxy (Rep t)+proxyForRepF _ _ = Proxy proxyForFun :: (a -> x) -> Proxy a proxyForFun _ = Proxy
src/Dahdit/Run.hs view
@@ -1,26 +1,34 @@+{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE UndecidableInstances #-} module Dahdit.Run ( GetError (..) , prettyGetError , runGetInternal+ , GetIncEnv (..)+ , newGetIncEnv+ , GetIncChunk (..)+ , GetIncRequest (..)+ , GetIncSuspend (..)+ , GetIncCb+ , runGetIncInternal , runCount , runPutInternal ) where import Control.Applicative (Alternative (..))-import Control.Exception (Exception (..), onException)+import Control.Exception (Exception (..)) import Control.Monad (replicateM_, unless) import Control.Monad.Except (ExceptT, MonadError, runExceptT, throwError)-import Control.Monad.Free.Church (F (..))-import Control.Monad.Primitive (PrimBase, PrimMonad (..), unsafeIOToPrim, unsafePrimToIO)+import Control.Monad.Free.Church (F (..), iterM)+import Control.Monad.Free.Class (MonadFree (..))+import Control.Monad.Primitive (MonadPrim, PrimMonad (..)) import Control.Monad.Reader (MonadReader (..), ReaderT (..), asks)-import Control.Monad.ST.Strict (ST, runST) import Control.Monad.State.Strict (MonadState, State, runState) import qualified Control.Monad.State.Strict as State-import Control.Monad.Trans (lift)-import Control.Monad.Trans.Free (FreeT (..), iterT, wrap)+import Control.Monad.Trans (MonadTrans (..))+import Control.Monad.Trans.Free.Church (FT (..), iterT) import Control.Monad.Trans.Maybe (MaybeT (..)) import Dahdit.Free ( Get (..)@@ -67,9 +75,11 @@ import Data.Foldable (for_, toList) import Data.Int (Int8) import Data.Maybe (fromJust)-import Data.Primitive.MutVar (MutVar, newMutVar, readMutVar, writeMutVar)-import Data.STRef.Strict (STRef, newSTRef, readSTRef, writeSTRef)+import Data.Primitive.MutVar (MutVar, modifyMutVar', newMutVar, readMutVar, writeMutVar)+import Data.Sequence (Seq (..)) import qualified Data.Sequence as Seq+import Data.Text (Text)+import qualified Data.Text as T import Data.Word (Word8) -- Sizes:@@ -92,132 +102,231 @@ -- Get: data GetError- = GetErrorParseNeed !String !ByteCount !ByteCount- | GetErrorScopedMismatch !ByteCount !ByteCount- | GetErrorFail !String+ = GetErrorLocalCap !Text !ByteCount !ByteCount+ | GetErrorScopedMismatch !ScopeMode !ByteCount !ByteCount+ | GetErrorFail !Text+ | GetErrorGlobalCap !Text !ByteCount !ByteCount+ | GetErrorRemaining !ByteCount deriving stock (Eq, Show) instance Exception GetError where- displayException = prettyGetError+ displayException = T.unpack . prettyGetError -prettyGetError :: GetError -> String+prettyGetError :: GetError -> Text prettyGetError = \case- GetErrorParseNeed nm ac bc -> "End of input parsing " ++ nm ++ " (have " ++ show (unByteCount ac) ++ " bytes, need " ++ show (unByteCount bc) ++ ")"- GetErrorScopedMismatch ac bc -> "Did not parse enough scoped input (read " ++ show (unByteCount ac) ++ " bytes, expected " ++ show (unByteCount bc) ++ ")"- GetErrorFail msg -> "User error: " ++ msg+ GetErrorLocalCap nm ac bc -> "End of chunk parsing " <> nm <> " (have " <> T.pack (show (unByteCount ac)) <> " bytes, need " <> T.pack (show (unByteCount bc)) <> ")"+ GetErrorScopedMismatch sm ac bc ->+ let ty = case sm of ScopeModeExact -> "exact"; ScopeModeWithin -> "within"+ in "Did not parse " <> ty <> " scoped input (read " <> T.pack (show (unByteCount ac)) <> " bytes, expected " <> T.pack (show (unByteCount bc)) <> ")"+ GetErrorFail msg -> "User error: " <> msg+ GetErrorGlobalCap nm ac bc -> "Hit limit parsing " <> nm <> " (allowed " <> T.pack (show (unByteCount ac)) <> " bytes, need " <> T.pack (show (unByteCount bc)) <> ")"+ GetErrorRemaining ac -> "Cannot read remaining length in stream context (read " <> T.pack (show (unByteCount ac)) <> ")" -data GetEnv s r = GetEnv- { geOff :: !(STRef s ByteCount)- -- ^ Offset from buffer start (in bytes)- , geCap :: !ByteCount- -- ^ Capacity of buffer segment- , geArray :: !r+-- | Get from a single buffer+runGetInternal :: (ReadMem r m) => ByteCount -> Get a -> ByteCount -> r -> m (Either GetError a, ByteCount)+runGetInternal off act cap mem = do+ let chunk = GetIncChunk off cap mem+ env <- newGetIncEnv (Just (cap - off)) chunk+ (ea, _, off') <- runGetIncInternal act env (const (pure Nothing))+ pure (ea, off')++-- Get inc++data GetIncChunk r = GetIncChunk+ { gicLocalOff :: !ByteCount+ -- ^ Offset from start of local buffer to data+ , gicLocalCap :: !ByteCount+ -- ^ Capacity of local buffer+ , gicArray :: !r -- ^ Source buffer } -newGetEnv :: ByteCount -> ByteCount -> r -> ST s (GetEnv s r)-newGetEnv off cap mem = do- offRef <- newSTRef off- pure (GetEnv offRef cap mem)+data GetIncEnv s r = GetIncEnv+ { gieGlobalAbs :: !(MutVar s ByteCount)+ -- ^ Offset from start of parsing (0) to current position+ , gieGlobalRel :: !(MutVar s ByteCount)+ -- ^ Offset from start of parsing (0) to start of buffer+ -- It will always be the case that gloRel <= gloAbs+ , gieGlobalCap :: !(MutVar s (Seq ByteCount))+ -- ^ Stack of maximum capcacity (across all chunks)+ -- Top of stack is end of sequence.+ -- This will be narrowed to check scoped length.+ , gieCurChunk :: !(MutVar s (GetIncChunk r))+ -- ^ Current chunk+ , gieLookAhead :: !(MutVar s (Seq ByteCount))+ -- ^ Stack of look ahead points (in absolute position)+ -- Top of stack is end of sequence.+ } -newtype GetEff s r a = GetEff {unGetEff :: ReaderT (GetEnv s r) (ExceptT GetError (ST s)) a}- deriving newtype (Functor, Applicative, Monad, MonadReader (GetEnv s r), MonadError GetError)+newGetIncEnv :: (MonadPrim s m) => Maybe ByteCount -> GetIncChunk r -> m (GetIncEnv s r)+newGetIncEnv mayCap chunk = do+ gloAbsVar <- newMutVar 0+ gloRelVar <- newMutVar 0+ gloCapVar <- newMutVar (maybe Empty Seq.singleton mayCap)+ curChunkVar <- newMutVar chunk+ lookAheadVar <- newMutVar Empty+ pure (GetIncEnv gloAbsVar gloRelVar gloCapVar curChunkVar lookAheadVar) -runGetEff :: GetEff s r a -> GetEnv s r -> ST s (Either GetError a)-runGetEff act env = runExceptT (runReaderT (unGetEff act) env)+-- | A request for more data. Includes absolute position, offset in the current buffer, and required length.+data GetIncRequest = GetIncRequest+ { girAbsPos :: !ByteCount+ , girBaseOff :: !ByteCount+ , girNeedLength :: !ByteCount+ }+ deriving stock (Eq, Ord, Show) -instance MonadFail (GetEff s r) where- fail = GetEff . throwError . GetErrorFail+-- | See 'GetIncCb' - this is the functor-ized version so we can suspend execution.+data GetIncSuspend z x = GetIncSuspend !GetIncRequest !(Maybe z -> x)+ deriving stock (Functor) -stGetEff :: ST s a -> GetEff s r a-stGetEff = GetEff . lift . lift+type GetIncSuspendChunk r = GetIncSuspend (GetIncChunk r) -newtype GetRun s r a = GetRun {unGetRun :: FreeT GetF (GetEff s r) a}- deriving newtype (Functor, Applicative, Monad)+-- Should not implement 'MonadReader' so we can prevent scoped operations like 'local'+newtype GetIncM s r m a = GetIncM {unGetIncM :: ReaderT (GetIncEnv s r) (ExceptT GetError (FT (GetIncSuspendChunk r) m)) a}+ deriving newtype+ ( Functor+ , Applicative+ , Monad+ , MonadError GetError+ , MonadFree (GetIncSuspendChunk r)+ ) -guardReadBytes :: String -> ByteCount -> GetEff s r ByteCount+instance MonadTrans (GetIncM s r) where+ lift = GetIncM . lift . lift . lift++-- | Return new chunk containing enough data (or nothing).+type GetIncCb z m = GetIncRequest -> m (Maybe z)++type GetIncCbChunk r m = GetIncCb (GetIncChunk r) m++pushMutVar :: (MonadPrim s m) => MutVar s (Seq a) -> a -> m ()+pushMutVar v a = modifyMutVar' v (:|> a)++popMutVar :: (MonadPrim s m) => MutVar s (Seq a) -> m ()+popMutVar v = modifyMutVar' v (\case Empty -> Empty; as :|> _ -> as)++peekMutVar :: (MonadPrim s m) => MutVar s (Seq a) -> m (Maybe a)+peekMutVar = fmap (\case Empty -> Nothing; _ :|> a -> Just a) . readMutVar++runGetIncM :: (MonadPrim s m) => GetIncM s r m a -> GetIncEnv s r -> GetIncCbChunk r m -> m (Either GetError a)+runGetIncM m env cb =+ runFT+ (runExceptT (runReaderT (unGetIncM m) env))+ pure+ (\k2 (GetIncSuspend req k1) -> cb req >>= k2 . k1)++guardReadBytes :: (MonadPrim s m) => Text -> ByteCount -> GetIncM s r m (ByteCount, GetIncChunk r, ByteCount) guardReadBytes nm bc = do- GetEnv offRef cap _ <- ask- off <- stGetEff (readSTRef offRef)- let ac = cap - off- if bc > ac- then throwError (GetErrorParseNeed nm ac bc)- else pure off+ GetIncEnv gloAbsRef gloRelRef capStackRef chunkRef lookStackRef <- GetIncM ask+ -- First check if we're in cap+ gloAbsStart <- lift (readMutVar gloAbsRef)+ let gloAbsEnd = gloAbsStart + bc+ mayCap <- lift (peekMutVar capStackRef)+ case mayCap of+ Just cap | gloAbsEnd > cap -> throwError (GetErrorGlobalCap nm cap gloAbsEnd)+ _ -> pure ()+ -- Now check that we have enough in the local buf+ gloRel <- lift (readMutVar gloRelRef)+ oldChunk@(GetIncChunk oldOff oldCap _) <- lift (readMutVar chunkRef)+ let oldLocOffStart = gloAbsStart - gloRel + oldOff+ oldLocOffEnd = oldLocOffStart + bc+ (newChunk, newLocOffStart) <-+ if oldLocOffEnd <= oldCap+ then pure (oldChunk, oldLocOffStart)+ else do+ lookStack <- lift (readMutVar lookStackRef)+ let gloBaseStart = case lookStack of Empty -> gloAbsStart; x :<| _ -> x+ baseOffStart = gloBaseStart - gloRel + oldOff+ baseOffEnd = gloAbsStart - gloRel + oldOff + bc+ let needLength = baseOffEnd - baseOffStart+ req = GetIncRequest gloAbsStart baseOffStart needLength+ wrap $ GetIncSuspend req $ \case+ Nothing -> throwError (GetErrorLocalCap nm oldCap baseOffEnd)+ Just newChunk@(GetIncChunk newOff newCap _) -> do+ let newEnd = newOff + needLength+ unless (newEnd <= newCap) (throwError (GetErrorLocalCap nm newCap newOff))+ lift (writeMutVar chunkRef newChunk)+ lift (writeMutVar gloRelRef gloBaseStart)+ pure (newChunk, gicLocalOff newChunk)+ pure (gloAbsEnd, newChunk, newLocOffStart) -readBytes :: String -> ByteCount -> (r -> ByteCount -> a) -> GetEff s r a+-- Memory read function takes local start offset+readBytes :: (MonadPrim s m) => Text -> ByteCount -> (r -> ByteCount -> m a) -> GetIncM s r m a readBytes nm bc f = do- off <- guardReadBytes nm bc- GetEnv offRef _ mem <- ask- stGetEff $ do- let a = f mem off- newOff = off + bc- writeSTRef offRef newOff- pure a+ (gloAbsEnd, newChunk, newLocOffStart) <- guardReadBytes nm bc+ let mem = gicArray newChunk+ a <- lift (f mem newLocOffStart)+ gloAbsRef <- GetIncM (asks gieGlobalAbs)+ lift (writeMutVar gloAbsRef gloAbsEnd)+ pure a -readScope :: ReadMem r => GetScopeF (GetEff s r a) -> GetEff s r a+readScope :: (MonadPrim s m, ReadMem r m) => GetScopeF (GetIncM s r m a) -> GetIncM s r m a readScope (GetScopeF sm bc g k) = do- GetEnv offRef oldCap _ <- ask- oldOff <- stGetEff (readSTRef offRef)- let oldAvail = oldCap - oldOff- if bc > oldAvail- then throwError (GetErrorParseNeed "scope" oldAvail bc)- else do- let newCap = oldOff + bc- a <- local (\ge -> ge {geCap = newCap}) (mkGetEff g)- case sm of- ScopeModeWithin -> k a- ScopeModeExact -> do- newOff <- stGetEff (readSTRef offRef)- let actualBc = newOff - oldOff- if actualBc == bc- then k a- else throwError (GetErrorScopedMismatch actualBc bc)+ GetIncEnv gloAbsRef _ capStackRef _ _ <- GetIncM ask+ gloAbsStart <- lift (readMutVar gloAbsRef)+ let gloAbsMax = gloAbsStart + bc+ mayCap <- lift (peekMutVar capStackRef)+ case mayCap of+ Just cap+ | sm == ScopeModeExact && gloAbsMax > cap ->+ throwError (GetErrorGlobalCap "scope" cap gloAbsMax)+ _ -> pure ()+ lift (pushMutVar capStackRef gloAbsMax)+ a <- interpGetInc g+ lift (popMutVar capStackRef)+ gloAbsEnd <- lift (readMutVar gloAbsRef)+ let actualBc = gloAbsEnd - gloAbsStart+ if (sm == ScopeModeExact && actualBc == bc) || (sm == ScopeModeWithin && actualBc <= bc)+ then k a+ else throwError (GetErrorScopedMismatch sm actualBc bc) -readStaticSeq :: ReadMem r => GetStaticSeqF (GetEff s r a) -> GetEff s r a+readStaticSeq :: (MonadPrim s m, ReadMem r m) => GetStaticSeqF (GetIncM s r m a) -> GetIncM s r m a readStaticSeq gss@(GetStaticSeqF ec g k) = do let bc = getStaticSeqSize gss _ <- guardReadBytes "static sequence" bc- ss <- Seq.replicateA (coerce ec) (mkGetEff g)+ ss <- Seq.replicateA (coerce ec) (interpGetInc g) k ss -readStaticArray :: ReadMem r => GetStaticArrayF (GetEff s r a) -> GetEff s r a+readStaticArray :: (MonadPrim s m, ReadMem r m) => GetStaticArrayF (GetIncM s r m a) -> GetIncM s r m a readStaticArray gsa@(GetStaticArrayF _ _ k) = do let bc = getStaticArraySize gsa sa <- readBytes "static vector" bc (\mem off -> cloneArrayMemInBytes mem off bc) k (LiftedPrimArray sa) -readLookAhead :: ReadMem r => GetLookAheadF (GetEff s r a) -> GetEff s r a+readLookAhead :: (MonadPrim s m, ReadMem r m) => GetLookAheadF (GetIncM s r m a) -> GetIncM s r m a readLookAhead (GetLookAheadF g k) = do- offRef <- asks geOff- startOff <- stGetEff (readSTRef offRef)- a <- mkGetEff g- stGetEff (writeSTRef offRef startOff)+ GetIncEnv gloAbsRef _ _ _ lookStackRef <- GetIncM ask+ gloAbs <- lift (readMutVar gloAbsRef)+ lift (pushMutVar lookStackRef gloAbs)+ a <- interpGetInc g+ lift (popMutVar lookStackRef)+ lift (writeMutVar gloAbsRef gloAbs) k a -execGetRun :: ReadMem r => GetF (GetEff s r a) -> GetEff s r a-execGetRun = \case- GetFWord8 k -> readBytes "Word8" 1 (indexMemInBytes @_ @Word8) >>= k- GetFInt8 k -> readBytes "Int8" 1 (indexMemInBytes @_ @Int8) >>= k- GetFWord16LE k -> readBytes "Word16LE" 2 (indexMemInBytes @_ @Word16LE) >>= k- GetFInt16LE k -> readBytes "Int16LE" 2 (indexMemInBytes @_ @Int16LE) >>= k- GetFWord24LE k -> readBytes "Word24LE" 3 (indexMemInBytes @_ @Word24LE) >>= k- GetFInt24LE k -> readBytes "Int24LE" 3 (indexMemInBytes @_ @Int24LE) >>= k- GetFWord32LE k -> readBytes "Word32LE" 4 (indexMemInBytes @_ @Word32LE) >>= k- GetFInt32LE k -> readBytes "Int32LE" 4 (indexMemInBytes @_ @Int32LE) >>= k- GetFWord64LE k -> readBytes "Word64LE" 8 (indexMemInBytes @_ @Word64LE) >>= k- GetFInt64LE k -> readBytes "Int64LE" 8 (indexMemInBytes @_ @Int64LE) >>= k- GetFFloatLE k -> readBytes "FloatLE" 4 (indexMemInBytes @_ @FloatLE) >>= k- GetFDoubleLE k -> readBytes "DoubleLE" 8 (indexMemInBytes @_ @DoubleLE) >>= k- GetFWord16BE k -> readBytes "Word16BE" 2 (indexMemInBytes @_ @Word16BE) >>= k- GetFInt16BE k -> readBytes "Int16BE" 2 (indexMemInBytes @_ @Int16BE) >>= k- GetFWord24BE k -> readBytes "Word24BE" 3 (indexMemInBytes @_ @Word24BE) >>= k- GetFInt24BE k -> readBytes "Int24BE" 3 (indexMemInBytes @_ @Int24BE) >>= k- GetFWord32BE k -> readBytes "Word32BE" 4 (indexMemInBytes @_ @Word32BE) >>= k- GetFInt32BE k -> readBytes "Int32BE" 4 (indexMemInBytes @_ @Int32BE) >>= k- GetFWord64BE k -> readBytes "Word64BE" 8 (indexMemInBytes @_ @Word64BE) >>= k- GetFInt64BE k -> readBytes "Int64BE" 8 (indexMemInBytes @_ @Int64BE) >>= k- GetFFloatBE k -> readBytes "FloatBE" 4 (indexMemInBytes @_ @FloatBE) >>= k- GetFDoubleBE k -> readBytes "DoubleBE" 8 (indexMemInBytes @_ @DoubleBE) >>= k+interpGetInc :: (MonadPrim s m, ReadMem r m) => Get a -> GetIncM s r m a+interpGetInc (Get g) = flip iterM g $ \case+ GetFWord8 k -> readBytes "Word8" 1 (indexMemInBytes @_ @_ @Word8) >>= k+ GetFInt8 k -> readBytes "Int8" 1 (indexMemInBytes @_ @_ @Int8) >>= k+ GetFWord16LE k -> readBytes "Word16LE" 2 (indexMemInBytes @_ @_ @Word16LE) >>= k+ GetFInt16LE k -> readBytes "Int16LE" 2 (indexMemInBytes @_ @_ @Int16LE) >>= k+ GetFWord24LE k -> readBytes "Word24LE" 3 (indexMemInBytes @_ @_ @Word24LE) >>= k+ GetFInt24LE k -> readBytes "Int24LE" 3 (indexMemInBytes @_ @_ @Int24LE) >>= k+ GetFWord32LE k -> readBytes "Word32LE" 4 (indexMemInBytes @_ @_ @Word32LE) >>= k+ GetFInt32LE k -> readBytes "Int32LE" 4 (indexMemInBytes @_ @_ @Int32LE) >>= k+ GetFWord64LE k -> readBytes "Word64LE" 8 (indexMemInBytes @_ @_ @Word64LE) >>= k+ GetFInt64LE k -> readBytes "Int64LE" 8 (indexMemInBytes @_ @_ @Int64LE) >>= k+ GetFFloatLE k -> readBytes "FloatLE" 4 (indexMemInBytes @_ @_ @FloatLE) >>= k+ GetFDoubleLE k -> readBytes "DoubleLE" 8 (indexMemInBytes @_ @_ @DoubleLE) >>= k+ GetFWord16BE k -> readBytes "Word16BE" 2 (indexMemInBytes @_ @_ @Word16BE) >>= k+ GetFInt16BE k -> readBytes "Int16BE" 2 (indexMemInBytes @_ @_ @Int16BE) >>= k+ GetFWord24BE k -> readBytes "Word24BE" 3 (indexMemInBytes @_ @_ @Word24BE) >>= k+ GetFInt24BE k -> readBytes "Int24BE" 3 (indexMemInBytes @_ @_ @Int24BE) >>= k+ GetFWord32BE k -> readBytes "Word32BE" 4 (indexMemInBytes @_ @_ @Word32BE) >>= k+ GetFInt32BE k -> readBytes "Int32BE" 4 (indexMemInBytes @_ @_ @Int32BE) >>= k+ GetFWord64BE k -> readBytes "Word64BE" 8 (indexMemInBytes @_ @_ @Word64BE) >>= k+ GetFInt64BE k -> readBytes "Int64BE" 8 (indexMemInBytes @_ @_ @Int64BE) >>= k+ GetFFloatBE k -> readBytes "FloatBE" 4 (indexMemInBytes @_ @_ @FloatBE) >>= k+ GetFDoubleBE k -> readBytes "DoubleBE" 8 (indexMemInBytes @_ @_ @DoubleBE) >>= k GetFShortByteString bc k -> readBytes "ShortByteString" bc (\mem off -> readSBSMem mem off bc) >>= k GetFStaticSeq gss -> readStaticSeq gss@@ -225,35 +334,28 @@ GetFByteArray bc k -> readBytes "ByteArray" bc (\mem off -> cloneArrayMemInBytes mem off bc) >>= k GetFScope gs -> readScope gs- GetFSkip bc k -> readBytes "skip" bc (\_ _ -> ()) *> k+ GetFSkip bc k -> readBytes "skip" bc (\_ _ -> pure ()) >> k GetFLookAhead gla -> readLookAhead gla GetFRemainingSize k -> do- GetEnv offRef cap _ <- ask- off <- stGetEff (readSTRef offRef)- k (cap - off)- GetFFail msg -> fail msg--runGetRun :: ReadMem r => GetRun s r a -> GetEnv s r -> ST s (Either GetError a)-runGetRun = runGetEff . iterGetRun--iterGetRun :: ReadMem r => GetRun s r a -> GetEff s r a-iterGetRun act = iterT execGetRun (unGetRun act)--mkGetRun :: Get a -> GetRun s r a-mkGetRun (Get (F w)) = GetRun (w pure wrap)--mkGetEff :: ReadMem r => Get a -> GetEff s r a-mkGetEff = iterGetRun . mkGetRun+ GetIncEnv gloAbsRef _ capStackRef _ _ <- GetIncM ask+ gloAbs <- lift (readMutVar gloAbsRef)+ capStack <- lift (readMutVar capStackRef)+ case capStack of+ Empty -> throwError (GetErrorRemaining gloAbs)+ _ :|> cap -> k (cap - gloAbs)+ GetFFail msg -> throwError (GetErrorFail msg) -runGetInternal :: ReadMem r => ByteCount -> Get a -> ByteCount -> r -> (Either GetError a, ByteCount)-runGetInternal off act cap mem = runST $ do- let eff = mkGetEff act- env <- newGetEnv off cap mem- ea <- runGetEff eff env- bc <- readSTRef (geOff env)- pure (ea, bc)+runGetIncInternal :: (MonadPrim s m, ReadMem r m) => Get a -> GetIncEnv s r -> GetIncCbChunk r m -> m (Either GetError a, ByteCount, ByteCount)+runGetIncInternal getter env cb = do+ let m = interpGetInc getter+ res <- runGetIncM m env cb+ gloAbs <- readMutVar (gieGlobalAbs env)+ gloRel <- readMutVar (gieGlobalRel env)+ curChunk <- readMutVar (gieCurChunk env)+ let baseOff = gloAbs - gloRel + gicLocalOff curChunk+ pure (res, gloAbs, baseOff) --- Put unsafe:+-- Put: data PutEnv s q = PutEnv { peOff :: !(MutVar s ByteCount)@@ -264,7 +366,7 @@ -- ^ Destination buffer } -newPutEnv :: PrimMonad m => ByteCount -> ByteCount -> q (PrimState m) -> m (PutEnv (PrimState m) q)+newPutEnv :: (PrimMonad m) => ByteCount -> ByteCount -> q (PrimState m) -> m (PutEnv (PrimState m) q) newPutEnv off cap mem = do offRef <- newMutVar off pure (PutEnv offRef cap mem)@@ -277,13 +379,13 @@ runPutEff :: PutEff q m a -> PutEnv (PrimState m) q -> m a runPutEff act = runReaderT (unPutEff act) -stPutEff :: Monad m => m a -> PutEff q m a+stPutEff :: (Monad m) => m a -> PutEff q m a stPutEff = PutEff . lift -newtype PutRun q m a = PutRun {unPutRun :: FreeT PutF (PutEff q m) a}+newtype PutRun q m a = PutRun {unPutRun :: FT PutF (PutEff q m) a} deriving newtype (Functor, Applicative, Monad) -writeBytes :: PrimMonad m => ByteCount -> (q (PrimState m) -> ByteCount -> m ()) -> PutEff q m ()+writeBytes :: (PrimMonad m) => ByteCount -> (q (PrimState m) -> ByteCount -> m ()) -> PutEff q m () writeBytes bc f = do PutEnv offRef _ mem <- ask stPutEff $ do@@ -292,7 +394,7 @@ let newOff = off + bc writeMutVar offRef newOff -writeStaticSeq :: WriteMem q m => PutStaticSeqF (PutEff q m a) -> PutEff q m a+writeStaticSeq :: (WriteMem q m) => PutStaticSeqF (PutEff q m a) -> PutEff q m a writeStaticSeq (PutStaticSeqF n mz p s k) = do for_ (take (coerce n) (toList s)) $ \a -> do mkPutEff (p a)@@ -302,7 +404,7 @@ replicateM_ (coerce n - e) q k -writeStaticArray :: WriteMem q m => PutStaticArrayF (PutEff q m a) -> PutEff q m a+writeStaticArray :: (WriteMem q m) => PutStaticArrayF (PutEff q m a) -> PutEff q m a writeStaticArray psa@(PutStaticArrayF needElems mz a@(LiftedPrimArray ba) k) = do let elemSize = putStaticArrayElemSize psa haveElems = sizeofLiftedPrimArray a@@ -317,52 +419,52 @@ Just z -> writeBytes extraBc (setMemInBytes extraBc z) k -execPutRun :: WriteMem q m => PutF (PutEff q m a) -> PutEff q m a+execPutRun :: (WriteMem q m) => PutF (PutEff q m a) -> PutEff q m a execPutRun = \case- PutFWord8 x k -> writeBytes 1 (writeMemInBytes x) *> k- PutFInt8 x k -> writeBytes 1 (writeMemInBytes x) *> k- PutFWord16LE x k -> writeBytes 2 (writeMemInBytes x) *> k- PutFInt16LE x k -> writeBytes 2 (writeMemInBytes x) *> k- PutFWord24LE x k -> writeBytes 3 (writeMemInBytes x) *> k- PutFInt24LE x k -> writeBytes 3 (writeMemInBytes x) *> k- PutFWord32LE x k -> writeBytes 4 (writeMemInBytes x) *> k- PutFInt32LE x k -> writeBytes 4 (writeMemInBytes x) *> k- PutFWord64LE x k -> writeBytes 8 (writeMemInBytes x) *> k- PutFInt64LE x k -> writeBytes 8 (writeMemInBytes x) *> k- PutFFloatLE x k -> writeBytes 4 (writeMemInBytes x) *> k- PutFDoubleLE x k -> writeBytes 8 (writeMemInBytes x) *> k- PutFWord16BE x k -> writeBytes 2 (writeMemInBytes x) *> k- PutFInt16BE x k -> writeBytes 2 (writeMemInBytes x) *> k- PutFWord24BE x k -> writeBytes 3 (writeMemInBytes x) *> k- PutFInt24BE x k -> writeBytes 3 (writeMemInBytes x) *> k- PutFWord32BE x k -> writeBytes 4 (writeMemInBytes x) *> k- PutFInt32BE x k -> writeBytes 4 (writeMemInBytes x) *> k- PutFWord64BE x k -> writeBytes 8 (writeMemInBytes x) *> k- PutFInt64BE x k -> writeBytes 8 (writeMemInBytes x) *> k- PutFFloatBE x k -> writeBytes 4 (writeMemInBytes x) *> k- PutFDoubleBE x k -> writeBytes 8 (writeMemInBytes x) *> k+ PutFWord8 x k -> writeBytes 1 (writeMemInBytes x) >> k+ PutFInt8 x k -> writeBytes 1 (writeMemInBytes x) >> k+ PutFWord16LE x k -> writeBytes 2 (writeMemInBytes x) >> k+ PutFInt16LE x k -> writeBytes 2 (writeMemInBytes x) >> k+ PutFWord24LE x k -> writeBytes 3 (writeMemInBytes x) >> k+ PutFInt24LE x k -> writeBytes 3 (writeMemInBytes x) >> k+ PutFWord32LE x k -> writeBytes 4 (writeMemInBytes x) >> k+ PutFInt32LE x k -> writeBytes 4 (writeMemInBytes x) >> k+ PutFWord64LE x k -> writeBytes 8 (writeMemInBytes x) >> k+ PutFInt64LE x k -> writeBytes 8 (writeMemInBytes x) >> k+ PutFFloatLE x k -> writeBytes 4 (writeMemInBytes x) >> k+ PutFDoubleLE x k -> writeBytes 8 (writeMemInBytes x) >> k+ PutFWord16BE x k -> writeBytes 2 (writeMemInBytes x) >> k+ PutFInt16BE x k -> writeBytes 2 (writeMemInBytes x) >> k+ PutFWord24BE x k -> writeBytes 3 (writeMemInBytes x) >> k+ PutFInt24BE x k -> writeBytes 3 (writeMemInBytes x) >> k+ PutFWord32BE x k -> writeBytes 4 (writeMemInBytes x) >> k+ PutFInt32BE x k -> writeBytes 4 (writeMemInBytes x) >> k+ PutFWord64BE x k -> writeBytes 8 (writeMemInBytes x) >> k+ PutFInt64BE x k -> writeBytes 8 (writeMemInBytes x) >> k+ PutFFloatBE x k -> writeBytes 4 (writeMemInBytes x) >> k+ PutFDoubleBE x k -> writeBytes 8 (writeMemInBytes x) >> k PutFShortByteString bc sbs k ->- writeBytes bc (writeSBSMem sbs bc) *> k+ writeBytes bc (writeSBSMem sbs bc) >> k PutFStaticSeq pss -> writeStaticSeq pss PutFStaticArray psa -> writeStaticArray psa PutFByteArray bc barr k ->- writeBytes bc (copyArrayMemInBytes barr 0 bc) *> k- PutFStaticHint (PutStaticHintF _ p k) -> mkPutEff p *> k+ writeBytes bc (copyArrayMemInBytes barr 0 bc) >> k+ PutFStaticHint (PutStaticHintF _ p k) -> mkPutEff p >> k -runPutRun :: WriteMem q m => PutRun q m a -> PutEnv (PrimState m) q -> m a+runPutRun :: (WriteMem q m) => PutRun q m a -> PutEnv (PrimState m) q -> m a runPutRun = runPutEff . iterPutRun -iterPutRun :: WriteMem q m => PutRun q m a -> PutEff q m a+iterPutRun :: (WriteMem q m) => PutRun q m a -> PutEff q m a iterPutRun act = iterT execPutRun (unPutRun act) -mkPutRun :: Monad m => PutM a -> PutRun q m a+mkPutRun :: PutM a -> PutRun q m a mkPutRun (PutM (F w)) = PutRun (w pure wrap) -mkPutEff :: WriteMem q m => PutM a -> PutEff q m a+mkPutEff :: (WriteMem q m) => PutM a -> PutEff q m a mkPutEff = iterPutRun . mkPutRun -runPutUnsafe :: WriteMem q m => ByteCount -> Put -> ByteCount -> q (PrimState m) -> m ByteCount-runPutUnsafe off act len mem = do+runPutInternal :: (WriteMem q m) => ByteCount -> Put -> ByteCount -> q (PrimState m) -> m ByteCount+runPutInternal off act len mem = do let eff = mkPutRun act cap = off + len st@(PutEnv offRef _ _) <- newPutEnv off cap mem@@ -377,42 +479,42 @@ runCountEff :: CountEff a -> ByteCount -> (Maybe a, ByteCount) runCountEff act = runState (runMaybeT (unCountEff act)) -newtype CountRun a = CountRun {unCountRun :: FreeT PutF CountEff a}+newtype CountRun a = CountRun {unCountRun :: FT PutF CountEff a} deriving newtype (Functor, Applicative, Monad) execCountRun :: PutF (CountEff a) -> CountEff a execCountRun = \case- PutFWord8 _ k -> State.modify' (1 +) *> k- PutFInt8 _ k -> State.modify' (1 +) *> k- PutFWord16LE _ k -> State.modify' (2 +) *> k- PutFInt16LE _ k -> State.modify' (2 +) *> k- PutFWord24LE _ k -> State.modify' (3 +) *> k- PutFInt24LE _ k -> State.modify' (3 +) *> k- PutFWord32LE _ k -> State.modify' (4 +) *> k- PutFInt32LE _ k -> State.modify' (4 +) *> k- PutFWord64LE _ k -> State.modify' (8 +) *> k- PutFInt64LE _ k -> State.modify' (8 +) *> k- PutFFloatLE _ k -> State.modify' (4 +) *> k- PutFDoubleLE _ k -> State.modify' (8 +) *> k- PutFWord16BE _ k -> State.modify' (2 +) *> k- PutFInt16BE _ k -> State.modify' (2 +) *> k- PutFWord24BE _ k -> State.modify' (3 +) *> k- PutFInt24BE _ k -> State.modify' (3 +) *> k- PutFWord32BE _ k -> State.modify' (4 +) *> k- PutFInt32BE _ k -> State.modify' (4 +) *> k- PutFWord64BE _ k -> State.modify' (8 +) *> k- PutFInt64BE _ k -> State.modify' (8 +) *> k- PutFFloatBE _ k -> State.modify' (4 +) *> k- PutFDoubleBE _ k -> State.modify' (8 +) *> k- PutFShortByteString bc _ k -> State.modify' (bc +) *> k+ PutFWord8 _ k -> State.modify' (1 +) >> k+ PutFInt8 _ k -> State.modify' (1 +) >> k+ PutFWord16LE _ k -> State.modify' (2 +) >> k+ PutFInt16LE _ k -> State.modify' (2 +) >> k+ PutFWord24LE _ k -> State.modify' (3 +) >> k+ PutFInt24LE _ k -> State.modify' (3 +) >> k+ PutFWord32LE _ k -> State.modify' (4 +) >> k+ PutFInt32LE _ k -> State.modify' (4 +) >> k+ PutFWord64LE _ k -> State.modify' (8 +) >> k+ PutFInt64LE _ k -> State.modify' (8 +) >> k+ PutFFloatLE _ k -> State.modify' (4 +) >> k+ PutFDoubleLE _ k -> State.modify' (8 +) >> k+ PutFWord16BE _ k -> State.modify' (2 +) >> k+ PutFInt16BE _ k -> State.modify' (2 +) >> k+ PutFWord24BE _ k -> State.modify' (3 +) >> k+ PutFInt24BE _ k -> State.modify' (3 +) >> k+ PutFWord32BE _ k -> State.modify' (4 +) >> k+ PutFInt32BE _ k -> State.modify' (4 +) >> k+ PutFWord64BE _ k -> State.modify' (8 +) >> k+ PutFInt64BE _ k -> State.modify' (8 +) >> k+ PutFFloatBE _ k -> State.modify' (4 +) >> k+ PutFDoubleBE _ k -> State.modify' (8 +) >> k+ PutFShortByteString bc _ k -> State.modify' (bc +) >> k PutFStaticSeq pss@(PutStaticSeqF _ _ _ _ k) -> let bc = putStaticSeqSize pss- in State.modify' (bc +) *> k+ in State.modify' (bc +) >> k PutFStaticArray psv@(PutStaticArrayF _ _ _ k) -> let bc = putStaticArraySize psv- in State.modify' (bc +) *> k- PutFByteArray bc _ k -> State.modify' (bc +) *> k- PutFStaticHint (PutStaticHintF bc _ k) -> State.modify' (bc +) *> k+ in State.modify' (bc +) >> k+ PutFByteArray bc _ k -> State.modify' (bc +) >> k+ PutFStaticHint (PutStaticHintF bc _ k) -> State.modify' (bc +) >> k runCountRun :: CountRun a -> ByteCount -> (Maybe a, ByteCount) runCountRun = runCountEff . iterCountRun@@ -431,14 +533,3 @@ let eff = mkCountRun act (_, bc) = runCountRun eff 0 in bc---- Put safe:--primOnExc :: PrimBase m => m a -> Maybe (IO ()) -> m a-primOnExc prim = maybe prim $ \onExc ->- unsafeIOToPrim (onException (unsafePrimToIO prim) onExc)--runPutInternal :: (PrimBase m, WriteMem q m) => ByteCount -> Put -> ByteCount -> (ByteCount -> ByteCount -> m (q (PrimState m), Maybe (IO ()))) -> (q (PrimState m) -> ByteCount -> ByteCount -> m z) -> m z-runPutInternal off act len mkMem useMem = do- (mem, rel) <- mkMem off len- primOnExc (runPutUnsafe off act len mem >>= useMem mem off) rel
src/Dahdit/Sizes.hs view
@@ -1,10 +1,9 @@+{-# LANGUAGE UndecidableInstances #-}+ module Dahdit.Sizes ( ByteCount (..) , ElemCount (..)- , ByteSized (..) , StaticByteSized (..)- , ViaStaticByteSized (..)- , byteSizeFoldable , staticByteSizeFoldable , byteSizeViaStatic )@@ -34,25 +33,13 @@ , Word64LE ) import Dahdit.Proxy (proxyFor, proxyForF)-import Data.ByteString.Short (ShortByteString)-import qualified Data.ByteString.Short as BSS import Data.Coerce (coerce) import Data.Default (Default)-import Data.Foldable (foldMap') import Data.Int (Int16, Int32, Int64, Int8)-import Data.IntMap (IntMap)-import qualified Data.IntMap as IntMap-import Data.IntSet (IntSet)-import qualified Data.IntSet as IntSet-import Data.Map.Strict (Map)-import qualified Data.Map.Strict as Map import Data.Proxy (Proxy (..))-import Data.Semigroup (Sum (..))-import Data.Sequence (Seq)-import Data.Set (Set)-import qualified Data.Set as Set import Data.ShortWord (Int24, Word24) import Data.Word (Word16, Word32, Word64, Word8)+import GHC.TypeLits (KnownNat, Nat, natVal) -- Counts @@ -64,279 +51,150 @@ deriving stock (Show) deriving newtype (Eq, Ord, Num, Enum, Real, Integral, Default) --- ByteSized--class ByteSized a where- byteSize :: a -> ByteCount--instance ByteSized () where- byteSize _ = 0--instance ByteSized Word8 where- byteSize _ = 1--instance ByteSized Int8 where- byteSize _ = 1--instance ByteSized Word16 where- byteSize _ = 2--instance ByteSized Int16 where- byteSize _ = 2--instance ByteSized Word24 where- byteSize _ = 3--instance ByteSized Int24 where- byteSize _ = 3--instance ByteSized Word32 where- byteSize _ = 4--instance ByteSized Int32 where- byteSize _ = 4--instance ByteSized Word64 where- byteSize _ = 8--instance ByteSized Int64 where- byteSize _ = 8--instance ByteSized Float where- byteSize _ = 4--instance ByteSized Double where- byteSize _ = 8--instance ByteSized Bool where- byteSize _ = 1--instance ByteSized Char where- byteSize _ = 1--instance ByteSized Int where- byteSize _ = 8--instance ByteSized Word16LE where- byteSize _ = 2--instance ByteSized Int16LE where- byteSize _ = 2--instance ByteSized Word24LE where- byteSize _ = 3--instance ByteSized Int24LE where- byteSize _ = 3--instance ByteSized Word32LE where- byteSize _ = 4--instance ByteSized Int32LE where- byteSize _ = 4--instance ByteSized Word64LE where- byteSize _ = 8--instance ByteSized Int64LE where- byteSize _ = 8--instance ByteSized FloatLE where- byteSize _ = 4--instance ByteSized DoubleLE where- byteSize _ = 8--instance StaticByteSized x => ByteSized (ViaFromIntegral x y) where- byteSize = byteSizeViaStatic--instance StaticByteSized le => ByteSized (ViaEndianPair le be) where- byteSize = byteSizeViaStatic--deriving via (ViaEndianPair Word16LE Word16BE) instance ByteSized Word16BE--deriving via (ViaEndianPair Int16LE Int16BE) instance ByteSized Int16BE--deriving via (ViaEndianPair Word24LE Word24BE) instance ByteSized Word24BE--deriving via (ViaEndianPair Int24LE Int24BE) instance ByteSized Int24BE--deriving via (ViaEndianPair Word32LE Word32BE) instance ByteSized Word32BE--deriving via (ViaEndianPair Int32LE Int32BE) instance ByteSized Int32BE--deriving via (ViaEndianPair Word64LE Word64BE) instance ByteSized Word64BE--deriving via (ViaEndianPair Int64LE Int64BE) instance ByteSized Int64BE--deriving via (ViaEndianPair FloatLE FloatBE) instance ByteSized FloatBE--deriving via (ViaEndianPair DoubleLE DoubleBE) instance ByteSized DoubleBE--instance ByteSized ShortByteString where- byteSize = coerce . BSS.length--instance ByteSized a => ByteSized [a] where- byteSize = byteSizeFoldable--instance ByteSized a => ByteSized (Seq a) where- byteSize = byteSizeFoldable--instance ByteSized a => ByteSized (Maybe a) where- byteSize = \case- Nothing -> 1- Just a -> 1 + byteSize a--instance (ByteSized b, ByteSized a) => ByteSized (Either b a) where- byteSize = \case- Left b -> 1 + byteSize b- Right a -> 1 + byteSize a--instance (ByteSized a, ByteSized b) => ByteSized (a, b) where- byteSize (a, b) = byteSize a + byteSize b--instance (ByteSized a, ByteSized b, ByteSized c) => ByteSized (a, b, c) where- byteSize (a, b, c) = byteSize a + byteSize b + byteSize c--instance (ByteSized a, ByteSized b, ByteSized c, ByteSized d) => ByteSized (a, b, c, d) where- byteSize (a, b, c, d) = byteSize a + byteSize b + byteSize c + byteSize d--instance (ByteSized a, ByteSized b, ByteSized c, ByteSized d, ByteSized e) => ByteSized (a, b, c, d, e) where- byteSize (a, b, c, d, e) = byteSize a + byteSize b + byteSize c + byteSize d + byteSize e--instance ByteSized a => ByteSized (Set a) where- byteSize = byteSize . Set.toAscList--instance (ByteSized k, ByteSized v) => ByteSized (Map k v) where- byteSize = byteSize . Map.toAscList--instance ByteSized IntSet where- byteSize = byteSize . IntSet.toAscList--instance ByteSized v => ByteSized (IntMap v) where- byteSize = byteSize . IntMap.toAscList- -- StaticByteSized -class ByteSized a => StaticByteSized a where+class (KnownNat (StaticSize a)) => StaticByteSized a where+ type StaticSize a :: Nat staticByteSize :: Proxy a -> ByteCount+ staticByteSize = fromInteger . natVal . staticByteProxy +staticByteProxy :: Proxy a -> Proxy (StaticSize a)+staticByteProxy _ = Proxy+ instance StaticByteSized () where+ type StaticSize () = 0 staticByteSize _ = 0 instance StaticByteSized Word8 where+ type StaticSize Word8 = 1 staticByteSize _ = 1 instance StaticByteSized Int8 where+ type StaticSize Int8 = 1 staticByteSize _ = 1 instance StaticByteSized Word16 where+ type StaticSize Word16 = 2 staticByteSize _ = 2 instance StaticByteSized Int16 where+ type StaticSize Int16 = 2 staticByteSize _ = 2 instance StaticByteSized Word24 where+ type StaticSize Word24 = 3 staticByteSize _ = 3 instance StaticByteSized Int24 where+ type StaticSize Int24 = 3 staticByteSize _ = 3 instance StaticByteSized Word32 where+ type StaticSize Word32 = 4 staticByteSize _ = 4 instance StaticByteSized Int32 where+ type StaticSize Int32 = 4 staticByteSize _ = 4 instance StaticByteSized Word64 where+ type StaticSize Word64 = 8 staticByteSize _ = 8 instance StaticByteSized Int64 where+ type StaticSize Int64 = 8 staticByteSize _ = 8 instance StaticByteSized Float where+ type StaticSize Float = 4 staticByteSize _ = 4 instance StaticByteSized Double where+ type StaticSize Double = 8 staticByteSize _ = 8 instance StaticByteSized Bool where+ type StaticSize Bool = 1 staticByteSize _ = 1 instance StaticByteSized Char where+ type StaticSize Char = 1 staticByteSize _ = 1 instance StaticByteSized Int where+ type StaticSize Int = 8 staticByteSize _ = 8 instance StaticByteSized Word16LE where+ type StaticSize Word16LE = 2 staticByteSize _ = 2 instance StaticByteSized Int16LE where+ type StaticSize Int16LE = 2 staticByteSize _ = 2 instance StaticByteSized Word24LE where+ type StaticSize Word24LE = 3 staticByteSize _ = 3 instance StaticByteSized Int24LE where+ type StaticSize Int24LE = 3 staticByteSize _ = 3 instance StaticByteSized Word32LE where+ type StaticSize Word32LE = 4 staticByteSize _ = 4 instance StaticByteSized Int32LE where+ type StaticSize Int32LE = 4 staticByteSize _ = 4 instance StaticByteSized Word64LE where+ type StaticSize Word64LE = 8 staticByteSize _ = 8 instance StaticByteSized Int64LE where+ type StaticSize Int64LE = 8 staticByteSize _ = 8 instance StaticByteSized FloatLE where+ type StaticSize FloatLE = 4 staticByteSize _ = 4 instance StaticByteSized DoubleLE where+ type StaticSize DoubleLE = 8 staticByteSize _ = 8 -instance StaticByteSized x => StaticByteSized (ViaFromIntegral x y) where+instance (StaticByteSized x, n ~ StaticSize x) => StaticByteSized (ViaFromIntegral n x y) where+ type StaticSize (ViaFromIntegral n x y) = n staticByteSize _ = staticByteSize (Proxy :: Proxy x) -instance StaticByteSized le => StaticByteSized (ViaEndianPair le be) where+instance (StaticByteSized le, n ~ StaticSize le) => StaticByteSized (ViaEndianPair n le be) where+ type StaticSize (ViaEndianPair n le be) = n staticByteSize _ = staticByteSize (Proxy :: Proxy le) -deriving via (ViaEndianPair Word16LE Word16BE) instance StaticByteSized Word16BE--deriving via (ViaEndianPair Int16LE Int16BE) instance StaticByteSized Int16BE--deriving via (ViaEndianPair Word24LE Word24BE) instance StaticByteSized Word24BE--deriving via (ViaEndianPair Int24LE Int24BE) instance StaticByteSized Int24BE--deriving via (ViaEndianPair Word32LE Word32BE) instance StaticByteSized Word32BE+deriving via (ViaEndianPair 2 Word16LE Word16BE) instance StaticByteSized Word16BE -deriving via (ViaEndianPair Int32LE Int32BE) instance StaticByteSized Int32BE+deriving via (ViaEndianPair 2 Int16LE Int16BE) instance StaticByteSized Int16BE -deriving via (ViaEndianPair Word64LE Word64BE) instance StaticByteSized Word64BE+deriving via (ViaEndianPair 3 Word24LE Word24BE) instance StaticByteSized Word24BE -deriving via (ViaEndianPair Int64LE Int64BE) instance StaticByteSized Int64BE+deriving via (ViaEndianPair 3 Int24LE Int24BE) instance StaticByteSized Int24BE -deriving via (ViaEndianPair FloatLE FloatBE) instance StaticByteSized FloatBE+deriving via (ViaEndianPair 4 Word32LE Word32BE) instance StaticByteSized Word32BE -deriving via (ViaEndianPair DoubleLE DoubleBE) instance StaticByteSized DoubleBE+deriving via (ViaEndianPair 4 Int32LE Int32BE) instance StaticByteSized Int32BE --- Via+deriving via (ViaEndianPair 8 Word64LE Word64BE) instance StaticByteSized Word64BE -newtype ViaStaticByteSized a = ViaStaticByteSized {unViaStaticByteSized :: a}+deriving via (ViaEndianPair 8 Int64LE Int64BE) instance StaticByteSized Int64BE -instance StaticByteSized a => ByteSized (ViaStaticByteSized a) where- byteSize _ = staticByteSize (Proxy :: Proxy a)+deriving via (ViaEndianPair 4 FloatLE FloatBE) instance StaticByteSized FloatBE -byteSizeFoldable :: (Foldable f, ByteSized a) => f a -> ByteCount-byteSizeFoldable = getSum . foldMap' (Sum . byteSize)+deriving via (ViaEndianPair 8 DoubleLE DoubleBE) instance StaticByteSized DoubleBE staticByteSizeFoldable :: (Foldable f, StaticByteSized a) => f a -> ByteCount staticByteSizeFoldable fa = staticByteSize (proxyForF fa) * coerce (length fa) -byteSizeViaStatic :: StaticByteSized a => a -> ByteCount+byteSizeViaStatic :: (StaticByteSized a) => a -> ByteCount byteSizeViaStatic = staticByteSize . proxyFor
test/Main.hs view
@@ -1,12 +1,17 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE UndecidableInstances #-}+ module Main (main) where -import Control.Monad.Primitive (PrimState)+import Control.Applicative (liftA2)+import Control.Monad (replicateM, (>=>))+import Control.Monad.Primitive (RealWorld) import Dahdit ( Binary (..)- , BinaryTarget (..)+ , BinaryGetTarget (..)+ , BinaryPutTarget (..) , BoolByte (..) , ByteCount (..)- , ByteSized (..) , ByteString , DoubleBE (..) , DoubleLE (..)@@ -15,6 +20,7 @@ , Generic , Get , GetError (..)+ , GetIncRequest (..) , Int16BE , Int16LE , Int24BE@@ -24,22 +30,27 @@ , Int64BE , Int64LE , LiftedPrimArray (..)- , MutBinaryTarget (..)+ , MutBinaryPutTarget (..) , Proxy (..) , Put , ShortByteString , StaticByteSized (..) , StaticBytes (..)+ , TermBytes16 (..)+ , TermBytes8 (..) , ViaGeneric (..) , ViaStaticGeneric (..) , Word16BE- , Word16LE+ , Word16LE (..) , Word24BE , Word24LE , Word32BE- , Word32LE+ , Word32LE (..) , Word64BE , Word64LE+ , decodeEnd+ , decodeInc+ , encode , getByteArray , getByteString , getDoubleBE@@ -64,6 +75,7 @@ , getStaticArray , getStaticSeq , getTarget+ , getText , getWithin , getWord16BE , getWord16LE@@ -97,6 +109,7 @@ , putSeq , putStaticArray , putStaticSeq+ , putText , putWord16BE , putWord16LE , putWord24BE@@ -114,59 +127,73 @@ import Data.ByteString.Short (ShortByteString (..)) import qualified Data.ByteString.Short as BSS import Data.Coerce (coerce)+import Data.IORef (modifyIORef', newIORef, readIORef, writeIORef) import Data.Int (Int16, Int32, Int64, Int8) import Data.Primitive.ByteArray (ByteArray (..), MutableByteArray, byteArrayFromList, freezeByteArray, newByteArray, sizeofMutableByteArray) import Data.Proxy (asProxyTypeOf)+import Data.Sequence (Seq (..)) import qualified Data.Sequence as Seq import Data.ShortWord (Int24, Word24) import Data.Vector.Storable (Vector) import qualified Data.Vector.Storable as VS-import Data.Vector.Storable.Mutable (MVector)+import Data.Vector.Storable.Mutable (IOVector) import qualified Data.Vector.Storable.Mutable as VSM import Data.Word (Word16, Word32, Word64, Word8) import GHC.Float (castWord32ToFloat, castWord64ToDouble)+import System.IO.Unsafe (unsafePerformIO)+import Test.Falsify.Generator (Gen)+import qualified Test.Falsify.Generator as FG+import qualified Test.Falsify.Predicate as FC+import Test.Falsify.Property (Property)+import qualified Test.Falsify.Property as FP+import qualified Test.Falsify.Range as FR import Test.Tasty (TestTree, defaultMain, testGroup)+import Test.Tasty.Falsify (testProperty) import Test.Tasty.HUnit (testCase, (@?=)) -class BinaryTarget z => CaseTarget z where- initSource :: [Word8] -> z- consumeSink :: z -> [Word8]+class (Eq z, Show z) => CaseTarget z where+ initSource :: [Word8] -> IO z+ consumeSink :: z -> IO [Word8]+ sliceBuffer :: z -> ByteCount -> ByteCount -> IO z instance CaseTarget ShortByteString where- initSource = BSS.pack- consumeSink = BSS.unpack+ initSource = pure . BSS.pack+ consumeSink = pure . BSS.unpack+ sliceBuffer buf off len = pure (BSS.take (coerce len) (BSS.drop (coerce off) buf)) instance CaseTarget ByteString where- initSource = BS.pack- consumeSink = BS.unpack+ initSource = pure . BS.pack+ consumeSink = pure . BS.unpack+ sliceBuffer buf off len = pure (BS.take (coerce len) (BS.drop (coerce off) buf)) instance CaseTarget (Vector Word8) where- initSource = VS.fromList- consumeSink = VS.toList+ initSource = pure . VS.fromList+ consumeSink = pure . VS.toList+ sliceBuffer buf off len = pure (VS.take (coerce len) (VS.drop (coerce off) buf)) -class MutBinaryTarget IO u => MutCaseTarget u where+class MutCaseTarget u where newSink :: ByteCount -> IO u freezeSink :: u -> IO [Word8] -instance (s ~ PrimState IO) => MutCaseTarget (MutableByteArray s) where+instance MutCaseTarget (MutableByteArray RealWorld) where newSink = newByteArray . unByteCount freezeSink u = fmap (\(ByteArray arr) -> BSS.unpack (SBS arr)) (freezeByteArray u 0 (sizeofMutableByteArray u)) -instance (s ~ PrimState IO) => MutCaseTarget (MVector s Word8) where+instance MutCaseTarget (IOVector Word8) where newSink = VSM.new . unByteCount- freezeSink = fmap consumeSink . VS.freeze+ freezeSink = VS.freeze >=> consumeSink data DynFoo = DynFoo !Word8 !Word16LE deriving stock (Eq, Show, Generic)- deriving (ByteSized, Binary) via (ViaGeneric DynFoo)+ deriving (Binary) via (ViaGeneric DynFoo) data StaFoo = StaFoo !Word8 !Word16LE deriving stock (Eq, Show, Generic)- deriving (ByteSized, StaticByteSized, Binary) via (ViaStaticGeneric StaFoo)+ deriving (StaticByteSized, Binary) via (ViaStaticGeneric StaFoo) data TagFoo = TagFooOne !Word8 | TagFooTwo !Word16LE deriving stock (Eq, Show, Generic)- deriving (ByteSized, Binary) via (ViaGeneric TagFoo)+ deriving (Binary) via (ViaGeneric TagFoo) type StaBytes = StaticBytes 2 @@ -176,11 +203,11 @@ data GetCase where GetCase :: (Show a, Eq a) => String -> Get a -> Maybe (ByteCount, ByteCount, a) -> [Word8] -> GetCase -runGetCase :: CaseTarget z => Proxy z -> GetCase -> TestTree+runGetCase :: (BinaryGetTarget z IO, CaseTarget z) => Proxy z -> GetCase -> TestTree runGetCase p (GetCase name getter mayRes buf) = testCase name $ do- let src = initSource buf `asProxyTypeOf` p- totLen = coerce (length buf)- (result, actOff) = getTarget getter src+ src <- initSource buf+ let totLen = coerce (length buf)+ (result, actOff) <- getTarget getter (src `asProxyTypeOf` p) case (result, mayRes) of (Left _, Nothing) -> pure () (Left err, Just (_, _, expecVal)) -> fail ("Got error <" ++ show err ++ ">, expected value <" ++ show expecVal ++ ">")@@ -193,18 +220,18 @@ data PutCase where PutCase :: String -> Put -> [Word8] -> PutCase -runPutCase :: CaseTarget z => Proxy z -> PutCase -> TestTree+runPutCase :: (BinaryPutTarget z IO, CaseTarget z) => Proxy z -> PutCase -> TestTree runPutCase p (PutCase name putter expecBs) = testCase name $ do let expecBc = coerce (length expecBs) estBc = runCount putter estBc @?= expecBc- let actSink = putTargetUnsafe putter expecBc `asProxyTypeOf` p- actBs = consumeSink actSink- actBc = coerce (length actBs)+ actSink <- putTargetUnsafe putter expecBc+ actBs <- consumeSink (actSink `asProxyTypeOf` p)+ let actBc = coerce (length actBs) actBs @?= expecBs actBc @?= expecBc -mutRunPutCase :: MutCaseTarget z => Proxy z -> PutCase -> TestTree+mutRunPutCase :: (MutBinaryPutTarget z IO, MutCaseTarget z) => Proxy z -> PutCase -> TestTree mutRunPutCase p (PutCase name putter expecBs) = testCase name $ do let expecBc = coerce (length expecBs) actSink <- fmap (`asProxyTypeOf` p) (newSink expecBc)@@ -255,7 +282,6 @@ , testCase "Int64BE" (byteSize @Int64BE 0 @?= 8) , testCase "FloatBE" (byteSize (FloatBE (castWord32ToFloat 0)) @?= 4) , testCase "DoubleBE" (byteSize (DoubleBE (castWord64ToDouble 0)) @?= 8)- , testCase "ShortByteString" (byteSize @ShortByteString (BSS.pack [0xEC, 0x5D]) @?= 2) , testCase "DynFoo" (byteSize (DynFoo 0xBB 0x5DEC) @?= 3) , testCase "StaFoo" (byteSize (StaFoo 0xBB 0x5DEC) @?= 3) , testCase "StaBytes" (byteSize (mkStaBytes "hi") @?= 2)@@ -340,6 +366,7 @@ , GetCase "DoubleLE" getDoubleLE (Just (8, 0, DoubleLE (castWord64ToDouble 0x5DEC6EFD12345678))) [0x78, 0x56, 0x34, 0x12, 0xFD, 0x6E, 0xEC, 0x5D] , GetCase "DoubleBE" getDoubleBE (Just (8, 0, DoubleBE (castWord64ToDouble 0x5DEC6EFD12345678))) [0x5D, 0xEC, 0x6E, 0xFD, 0x12, 0x34, 0x56, 0x78] , GetCase "ShortByteString" (getByteString 2) (Just (2, 1, BSS.pack [0xEC, 0x5D])) [0xEC, 0x5D, 0xBB]+ , GetCase "Text" (getText 2) (Just (2, 1, "hi")) [0x68, 0x69, 0xBB] , GetCase "Two Word8" ((,) <$> getWord8 <*> getWord8) (Just (2, 0, (0x5D, 0xBB))) [0x5D, 0xBB] , GetCase "Two Word16LE" ((,) <$> getWord16LE <*> getWord16LE) (Just (4, 0, (0x5DEC, 0x4020))) [0xEC, 0x5D, 0x20, 0x40] , GetCase "Seq" (getSeq 2 getWord16LE) (Just (4, 0, Seq.fromList [0x5DEC, 0x4020])) [0xEC, 0x5D, 0x20, 0x40]@@ -349,7 +376,9 @@ , GetCase "StaFoo" (get @StaFoo) (Just (3, 0, StaFoo 0xBB 0x5DEC)) [0xBB, 0xEC, 0x5D] , GetCase "getRemainingSize" getRemainingSize (Just (0, 3, 3)) [0xBB, 0xEC, 0x5D] , GetCase "getSkip" (getSkip 2) (Just (2, 1, ())) [0xBB, 0xEC, 0x5D]- , GetCase "getLookAhead" (getLookAhead getWord16LE) (Just (0, 3, 0x5DEC)) [0xEC, 0x5D, 0xBB]+ , GetCase "getLookAhead 0" (getLookAhead getWord16LE) (Just (0, 3, 0x5DEC)) [0xEC, 0x5D, 0xBB]+ , GetCase "getLookAhead 1" (getWord8 >> getLookAhead getWord16LE) (Just (1, 2, 0xBB5D)) [0xEC, 0x5D, 0xBB]+ , GetCase "getLookAhead 2" (getLookAhead (getWord8 >> getWord16LE)) (Just (0, 3, 0xBB5D)) [0xEC, 0x5D, 0xBB] , GetCase "getExact eq" (getExact 2 getWord16LE) (Just (2, 1, 0x5DEC)) [0xEC, 0x5D, 0xBB] , GetCase "getExact lt" (getExact 1 getWord16LE) Nothing [0xEC, 0x5D, 0xBB] , GetCase "getExact gt" (getExact 3 getWord16LE) Nothing [0xEC, 0x5D, 0xBB]@@ -363,9 +392,23 @@ , GetCase "StaBytes" (get @StaBytes) (Just (2, 1, mkStaBytes "hi")) [0x68, 0x69, 0x21] , GetCase "TagFoo (one)" (get @TagFoo) (Just (2, 0, TagFooOne 7)) [0x00, 0x07] , GetCase "TagFoo (two)" (get @TagFoo) (Just (3, 0, TagFooTwo 7)) [0x01, 0x07, 0x00]+ , GetCase "TB8 0" (get @TermBytes8) (Just (1, 0, TermBytes8 BSS.empty)) [0]+ , GetCase "TB8 1" (get @TermBytes8) (Just (2, 0, TermBytes8 (BSS.pack [1]))) [1, 0]+ , GetCase "TB8 2" (get @TermBytes8) (Just (3, 0, TermBytes8 (BSS.pack [1, 2]))) [1, 2, 0]+ , GetCase "TB8 3" (get @TermBytes8) (Just (4, 0, TermBytes8 (BSS.pack [1, 2, 3]))) [1, 2, 3, 0]+ , GetCase "TB16 0" (get @TermBytes16) (Just (2, 0, TermBytes16 BSS.empty)) [0, 0]+ , GetCase "TB16 1" (get @TermBytes16) (Just (2, 0, TermBytes16 (BSS.pack [1]))) [1, 0]+ , GetCase "TB16 2" (get @TermBytes16) (Just (4, 0, TermBytes16 (BSS.pack [1, 2]))) [1, 2, 0, 0]+ , GetCase "TB16 3" (get @TermBytes16) (Just (4, 0, TermBytes16 (BSS.pack [1, 2, 3]))) [1, 2, 3, 0]+ , GetCase "Seq Word16LE" (get @(Seq Word16LE)) (Just (12, 0, Seq.fromList [0xEC, 0x5D])) [2, 0, 0, 0, 0, 0, 0, 0, 0xEC, 0, 0x5D, 0]+ , GetCase+ "Seq WordX"+ (get @(Seq WordX))+ (Just (18, 0, Seq.fromList [WordX32 0, WordX32 0]))+ [2, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 4, 0, 0, 0, 0] ] -testGet :: CaseTarget z => String -> Proxy z -> TestTree+testGet :: (BinaryGetTarget z IO, CaseTarget z) => String -> Proxy z -> TestTree testGet n p = testGroup ("get (" ++ n ++ ")") (fmap (runGetCase p) getCases) putCases :: [PutCase]@@ -393,6 +436,7 @@ , PutCase "DoubleLE" (putDoubleLE (DoubleLE (castWord64ToDouble 0x5DEC6EFD12345678))) [0x78, 0x56, 0x34, 0x12, 0xFD, 0x6E, 0xEC, 0x5D] , PutCase "DoubleBE" (putDoubleBE (DoubleBE (castWord64ToDouble 0x5DEC6EFD12345678))) [0x5D, 0xEC, 0x6E, 0xFD, 0x12, 0x34, 0x56, 0x78] , PutCase "ShortByteString" (putByteString (BSS.pack [0xEC, 0x5D])) [0xEC, 0x5D]+ , PutCase "Text" (putText "hi") [0x68, 0x69] , PutCase "Two Word8" (putWord8 0x5D *> putWord8 0xBB) [0x5D, 0xBB] , PutCase "Two Word16LE" (putWord16LE 0x5DEC *> putWord16LE 0x4020) [0xEC, 0x5D, 0x20, 0x40] , PutCase "Seq" (putSeq putWord16LE (Seq.fromList [0x5DEC, 0x4020])) [0xEC, 0x5D, 0x20, 0x40]@@ -409,9 +453,40 @@ , PutCase "StaBytes (more)" (put (mkStaBytes "hi!")) [0x68, 0x69] , PutCase "TagFoo (one)" (put (TagFooOne 7)) [0x00, 0x07] , PutCase "TagFoo (two)" (put (TagFooTwo 7)) [0x01, 0x07, 0x00]+ , PutCase "TB8 0" (put (TermBytes8 BSS.empty)) [0]+ , PutCase "TB8 1" (put (TermBytes8 (BSS.pack [1]))) [1, 0]+ , PutCase "TB8 2" (put (TermBytes8 (BSS.pack [1, 2]))) [1, 2, 0]+ , PutCase "TB8 3" (put (TermBytes8 (BSS.pack [1, 2, 3]))) [1, 2, 3, 0]+ , PutCase "TB16 0" (put (TermBytes16 BSS.empty)) [0, 0]+ , PutCase "TB16 1" (put (TermBytes16 (BSS.pack [1]))) [1, 0]+ , PutCase "TB16 2" (put (TermBytes16 (BSS.pack [1, 2]))) [1, 2, 0, 0]+ , PutCase "TB16 3" (put (TermBytes16 (BSS.pack [1, 2, 3]))) [1, 2, 3, 0]+ , PutCase "Seq Word16LE" (put @(Seq Word16LE) (Seq.fromList [0xEC, 0x5D])) [2, 0, 0, 0, 0, 0, 0, 0, 0xEC, 0, 0x5D, 0]+ , PutCase+ "Seq WordX"+ (put @(Seq WordX) (Seq.fromList [WordX32 0, WordX32 0]))+ [ 2+ , 0+ , 0+ , 0+ , 0+ , 0+ , 0+ , 0+ , 4+ , 0+ , 0+ , 0+ , 0+ , 4+ , 0+ , 0+ , 0+ , 0+ ] ] -testPut :: CaseTarget z => String -> Proxy z -> TestTree+testPut :: (BinaryPutTarget z IO, CaseTarget z) => String -> Proxy z -> TestTree testPut n p = testGroup ("put (" ++ n ++ ")") (fmap (runPutCase p) putCases) testLiftedPrimArray :: TestTree@@ -421,24 +496,109 @@ sizeofLiftedPrimArray arr @?= 6 lengthLiftedPrimArray arr @?= 3 -testGetOffset :: CaseTarget z => String -> Proxy z -> TestTree+testGetOffset :: (BinaryGetTarget z IO, CaseTarget z) => String -> Proxy z -> TestTree testGetOffset n p = testCase ("get offset (" ++ n ++ ")") $ do let buf = [0x12, 0x34, 0x56, 0x78]- src = initSource buf `asProxyTypeOf` p- (ez1, c1) = getTargetOffset 0 getWord8 src+ src <- initSource buf+ (ez1, c1) <- getTargetOffset 0 getWord8 (src `asProxyTypeOf` p) ez1 @?= Right 0x12 c1 @?= 1- let (ez2, c2) = getTargetOffset 1 getWord16LE src+ (ez2, c2) <- getTargetOffset 1 getWord16LE src ez2 @?= Right 0x5634 c2 @?= 3- let (ez3, c3) = getTargetOffset 3 getWord16LE src- ez3 @?= Left (GetErrorParseNeed "Word16LE" 1 2)+ (ez3, c3) <- getTargetOffset 3 getWord16LE src+ ez3 @?= Left (GetErrorGlobalCap "Word16LE" 1 2) c3 @?= 3 -testMutPut :: MutCaseTarget u => String -> Proxy u -> TestTree+data WordX+ = WordX8 !Word8+ | WordX16 !Word16LE+ | WordX32 !Word32LE+ deriving stock (Eq, Ord, Show)++instance Binary WordX where+ byteSize =+ succ . \case+ WordX8 _ -> 1+ WordX16 _ -> 2+ WordX32 _ -> 4+ get = do+ w <- get @Word8+ case w of+ 1 -> fmap WordX8 get+ 2 -> fmap WordX16 get+ 4 -> fmap WordX32 get+ _ -> fail ("Bad size for WordX: " ++ show w)+ put = \case+ WordX8 w -> put @Word8 1 >> put w+ WordX16 w -> put @Word8 2 >> put w+ WordX32 w -> put @Word8 4 >> put w++wordXGen :: Gen WordX+wordXGen = FG.choose gen8 (FG.choose gen16 gen32)+ where+ gen8 = fmap WordX8 (FG.inRange (FR.between (0, maxBound)))+ gen16 = fmap (WordX16 . Word16LE) (FG.inRange (FR.between (0, maxBound)))+ gen32 = fmap (WordX32 . Word32LE) (FG.inRange (FR.between (0, maxBound)))++takeDiff :: (CaseTarget z) => z -> ByteCount -> ByteCount -> ByteCount -> [ByteCount] -> IO ([ByteCount], (ByteCount, z))+takeDiff z pos had diff = go 0+ where+ go !acc = \case+ y : ys | acc < diff -> go (acc + y) ys+ ys -> do+ zz <- sliceBuffer z pos (had + acc)+ pure (ys, (acc, zz))++assertEq :: (Eq a, Show a) => a -> a -> Property ()+assertEq x y = FP.assert (FC.eq FC..$ ("LHS", x) FC..$ ("RHS", y))++hackLiftIO :: IO a -> Property a+hackLiftIO = pure . unsafePerformIO++testGetInc :: (BinaryPutTarget z IO, CaseTarget z) => String -> Proxy z -> TestTree+testGetInc n p = testProperty ("get inc (" ++ n ++ ")") $ do+ -- Generate some random elements+ numElems <- FP.gen @Int (FG.inRange (FR.between (0, 20)))+ xs <- FP.gen (replicateM numElems wordXGen)+ -- First some sanity checks that encode/decode work+ assertEq (length xs) numElems+ wholeBuf <- hackLiftIO (encode xs)+ (exs, totLen) <- hackLiftIO (decodeEnd (wholeBuf `asProxyTypeOf` p))+ case exs of+ Left err -> fail (show err)+ Right xs' -> do+ assertEq xs' xs+ assertEq totLen (byteSize xs)+ wholeBuf' <- hackLiftIO (sliceBuffer wholeBuf 0 totLen)+ assertEq wholeBuf' wholeBuf+ -- Shuffle list to come up with splits and test incremental+ ys <- FP.gen (FG.shuffle (8 : fmap byteSize xs))+ ysRef <- hackLiftIO (newIORef ys)+ sentRef <- hackLiftIO (newIORef 0)+ let cb (GetIncRequest pos _ len) = do+ sent <- readIORef sentRef+ let had = sent - pos+ let diff = len - had+ ys' <- readIORef ysRef+ (ys'', (bufLen, buf)) <- takeDiff wholeBuf pos had diff ys'+ writeIORef ysRef ys''+ modifyIORef' sentRef (+ bufLen)+ pure $+ if bufLen == 0+ then Nothing+ else Just (buf `asProxyTypeOf` p)+ (ezs, totLen', _) <- hackLiftIO (decodeInc (Just totLen) cb)+ case ezs of+ Left err -> fail (show err)+ Right zs -> do+ assertEq zs xs+ assertEq totLen' totLen++testMutPut :: (MutBinaryPutTarget z IO, MutCaseTarget z) => String -> Proxy z -> TestTree testMutPut n p = testGroup ("mut put (" ++ n ++ ")") (fmap (mutRunPutCase p) putCases) -testMutPutOffset :: MutCaseTarget u => String -> Proxy u -> TestTree+testMutPutOffset :: (MutBinaryPutTarget z IO, MutCaseTarget z) => String -> Proxy z -> TestTree testMutPutOffset n p = testCase ("mut put offset (" ++ n ++ ")") $ do u <- newSink 4 c1 <- mutPutTargetOffset 0 (putWord8 0x12) u@@ -446,11 +606,20 @@ c2 <- mutPutTargetOffset 1 (putWord16LE 0x5634) u c2 @?= 3 x <- freezeSink (u `asProxyTypeOf` p)- x @?= [0x12, 0x34, 0x56, 0]- pure ()+ take 3 x @?= [0x12, 0x34, 0x56]+ -- Use this opportunity to test getting+ (w, h) <- getTarget (liftA2 (,) (get @Word8) (get @Word16LE)) u+ w @?= Right (0x12, 0x5634)+ h @?= 3+ (y, i) <- getTargetOffset 0 (get @Word8) u+ y @?= Right 0x12+ i @?= 1+ (z, j) <- getTargetOffset 1 (get @Word16LE) u+ z @?= Right 0x5634+ j @?= 3 data TargetDef where- TargetDef :: CaseTarget z => String -> Proxy z -> TargetDef+ TargetDef :: (BinaryPutTarget z IO, CaseTarget z) => String -> Proxy z -> TargetDef targets :: [TargetDef] targets =@@ -460,12 +629,12 @@ ] data MutTargetDef where- MutTargetDef :: MutCaseTarget u => String -> Proxy u -> MutTargetDef+ MutTargetDef :: (MutBinaryPutTarget z IO, MutCaseTarget z) => String -> Proxy z -> MutTargetDef mutTargets :: [MutTargetDef] mutTargets =- [ MutTargetDef "MutableByteArray" (Proxy :: Proxy (MutableByteArray (PrimState IO)))- , MutTargetDef "MVector" (Proxy :: Proxy (MVector (PrimState IO) Word8))+ [ MutTargetDef "MutableByteArray" (Proxy :: Proxy (MutableByteArray RealWorld))+ , MutTargetDef "IOVector" (Proxy :: Proxy (IOVector Word8)) ] testDahdit :: TestTree@@ -476,8 +645,9 @@ targetTrees = targets >>= \(TargetDef name prox) -> [ testGet name prox- , testPut name prox , testGetOffset name prox+ , testGetInc name prox+ , testPut name prox ] mutTargetTrees = mutTargets >>= \(MutTargetDef name prox) ->