Safe Haskell | None |
---|---|
Language | Haskell2010 |
NamedStructure definition for sequences of bits.
This module provides the core data types and functions for conversion of finite bit sequences from an to conventional (Haskell) data types.
Non-compressed, non-random finite bit sequences generated by programs are usually compositions of bytes and multi byte words, and a ton of Haskell libraries exist for the serialization and deserialization of ByteStrings.
This module allows the definition of a structure i.e. a very simple grammar, which allows functions in this library to read and write single bytes, words and bits.
Also complete bit sequence may be constructed or destructed from and to Haskell types.
Further more, the Record may contain dependent sub-sequences, for example to express Record that precede a length field before a repetitive block data.
Antother example for dependent sequences is fields whose presence depends on flags preceding them.
This library is also designed with zero copying in mind.
It should be emphasized that binary deserialization is not to be confused with binary destructuring. While the former usually involves copying all regular sub sequences from the input to a value of a certain type, the later merely requires to peek into the sequeuence at a certain position and deserializing a sub sequence. The starting position and the interpretation are governed by the strucuture applied to the sequence.
Synopsis
- data Structure (sizeType :: StructureSizeType) where
- type FixStructure = Structure FixSize
- type VariableStructure = Structure VarSize
- data StructureSizeType
- type family GetStructureSize (t :: Extends (Structure FixSize)) :: Nat
- type family PrettyStructure (struct :: Extends (Structure sizeType)) :: PrettyType
- data EmptyStructure :: Extends (Structure FixSize)
- data Record :: [Extends (Named (Structure sizeType))] -> Extends (Structure sizeType)
- type family (a :: Extends (Named (Structure sizeType))) <> (b :: k) :: Extends (Structure sizeType) where ...
- type family PrettyRecord (xs :: [Extends (Named (Structure sizeType))]) :: PrettyType where ...
- data BitSequence (length :: Nat) :: Extends (Structure FixSize)
- type family WithValidBitSequenceLength (length :: Nat) (out :: k) :: k where ...
- type family (name :: Symbol) // (length :: Nat) :: Extends (Named (Structure FixSize)) where ...
- data LiteralStructure a :: Extends (Structure FixSize)
- data Padded (literal :: Either j j) (struct :: Extends (Structure FixSize)) :: Extends (Structure FixSize)
- type family GetPaddingSize literal (struct :: Extends (Structure FixSize)) :: Nat where ...
- type family PaddedStructureValidateSize literal (rhs :: Extends (Structure FixSize)) (out :: k) :: k where ...
- data Alias :: Extends (Structure FixSize) -> Extends (Structure FixSize) -> Extends (Structure FixSize)
- type family AliasStructureValidateSize (lhs :: Extends (Structure FixSize)) (rhs :: Extends (Structure FixSize)) (out :: k) :: k where ...
- data TypeStructure :: Type -> Extends (Structure FixSize)
- type U8 = TypeStructure Word8
- type S8 = TypeStructure Int8
- type FlagStructure = TypeStructure Bool
- data IntegerStructure :: Nat -> Sign -> Endianess -> Extends (Structure FixSize) where
- S16LE :: Int16 -> IntegerStructure 16 Signed LE MkFixStructure
- S16BE :: Int16 -> IntegerStructure 16 Signed BE MkFixStructure
- U16LE :: Word16 -> IntegerStructure 16 Unsigned LE MkFixStructure
- U16BE :: Word16 -> IntegerStructure 16 Unsigned BE MkFixStructure
- S32LE :: Int32 -> IntegerStructure 32 Signed LE MkFixStructure
- S32BE :: Int32 -> IntegerStructure 32 Signed BE MkFixStructure
- U32LE :: Word32 -> IntegerStructure 32 Unsigned LE MkFixStructure
- U32BE :: Word32 -> IntegerStructure 32 Unsigned BE MkFixStructure
- S64LE :: Int64 -> IntegerStructure 64 Signed LE MkFixStructure
- S64BE :: Int64 -> IntegerStructure 64 Signed BE MkFixStructure
- U64LE :: Word64 -> IntegerStructure 64 Unsigned LE MkFixStructure
- U64BE :: Word64 -> IntegerStructure 64 Unsigned BE MkFixStructure
- data Endianess
- data Sign
- type family IntegerStructureValidateLength (n :: Nat) (out :: k) where ...
- type U n e = IntegerStructure n Unsigned e
- type S n e = IntegerStructure n Signed e
- data ConditionalStructure (condition :: Bool) (ifStruct :: Extends (Structure FixSize)) (elseStruct :: Extends (Structure FixSize)) :: Extends (Structure FixSize)
- showStructure :: forall proxy (struct :: Extends (Structure FixSize)). PrettyTypeShow (PrettyStructure struct) => proxy struct -> String
- data BoolProxy (t :: Bool) where
- _typeSpecGetStructureSize :: BoolProxy (testBool :: Bool) -> Expect [GetStructureSize U8 `ShouldBe` 8, GetStructureSize EmptyStructure `ShouldBe` 0, GetStructureSize (Record [Name "x" U8, Name "y" U8]) `ShouldBe` 16, GetStructureSize (S 16 BE) `ShouldBe` 16, GetStructureSize (ConditionalStructure testBool (U 32 LE) S8) `ShouldBe` If testBool 32 8, GetStructureSize (("field 1" // 3) <> (("field 2" // 2) <> (("field 3" // 5) <> Name "field 4" (("field 4.1" // 3) <> ("field 4.2" // 6))))) `ShouldBe` 19, GetStructureSize (Alias (BitSequence 4) (LiteralStructure (Bits '[1, 0, 0, 1]))) `ShouldBe` 4, GetStructureSize (Padded (Left (Bits '[1, 0, 1, 0, 1, 0, 1, 0])) (("x" // 1) <> ("y" // 2))) `ShouldBe` 8, GetStructureSize (Padded (Right (Bits '[1, 0, 1, 0, 1, 0, 1, 0])) (Anonymous ("x" // 9))) `ShouldBe` 16, GetStructureSize (Padded (Left (Bits '[1, 0, 1, 0, 1, 0, 1, 0])) (Anonymous ("x" // 22))) `ShouldBe` 24, GetStructureSize (Padded (Right (Bits '[1, 0, 1, 0, 1, 0, 1, 0])) (Anonymous ("x" // 33))) `ShouldBe` 40, GetStructureSize (Padded (Right (To (Sequence Word8 Nat) '[0, 255, 0, 255])) (Anonymous ("x" // 10))) `ShouldBe` 32]
- _prettySpec :: String
Documentation
data Structure (sizeType :: StructureSizeType) where Source #
Phantom type for structures
Instances
type PrettyStructure (Anonymous (Name name struct) :: Structure sizeType -> Type) Source # | |
Defined in Data.Type.BitRecords.Structure type PrettyStructure (Anonymous (Name name struct) :: Structure sizeType -> Type) = name <:> PrettyStructure struct | |
type ToPretty (struct :: Extends (Structure sizeType)) Source # | |
Defined in Data.Type.BitRecords.Structure | |
type GetStructureSize (Anonymous (Name name struct)) Source # | |
Defined in Data.Type.BitRecords.Structure | |
type GetStructureSize (Record (x ': xs)) Source # | |
Defined in Data.Type.BitRecords.Structure type GetStructureSize (Record (x ': xs)) = GetStructureSize (Anonymous x) + GetStructureSize (Record xs) | |
type GetStructureSize (Record ([] :: [Extends (Named (Structure FixSize))])) Source # | |
Defined in Data.Type.BitRecords.Structure |
type VariableStructure = Structure VarSize Source #
Structure
s that have no statically known fixed size.
data StructureSizeType Source #
Phantom type indicating that if a Structure
has a statically known size.
type family GetStructureSize (t :: Extends (Structure FixSize)) :: Nat Source #
The number of bits that a structure with a predetermined fixed size requires.
Instances
type family PrettyStructure (struct :: Extends (Structure sizeType)) :: PrettyType Source #
Support for Pretty Printing Structure
Types
Instances
data EmptyStructure :: Extends (Structure FixSize) Source #
Empty Structure
Instances
type GetStructureSize EmptyStructure Source # | |
Defined in Data.Type.BitRecords.Structure | |
type PrettyStructure EmptyStructure Source # | |
Defined in Data.Type.BitRecords.Structure |
data Record :: [Extends (Named (Structure sizeType))] -> Extends (Structure sizeType) Source #
Instances
type PrettyStructure (Record xs :: Structure sizeType -> Type) Source # | |
Defined in Data.Type.BitRecords.Structure | |
type GetStructureSize (Record (x ': xs)) Source # | |
Defined in Data.Type.BitRecords.Structure type GetStructureSize (Record (x ': xs)) = GetStructureSize (Anonymous x) + GetStructureSize (Record xs) | |
type GetStructureSize (Record ([] :: [Extends (Named (Structure FixSize))])) Source # | |
Defined in Data.Type.BitRecords.Structure |
type family (a :: Extends (Named (Structure sizeType))) <> (b :: k) :: Extends (Structure sizeType) where ... infixr 6 Source #
type family PrettyRecord (xs :: [Extends (Named (Structure sizeType))]) :: PrettyType where ... Source #
Internal function to render Record
s
PrettyRecord '[] = PrettyEmpty | |
PrettyRecord (x ': xs) = (PutStr "-" <+> PrettyStructure (Anonymous x)) <$$> PrettyRecord xs |
data BitSequence (length :: Nat) :: Extends (Structure FixSize) Source #
A fixed length sequence of bits.
Instances
type PrettyStructure (BitSequence length :: Structure FixSize -> Type) Source # | |
Defined in Data.Type.BitRecords.Structure type PrettyStructure (BitSequence length :: Structure FixSize -> Type) = WithValidBitSequenceLength length (PutStr "BitSequence " <+> PutNat length) | |
type GetStructureSize (BitSequence length) Source # | |
Defined in Data.Type.BitRecords.Structure |
type family WithValidBitSequenceLength (length :: Nat) (out :: k) :: k where ... Source #
Internal function to validate that a BitSequence
has a valid length.
type family (name :: Symbol) // (length :: Nat) :: Extends (Named (Structure FixSize)) where ... infixr 7 Source #
An alias to construct a Name
d BitSequence
with the given number of bits
name // length = WithValidBitSequenceLength length (Name name (BitSequence length)) |
data LiteralStructure a :: Extends (Structure FixSize) Source #
A constant, fixed length sequence of bits, generated by a type level LiteralFamily
.
Instances
type PrettyStructure (LiteralStructure (Value s k1 x) :: Structure FixSize -> Type) Source # | |
Defined in Data.Type.BitRecords.Structure type PrettyStructure (LiteralStructure (Value s k1 x) :: Structure FixSize -> Type) = "LiteralStructure" <:> Pretty s x | |
type GetStructureSize (LiteralStructure (Value s k1 x)) Source # | |
Defined in Data.Type.BitRecords.Structure |
data Padded (literal :: Either j j) (struct :: Extends (Structure FixSize)) :: Extends (Structure FixSize) Source #
Pad a Structure
to a structure with a length being a multiple of the length of the literal.
Instances
type PrettyStructure (Padded (either literal) struct :: Structure FixSize -> Type) Source # | |
Defined in Data.Type.BitRecords.Structure type PrettyStructure (Padded (either literal) struct :: Structure FixSize -> Type) = PrettyParens (PrettyStructure struct) <+> (("padded with" <:> PutNat (GetPaddingSize literal struct)) <+> PutStr "bits.") | |
type GetStructureSize (Padded (either literal) struct) Source # | |
Defined in Data.Type.BitRecords.Structure type GetStructureSize (Padded (either literal) struct) = PaddedStructureValidateSize literal struct (GetPaddingSize literal struct + GetStructureSize struct) |
type family GetPaddingSize literal (struct :: Extends (Structure FixSize)) :: Nat where ... Source #
Type function calculating the number of padding bits requred to pad struct
to a multiple of
literal size.
GetPaddingSize (Value s k (x :: k)) y = (SizeOf s x - (GetStructureSize y `Mod` SizeOf s x)) `Mod` SizeOf s x |
type family PaddedStructureValidateSize literal (rhs :: Extends (Structure FixSize)) (out :: k) :: k where ... Source #
data Alias :: Extends (Structure FixSize) -> Extends (Structure FixSize) -> Extends (Structure FixSize) Source #
Alias structures, the size of the an alias structure is equal to the size of both elements.
Instances
type PrettyStructure (Alias lhs rhs :: Structure FixSize -> Type) Source # | |
Defined in Data.Type.BitRecords.Structure type PrettyStructure (Alias lhs rhs :: Structure FixSize -> Type) = AliasStructureValidateSize lhs rhs ("Alias" <:$$--> (PrettyStructure lhs <$$> PrettyStructure rhs)) | |
type GetStructureSize (Alias lhs rhs) Source # | |
Defined in Data.Type.BitRecords.Structure |
type family AliasStructureValidateSize (lhs :: Extends (Structure FixSize)) (rhs :: Extends (Structure FixSize)) (out :: k) :: k where ... Source #
Internal function to validate that both arguments to Alias
have a valid length. The lengths are valid
iff the right hand side requires the same amount of bits as the left hand side.
If necessary, one can always pad the right hand side to match the left hand side using Padded
.
AliasStructureValidateSize lhs rhs out = If (GetStructureSize rhs == GetStructureSize lhs) out (TypeError ((((((((Text "Cannot alias structures of different size " :<>: ShowType rhs) :<>: Text " requires ") :<>: ShowType (GetStructureSize rhs)) :<>: Text " bits, but ") :<>: ShowType lhs) :<>: Text " requires ") :<>: ShowType (GetStructureSize lhs)) :<>: Text " bits.")) |
Integer Sequences
data TypeStructure :: Type -> Extends (Structure FixSize) Source #
A Wrapper for Haskell types. Users should implement the GetStructureSize
and Constructor
instances.
Instances
type PrettyStructure (TypeStructure Bool) Source # | |
Defined in Data.Type.BitRecords.Structure | |
type PrettyStructure (TypeStructure Int8) Source # | |
Defined in Data.Type.BitRecords.Structure | |
type PrettyStructure (TypeStructure Word8) Source # | |
Defined in Data.Type.BitRecords.Structure | |
type GetStructureSize (TypeStructure Bool) Source # | |
Defined in Data.Type.BitRecords.Structure | |
type GetStructureSize (TypeStructure Int8) Source # | |
Defined in Data.Type.BitRecords.Structure | |
type GetStructureSize (TypeStructure Word8) Source # | |
Defined in Data.Type.BitRecords.Structure |
type U8 = TypeStructure Word8 Source #
An usigned 8-bit integer
type S8 = TypeStructure Int8 Source #
A signed 8-bit integer
type FlagStructure = TypeStructure Bool Source #
A single bit structure
data IntegerStructure :: Nat -> Sign -> Endianess -> Extends (Structure FixSize) where Source #
(Structure 'FixSize) holding integral numbers
S16LE :: Int16 -> IntegerStructure 16 Signed LE MkFixStructure | |
S16BE :: Int16 -> IntegerStructure 16 Signed BE MkFixStructure | |
U16LE :: Word16 -> IntegerStructure 16 Unsigned LE MkFixStructure | |
U16BE :: Word16 -> IntegerStructure 16 Unsigned BE MkFixStructure | |
S32LE :: Int32 -> IntegerStructure 32 Signed LE MkFixStructure | |
S32BE :: Int32 -> IntegerStructure 32 Signed BE MkFixStructure | |
U32LE :: Word32 -> IntegerStructure 32 Unsigned LE MkFixStructure | |
U32BE :: Word32 -> IntegerStructure 32 Unsigned BE MkFixStructure | |
S64LE :: Int64 -> IntegerStructure 64 Signed LE MkFixStructure | |
S64BE :: Int64 -> IntegerStructure 64 Signed BE MkFixStructure | |
U64LE :: Word64 -> IntegerStructure 64 Unsigned LE MkFixStructure | |
U64BE :: Word64 -> IntegerStructure 64 Unsigned BE MkFixStructure |
Instances
type PrettyStructure (IntegerStructure n s e :: Structure FixSize -> Type) Source # | |
Defined in Data.Type.BitRecords.Structure | |
type GetStructureSize (IntegerStructure n s e) Source # | |
Defined in Data.Type.BitRecords.Structure |
type family IntegerStructureValidateLength (n :: Nat) (out :: k) where ... Source #
Internal function to ensure that the length of an IntegerStructure
is 16,32 or 64
type U n e = IntegerStructure n Unsigned e Source #
An unsigned integer structure
type S n e = IntegerStructure n Signed e Source #
data ConditionalStructure (condition :: Bool) (ifStruct :: Extends (Structure FixSize)) (elseStruct :: Extends (Structure FixSize)) :: Extends (Structure FixSize) Source #
Conditional structure, since this is equivalent to If
this might be removed (TODO)
Instances
type PrettyStructure (ConditionalStructure False l r :: Structure FixSize -> Type) Source # | |
Defined in Data.Type.BitRecords.Structure type PrettyStructure (ConditionalStructure False l r :: Structure FixSize -> Type) = PrettyStructure r | |
type PrettyStructure (ConditionalStructure True l r :: Structure FixSize -> Type) Source # | |
Defined in Data.Type.BitRecords.Structure type PrettyStructure (ConditionalStructure True l r :: Structure FixSize -> Type) = PrettyStructure l | |
type GetStructureSize (ConditionalStructure False l r) Source # | |
Defined in Data.Type.BitRecords.Structure | |
type GetStructureSize (ConditionalStructure True l r) Source # | |
Defined in Data.Type.BitRecords.Structure |
Structure PrettyType Printing
showStructure :: forall proxy (struct :: Extends (Structure FixSize)). PrettyTypeShow (PrettyStructure struct) => proxy struct -> String Source #
Render struct
to a pretty, human readable form. Internally this is a wrapper
around ptShow
using PrettyStructure
.
_typeSpecGetStructureSize :: BoolProxy (testBool :: Bool) -> Expect [GetStructureSize U8 `ShouldBe` 8, GetStructureSize EmptyStructure `ShouldBe` 0, GetStructureSize (Record [Name "x" U8, Name "y" U8]) `ShouldBe` 16, GetStructureSize (S 16 BE) `ShouldBe` 16, GetStructureSize (ConditionalStructure testBool (U 32 LE) S8) `ShouldBe` If testBool 32 8, GetStructureSize (("field 1" // 3) <> (("field 2" // 2) <> (("field 3" // 5) <> Name "field 4" (("field 4.1" // 3) <> ("field 4.2" // 6))))) `ShouldBe` 19, GetStructureSize (Alias (BitSequence 4) (LiteralStructure (Bits '[1, 0, 0, 1]))) `ShouldBe` 4, GetStructureSize (Padded (Left (Bits '[1, 0, 1, 0, 1, 0, 1, 0])) (("x" // 1) <> ("y" // 2))) `ShouldBe` 8, GetStructureSize (Padded (Right (Bits '[1, 0, 1, 0, 1, 0, 1, 0])) (Anonymous ("x" // 9))) `ShouldBe` 16, GetStructureSize (Padded (Left (Bits '[1, 0, 1, 0, 1, 0, 1, 0])) (Anonymous ("x" // 22))) `ShouldBe` 24, GetStructureSize (Padded (Right (Bits '[1, 0, 1, 0, 1, 0, 1, 0])) (Anonymous ("x" // 33))) `ShouldBe` 40, GetStructureSize (Padded (Right (To (Sequence Word8 Nat) '[0, 255, 0, 255])) (Anonymous ("x" // 10))) `ShouldBe` 32] Source #
_prettySpec :: String Source #