packed-data-0.2.0.0
Safe HaskellNone
LanguageHaskell2010

Data.Packed

Description

Packed data is data serialised into a binary format that is usable as-is, meaning there is no need to parse it to be able to use it. Another perk of such format is that it can be stored in files easily.

`packed-data` allows using packed data type-safely, without explicit pointer arithmetic.

Check out examples here: https://github.com/Arthi-chaud/packed-data/tree/main/examples

Example of a tree traversal:

{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TemplateHaskellQuotes #-}
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE QualifiedDo #-}
{-# LANGUAGE ViewPatterns #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE UnboxedTuples #-}

import Data.Packed
import Data.Packed.Reader
import qualified Data.Packed.Reader as R

data Tree a = Leaf a | Node (Tree a) (Tree a)
$(mkPacked ''Tree [])

myTree :: Tree Int
myTree = Node (Leaf 1) (Leaf 2)

packedTree :: Packed '[Tree Int]
packedTree = pack myTree

-- The two following functions do th same thing

sumPacked1 :: PackedReader '[Tree Int] r Int
sumPacked1 =
    caseTree -- Generated
        ( R.do
            !n <- reader
            R.return n
        )
        ( R.do
            !left <- sumPacked1
            !right <- sumPacked1
            let !res = left + right
            R.return res
        )

-- The patterns PackedLead and PackedNode are generated
sumPacked2 :: PackedReader '[Tree Int] r Int
sumPacked2 = mkPackedReader $ case
    PackedLeaf l -> reader with l
    PackedNode n -> threadedWith n $ R.do
        !left <- sumPacked2
        !right <- sumPacked2
        let !res = left + right
        R.return res

runSum :: Int
runSum = fst $ runReader sumPacked1 packedTree
Synopsis

Classes

class Packable a where Source #

Typeclass for values that can be packed, i.e. written inside a Needs

Methods

write :: forall (r :: [Type]) (t :: [Type]). a -> NeedsWriter a r t Source #

Instances

Instances details
Packable FieldSize Source # 
Instance details

Defined in Data.Packed.FieldSize

Methods

write :: forall (r :: [Type]) (t :: [Type]). FieldSize -> NeedsWriter FieldSize r t Source #

Storable a => Packable a Source # 
Instance details

Defined in Data.Packed.Packable

Methods

write :: forall (r :: [Type]) (t :: [Type]). a -> NeedsWriter a r t Source #

pack :: Packable a => a -> Packed '[a] Source #

Shortcut to produce a Packed buffer from a single Packable value

class Unpackable a where Source #

An Unpackable is a value that can be read (i.e. deserialised) from a Packed value

Methods

reader :: forall (r :: [Type]). PackedReader '[a] r a Source #

The PackedReader to unpack a value of that type

Instances

Instances details
Unpackable FieldSize Source # 
Instance details

Defined in Data.Packed.FieldSize

Methods

reader :: forall (r :: [Type]). PackedReader '[FieldSize] r FieldSize Source #

Storable a => Unpackable a Source # 
Instance details

Defined in Data.Packed.Unpackable

Methods

reader :: forall (r :: [Type]). PackedReader '[a] r a Source #

readerWithoutShift :: forall a (r :: [Type]). Unpackable a => PackedReader ('[] :: [Type]) (a ': r) a Source #

In a PackedReader, reads a value without moving the cursor

unpack :: forall a (r :: [Type]). Unpackable a => Packed (a ': r) -> (a, Packed r) Source #

Deserialise a value from a Packed.

Returns the unconsumed Packed portion

unpack' :: forall a (r :: [Type]). Unpackable a => Packed (a ': r) -> a Source #

Same as unpack, but throws away the unconsumed bytes

Needs

data Needs (p :: [Type]) (t :: [Type]) Source #

A buffer where packed values can be written The order to write these values is defined by the l type list

If p is an empty list, then a value of type t can be extracted from that buffer. (See the signature of runReader)

runBuilder :: forall (p1 :: [Type]) (r :: [Type]). NeedsBuilder p1 r ('[] :: [Type]) r -> Packed r Source #

Runs a NeedsBuilder computation. Produces a Packed

writeWithFieldSize :: forall a (r :: [Type]) (t :: [Type]). Packable a => a -> NeedsWriter' '[FieldSize, a] r t Source #

Write a value into a Needs, along with its FieldSize

Note: Universal quantifier is nedded for GHC < 9.10, because of ScopedTypeVariables

unsafeCastNeeds :: forall (a :: [Type]) (b :: [Type]) (c :: [Type]) (d :: [Type]). Needs a b %1 -> Needs c d Source #

Casts a Needs

Packed

data Packed (l :: [Type]) Source #

A buffer that contains one or more packed (i.e. serialised) values. The order of the values in the buffer is defined by the l type list

Instances

Instances details
NFData (Packed a) Source # 
Instance details

Defined in Data.Packed.Packed

Methods

rnf :: Packed a -> () #

skipWithFieldSize :: forall a (r :: [Type]). PackedReader '[FieldSize, a] r () Source #

Allows skipping over a field without having to unpack it

isolate :: forall a (r :: [Type]). PackedReader '[FieldSize, a] r (PackedFragment '[a]) Source #

Splits the Packed value, and isolate the first encoded value.

fromPacked :: forall (a :: [Type]). Packed a -> ByteString Source #

Extracts the raw buffer from a Packed value

unsafeToPacked :: forall (a :: [Type]). ByteString -> Packed a Source #

UNSAFE: Casts a generic ByteString into a Needs

unsafeCastPacked :: forall (a :: [Type]) (b :: [Type]). Packed a -> Packed b Source #

UNSAFE: Casts a typed Packed value into another Packed value of another type

PackedReader

data PackedReader (p :: [Type]) (r :: [Type]) v Source #

Basically a function that reads/desrialises a value from a Packed

p the types of the packed values to read

r the packed type after the encoded values to read

v the type of the value to unpack

Note: It is an indexed monad.

Instances

Instances details
Functor (PackedReader p r) Source # 
Instance details

Defined in Data.Packed.Reader

Methods

fmap :: (a -> b) -> PackedReader p r a -> PackedReader p r b #

(<$) :: a -> PackedReader p r b -> PackedReader p r a #

mkPackedReader :: forall (p :: [Type]) (r :: [Type]) v. (PackedFragment (p :++: r) -> Identity (v, PackedFragment r)) -> PackedReader p r v Source #

Builds a PackedReader

runReader :: forall (p :: [Type]) (r :: [Type]) v. PackedReader p r v -> Packed (p :++: r) -> (v, Packed r) Source #

Run the reading function using a Packed.

readerWithFieldSize :: forall a (r :: [Type]). Unpackable a => PackedReader '[FieldSize, a] r a Source #

Produces a reader for a value preceded by its FieldSize

Code generation

mkPacked Source #

Arguments

:: Name

The name of the type to generate the functions for

-> [PackingFlag]

Generation customisation flags

-> Q [Dec] 

Generate the following for the given type

Example:

 $(mkPacked ''Tree [InsertFieldSize])

data PackingFlag Source #

Options for the generation process.

Beware: these options alter the signature and behaviour of the generated functions.

Constructors

InsertFieldSize

When specified, each field in a packed data constructor will be preceded by a FieldSize, which indicates the size of the following packed value.

Example

As a consequence, for the following type, the caseTree function will have the following signature

caseTree ::
    (PackedReader (FieldSize ': a ': r) r b) ->
    (PackedReader (FieldSize ': Tree a ': FieldSize ': Tree a ': r) r b) ->
    PackedReader (Tree a ': r) r b
SkipLastFieldSize

This flag should be used in complement to InsertFieldSize

If set, no FieldSize will be inserted before the last parameter of the data constructor.

Example

If this flag is set (along with InsertFieldSize), for the following type, the caseTree function will have the following signature

caseTree ::
    (PackedReader (a ': r) r b) ->
    (PackedReader (FieldSize ': Tree a ': Tree a ': r) r b) ->
    PackedReader (Tree a ': r) r b

Instances

Instances details
Eq PackingFlag Source # 
Instance details

Defined in Data.Packed.TH.Flag

Utils

newtype FieldSize Source #

Type representation for the size of a packed data. The size is in bytes.

Note: Take a look at the PackingFlags to understand how to use it

Constructors

FieldSize Int32 

Instances

Instances details
Enum FieldSize Source # 
Instance details

Defined in Data.Packed.FieldSize

Num FieldSize Source # 
Instance details

Defined in Data.Packed.FieldSize

Integral FieldSize Source # 
Instance details

Defined in Data.Packed.FieldSize

Real FieldSize Source # 
Instance details

Defined in Data.Packed.FieldSize

Eq FieldSize Source # 
Instance details

Defined in Data.Packed.FieldSize

Ord FieldSize Source # 
Instance details

Defined in Data.Packed.FieldSize

Packable FieldSize Source # 
Instance details

Defined in Data.Packed.FieldSize

Methods

write :: forall (r :: [Type]) (t :: [Type]). FieldSize -> NeedsWriter FieldSize r t Source #

Skippable FieldSize Source # 
Instance details

Defined in Data.Packed.FieldSize

Methods

skip :: forall (r :: [Type]). PackedReader '[FieldSize] r () Source #

Unpackable FieldSize Source # 
Instance details

Defined in Data.Packed.FieldSize

Methods

reader :: forall (r :: [Type]). PackedReader '[FieldSize] r FieldSize Source #

getFieldSizeFromPacked :: Packed '[a] -> FieldSize Source #

Returns the size of the packed value.

Warning: For this to be accurate, there should only be one value packed in the binary strea.

class Skippable a where Source #

Methods

skip :: forall (r :: [Type]). PackedReader '[a] r () Source #

Instances

Instances details
Skippable FieldSize Source # 
Instance details

Defined in Data.Packed.FieldSize

Methods

skip :: forall (r :: [Type]). PackedReader '[FieldSize] r () Source #

Storable a => Skippable a Source # 
Instance details

Defined in Data.Packed.Skippable

Methods

skip :: forall (r :: [Type]). PackedReader '[a] r () Source #