| Copyright | (C) 2015 Oleg Grenrus |
|---|---|
| License | BSD3 |
| Maintainer | Oleg Grenrus <oleg.grenrus@iki.fi> |
| Safe Haskell | None |
| Language | Haskell2010 |
Data.Binary.Tagged
Contents
Description
Structurally tag binary serialisation stream.
Say you have:
data Record = Record
{ _recordFields :: HM.HashMap Text (Integer, ByteString)
, _recordEnabled :: Bool
}
deriving (Eq, Show, Generic)
instance Binary Record
instance HasStructuralInfo Record
instance HasSemanticVersion Recordthen you can serialise and deserialise Record values with a structure tag by simply
encodeTaggedFile "cachefile" record decodeTaggedFile "cachefile" :: IO Record
If structure of Record changes in between, deserialisation will fail early.
Synopsis
- newtype BinaryTagged (v :: k) a = BinaryTagged {
- unBinaryTagged :: a
- type BinaryTagged' a = BinaryTagged (SemanticVersion a) a
- binaryTag :: Proxy v -> a -> BinaryTagged v a
- binaryTag' :: HasSemanticVersion a => a -> BinaryTagged' a
- binaryUntag :: Proxy v -> BinaryTagged v a -> a
- binaryUntag' :: HasSemanticVersion a => BinaryTagged' a -> a
- data StructuralInfo
- taggedEncode :: forall a. (HasStructuralInfo a, HasSemanticVersion a, Binary a) => a -> ByteString
- taggedDecode :: forall a. (HasStructuralInfo a, HasSemanticVersion a, Binary a) => ByteString -> a
- taggedDecodeOrFail :: forall a. (HasStructuralInfo a, HasSemanticVersion a, Binary a) => ByteString -> Either (ByteString, ByteOffset, String) (ByteString, ByteOffset, a)
- taggedEncodeFile :: forall a. (HasStructuralInfo a, HasSemanticVersion a, Binary a) => FilePath -> a -> IO ()
- taggedDecodeFile :: forall a. (HasStructuralInfo a, HasSemanticVersion a, Binary a) => FilePath -> IO a
- taggedDecodeFileOrFail :: forall a. (HasStructuralInfo a, HasSemanticVersion a, Binary a) => FilePath -> IO (Either (ByteOffset, String) a)
- class HasStructuralInfo a where
- structuralInfo :: Proxy a -> StructuralInfo
- class KnownNat (SemanticVersion a) => HasSemanticVersion (a :: *) where
- type SemanticVersion a :: Nat
- type Version = Word32
- type Interleave (n :: Nat) (m :: Nat) = SumUpTo (n + m) + m
- type SumUpTo (n :: Nat) = Div2 (n * (n + 1))
- type family Div2 (n :: Nat) :: Nat where ...
- ghcStructuralInfo :: (Generic a, All2 HasStructuralInfo (GCode a), GDatatypeInfo a, SListI2 (GCode a)) => Proxy a -> StructuralInfo
- ghcNominalType :: (Generic a, GDatatypeInfo a) => Proxy a -> StructuralInfo
- ghcStructuralInfo1 :: forall f a. (Generic1 f, GDatatypeInfo (f a), HasStructuralInfo a) => Proxy (f a) -> StructuralInfo
- sopStructuralInfo :: forall a. (Generic a, HasDatatypeInfo a, All2 HasStructuralInfo (Code a)) => Proxy a -> StructuralInfo
- sopNominalType :: forall a. (Generic a, HasDatatypeInfo a) => Proxy a -> StructuralInfo
- sopStructuralInfo1 :: forall f a. (Generic (f a), HasDatatypeInfo (f a), HasStructuralInfo a) => Proxy (f a) -> StructuralInfo
- sopStructuralInfoS :: forall xss. (All2 HasStructuralInfo xss, SListI2 xss) => DatatypeInfo xss -> StructuralInfo
- sopNominalTypeS :: DatatypeInfo xss -> StructuralInfo
- sopStructuralInfo1S :: StructuralInfo -> DatatypeInfo xss -> StructuralInfo
- structuralInfoSha1Digest :: StructuralInfo -> Digest SHA1State
- structuralInfoSha1ByteStringDigest :: StructuralInfo -> ByteString
Data
newtype BinaryTagged (v :: k) a Source #
Binary serialisable class, which tries to be less error-prone to data structure changes.
Values are serialised with header consisting of version v and hash of structuralInfo.
Constructors
| BinaryTagged | |
Fields
| |
Instances
type BinaryTagged' a = BinaryTagged (SemanticVersion a) a Source #
binaryTag :: Proxy v -> a -> BinaryTagged v a Source #
binaryTag' :: HasSemanticVersion a => a -> BinaryTagged' a Source #
binaryUntag :: Proxy v -> BinaryTagged v a -> a Source #
binaryUntag' :: HasSemanticVersion a => BinaryTagged' a -> a Source #
data StructuralInfo Source #
Data type structure, with (some) nominal information.
Constructors
| NominalType String | |
| NominalNewtype String StructuralInfo | |
| StructuralInfo String [[StructuralInfo]] |
Instances
Serialisation
taggedEncode :: forall a. (HasStructuralInfo a, HasSemanticVersion a, Binary a) => a -> ByteString Source #
Tagged version of encode
taggedDecode :: forall a. (HasStructuralInfo a, HasSemanticVersion a, Binary a) => ByteString -> a Source #
Tagged version of decode
taggedDecodeOrFail :: forall a. (HasStructuralInfo a, HasSemanticVersion a, Binary a) => ByteString -> Either (ByteString, ByteOffset, String) (ByteString, ByteOffset, a) Source #
Tagged version of decodeOrFail
IO functions for serialisation
taggedEncodeFile :: forall a. (HasStructuralInfo a, HasSemanticVersion a, Binary a) => FilePath -> a -> IO () Source #
Tagged version of encodeFile
taggedDecodeFile :: forall a. (HasStructuralInfo a, HasSemanticVersion a, Binary a) => FilePath -> IO a Source #
Tagged version of decodeFile
taggedDecodeFileOrFail :: forall a. (HasStructuralInfo a, HasSemanticVersion a, Binary a) => FilePath -> IO (Either (ByteOffset, String) a) Source #
Tagged version of decodeFileOrFail
Class
class HasStructuralInfo a where Source #
Type class providing StructuralInfo for each data type.
For regular non-recursive ADTs HasStructuralInfo can be derived generically.
data Record = Record { a :: Int, b :: Bool, c :: [Char] } deriving (Generic)
instance hasStructuralInfo RecordFor stable types, you can provide only type name
instance HasStructuralInfo Int where structuralInfo = ghcNominalType -- infer name from Generic information instance HasStructuralInfo Integer where structuralInfo _ = NominalType "Integer"
Recursive type story is a bit sad atm. If the type structure is stable, you can do:
instance HasStructuralInfo a => HasStructuralInfo [a] where structuralInfo = ghcStructuralInfo1
Minimal complete definition
Nothing
Methods
structuralInfo :: Proxy a -> StructuralInfo Source #
structuralInfo :: (Generic a, All2 HasStructuralInfo (GCode a), GDatatypeInfo a, SListI2 (GCode a)) => Proxy a -> StructuralInfo Source #
Instances
class KnownNat (SemanticVersion a) => HasSemanticVersion (a :: *) Source #
A helper type family for encodeTaggedFile and decodeTaggedFile.
The default definition is SemanticVersion a = 0
Associated Types
type SemanticVersion a :: Nat Source #
Instances
Type level calculations
type Interleave (n :: Nat) (m :: Nat) = SumUpTo (n + m) + m Source #
Interleaving
3 | 9 . . . .
2 | 5 8 . . .
1 | 2 4 7 11 .
0 | 0 1 3 6 10
-----------------
0 1 2 3 4This can be calculated by f x y = sum ([0..x+y]) + y
Generic derivation
GHC
ghcStructuralInfo :: (Generic a, All2 HasStructuralInfo (GCode a), GDatatypeInfo a, SListI2 (GCode a)) => Proxy a -> StructuralInfo Source #
ghcNominalType :: (Generic a, GDatatypeInfo a) => Proxy a -> StructuralInfo Source #
ghcStructuralInfo1 :: forall f a. (Generic1 f, GDatatypeInfo (f a), HasStructuralInfo a) => Proxy (f a) -> StructuralInfo Source #
SOP
sopStructuralInfo :: forall a. (Generic a, HasDatatypeInfo a, All2 HasStructuralInfo (Code a)) => Proxy a -> StructuralInfo Source #
sopNominalType :: forall a. (Generic a, HasDatatypeInfo a) => Proxy a -> StructuralInfo Source #
sopStructuralInfo1 :: forall f a. (Generic (f a), HasDatatypeInfo (f a), HasStructuralInfo a) => Proxy (f a) -> StructuralInfo Source #
SOP direct
sopStructuralInfoS :: forall xss. (All2 HasStructuralInfo xss, SListI2 xss) => DatatypeInfo xss -> StructuralInfo Source #
sopNominalTypeS :: DatatypeInfo xss -> StructuralInfo Source #
sopStructuralInfo1S :: StructuralInfo -> DatatypeInfo xss -> StructuralInfo Source #