{-# LANGUAGE GADTs #-}
{-# LANGUAGE RankNTypes, ScopedTypeVariables #-}
{-# OPTIONS_GHC -fno-warn-name-shadowing #-}

--
-- (c) The University of Glasgow 2002-2006
--
-- Serialized values

module GHC.Serialized (
    -- * Main Serialized data type
    Serialized(..),

    -- * Going into and out of 'Serialized'
    toSerialized, fromSerialized,

    -- * Handy serialization functions
    serializeWithData, deserializeWithData,
  ) where

import Prelude -- See note [Why do we import Prelude here?]
import Data.Bits
import Data.Word        ( Word8 )
import Data.Data


-- | Represents a serialized value of a particular type. Attempts can be made to deserialize it at certain types
data Serialized = Serialized TypeRep [Word8]

-- | Put a Typeable value that we are able to actually turn into bytes into a 'Serialized' value ready for deserialization later
toSerialized :: forall a. Typeable a => (a -> [Word8]) -> a -> Serialized
toSerialized :: (a -> [Word8]) -> a -> Serialized
toSerialized serialize :: a -> [Word8]
serialize what :: a
what = TypeRep -> [Word8] -> Serialized
Serialized (a -> TypeRep
forall a. Typeable a => a -> TypeRep
typeOf a
what) (a -> [Word8]
serialize a
what)

-- | If the 'Serialized' value contains something of the given type, then use the specified deserializer to return @Just@ that.
-- Otherwise return @Nothing@.
fromSerialized :: forall a. Typeable a => ([Word8] -> a) -> Serialized -> Maybe a
fromSerialized :: ([Word8] -> a) -> Serialized -> Maybe a
fromSerialized deserialize :: [Word8] -> a
deserialize (Serialized the_type :: TypeRep
the_type bytes :: [Word8]
bytes)
  | TypeRep
the_type TypeRep -> TypeRep -> Bool
forall a. Eq a => a -> a -> Bool
== TypeRep
rep = a -> Maybe a
forall a. a -> Maybe a
Just ([Word8] -> a
deserialize [Word8]
bytes)
  | Bool
otherwise       = Maybe a
forall a. Maybe a
Nothing
  where rep :: TypeRep
rep = Proxy a -> TypeRep
forall k (proxy :: k -> *) (a :: k).
Typeable a =>
proxy a -> TypeRep
typeRep (Proxy a
forall k (t :: k). Proxy t
Proxy :: Proxy a)

-- | Use a 'Data' instance to implement a serialization scheme dual to that of 'deserializeWithData'
serializeWithData :: Data a => a -> [Word8]
serializeWithData :: a -> [Word8]
serializeWithData what :: a
what = a -> [Word8] -> [Word8]
forall a. Data a => a -> [Word8] -> [Word8]
serializeWithData' a
what []

serializeWithData' :: Data a => a -> [Word8] -> [Word8]
serializeWithData' :: a -> [Word8] -> [Word8]
serializeWithData' what :: a
what = ([Word8] -> [Word8], a) -> [Word8] -> [Word8]
forall a b. (a, b) -> a
fst (([Word8] -> [Word8], a) -> [Word8] -> [Word8])
-> ([Word8] -> [Word8], a) -> [Word8] -> [Word8]
forall a b. (a -> b) -> a -> b
$ (forall d b.
 Data d =>
 ([Word8] -> [Word8], d -> b) -> d -> ([Word8] -> [Word8], b))
-> (forall g. g -> ([Word8] -> [Word8], g))
-> a
-> ([Word8] -> [Word8], a)
forall a (c :: * -> *).
Data a =>
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> a -> c a
gfoldl (\(before, a_to_b) a :: d
a -> ([Word8] -> [Word8]
before ([Word8] -> [Word8]) -> ([Word8] -> [Word8]) -> [Word8] -> [Word8]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. d -> [Word8] -> [Word8]
forall a. Data a => a -> [Word8] -> [Word8]
serializeWithData' d
a, d -> b
a_to_b d
a))
                                       (\x :: g
x -> (ConstrRep -> [Word8] -> [Word8]
serializeConstr (Constr -> ConstrRep
constrRep (a -> Constr
forall a. Data a => a -> Constr
toConstr a
what)), g
x))
                                       a
what

-- | Use a 'Data' instance to implement a deserialization scheme dual to that of 'serializeWithData'
deserializeWithData :: Data a => [Word8] -> a
deserializeWithData :: [Word8] -> a
deserializeWithData = ([Word8], a) -> a
forall a b. (a, b) -> b
snd (([Word8], a) -> a) -> ([Word8] -> ([Word8], a)) -> [Word8] -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Word8] -> ([Word8], a)
forall a. Data a => [Word8] -> ([Word8], a)
deserializeWithData'

deserializeWithData' :: forall a. Data a => [Word8] -> ([Word8], a)
deserializeWithData' :: [Word8] -> ([Word8], a)
deserializeWithData' bytes :: [Word8]
bytes = [Word8] -> (ConstrRep -> [Word8] -> ([Word8], a)) -> ([Word8], a)
forall a. [Word8] -> (ConstrRep -> [Word8] -> a) -> a
deserializeConstr [Word8]
bytes ((ConstrRep -> [Word8] -> ([Word8], a)) -> ([Word8], a))
-> (ConstrRep -> [Word8] -> ([Word8], a)) -> ([Word8], a)
forall a b. (a -> b) -> a -> b
$ \constr_rep :: ConstrRep
constr_rep bytes :: [Word8]
bytes ->
                             (forall b r. Data b => ([Word8], b -> r) -> ([Word8], r))
-> (forall r. r -> ([Word8], r)) -> Constr -> ([Word8], a)
forall a (c :: * -> *).
Data a =>
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c a
gunfold (\(bytes, b_to_r) -> let (bytes' :: [Word8]
bytes', b :: b
b) = [Word8] -> ([Word8], b)
forall a. Data a => [Word8] -> ([Word8], a)
deserializeWithData' [Word8]
bytes in ([Word8]
bytes', b -> r
b_to_r b
b))
                                     (\x :: r
x -> ([Word8]
bytes, r
x))
                                     (DataType -> ConstrRep -> Constr
repConstr (a -> DataType
forall a. Data a => a -> DataType
dataTypeOf (a
forall a. HasCallStack => a
undefined :: a)) ConstrRep
constr_rep)


serializeConstr :: ConstrRep -> [Word8] -> [Word8]
serializeConstr :: ConstrRep -> [Word8] -> [Word8]
serializeConstr (AlgConstr ix :: ConIndex
ix)   = Word8 -> [Word8] -> [Word8]
serializeWord8 1 ([Word8] -> [Word8]) -> ([Word8] -> [Word8]) -> [Word8] -> [Word8]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ConIndex -> [Word8] -> [Word8]
serializeInt ConIndex
ix
serializeConstr (IntConstr i :: Integer
i)    = Word8 -> [Word8] -> [Word8]
serializeWord8 2 ([Word8] -> [Word8]) -> ([Word8] -> [Word8]) -> [Word8] -> [Word8]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> [Word8] -> [Word8]
serializeInteger Integer
i
serializeConstr (FloatConstr r :: Rational
r)  = Word8 -> [Word8] -> [Word8]
serializeWord8 3 ([Word8] -> [Word8]) -> ([Word8] -> [Word8]) -> [Word8] -> [Word8]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Rational -> [Word8] -> [Word8]
forall a. Real a => a -> [Word8] -> [Word8]
serializeRational Rational
r
serializeConstr (CharConstr c :: Char
c)   = Word8 -> [Word8] -> [Word8]
serializeWord8 4 ([Word8] -> [Word8]) -> ([Word8] -> [Word8]) -> [Word8] -> [Word8]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> [Word8] -> [Word8]
serializeChar Char
c


deserializeConstr :: [Word8] -> (ConstrRep -> [Word8] -> a) -> a
deserializeConstr :: [Word8] -> (ConstrRep -> [Word8] -> a) -> a
deserializeConstr bytes :: [Word8]
bytes k :: ConstrRep -> [Word8] -> a
k = [Word8] -> (Word8 -> [Word8] -> a) -> a
forall a. [Word8] -> (Word8 -> [Word8] -> a) -> a
deserializeWord8 [Word8]
bytes ((Word8 -> [Word8] -> a) -> a) -> (Word8 -> [Word8] -> a) -> a
forall a b. (a -> b) -> a -> b
$ \constr_ix :: Word8
constr_ix bytes :: [Word8]
bytes ->
                            case Word8
constr_ix of
                                1 -> [Word8] -> (ConIndex -> [Word8] -> a) -> a
forall a. [Word8] -> (ConIndex -> [Word8] -> a) -> a
deserializeInt      [Word8]
bytes ((ConIndex -> [Word8] -> a) -> a)
-> (ConIndex -> [Word8] -> a) -> a
forall a b. (a -> b) -> a -> b
$ \ix :: ConIndex
ix -> ConstrRep -> [Word8] -> a
k (ConIndex -> ConstrRep
AlgConstr ConIndex
ix)
                                2 -> [Word8] -> (Integer -> [Word8] -> a) -> a
forall a. [Word8] -> (Integer -> [Word8] -> a) -> a
deserializeInteger  [Word8]
bytes ((Integer -> [Word8] -> a) -> a) -> (Integer -> [Word8] -> a) -> a
forall a b. (a -> b) -> a -> b
$ \i :: Integer
i  -> ConstrRep -> [Word8] -> a
k (Integer -> ConstrRep
IntConstr Integer
i)
                                3 -> [Word8] -> (Rational -> [Word8] -> a) -> a
forall a b. Fractional a => [Word8] -> (a -> [Word8] -> b) -> b
deserializeRational [Word8]
bytes ((Rational -> [Word8] -> a) -> a)
-> (Rational -> [Word8] -> a) -> a
forall a b. (a -> b) -> a -> b
$ \r :: Rational
r  -> ConstrRep -> [Word8] -> a
k (Rational -> ConstrRep
FloatConstr Rational
r)
                                4 -> [Word8] -> (Char -> [Word8] -> a) -> a
forall a. [Word8] -> (Char -> [Word8] -> a) -> a
deserializeChar     [Word8]
bytes ((Char -> [Word8] -> a) -> a) -> (Char -> [Word8] -> a) -> a
forall a b. (a -> b) -> a -> b
$ \c :: Char
c  -> ConstrRep -> [Word8] -> a
k (Char -> ConstrRep
CharConstr Char
c)
                                x :: Word8
x -> [Char] -> a
forall a. HasCallStack => [Char] -> a
error ([Char] -> a) -> [Char] -> a
forall a b. (a -> b) -> a -> b
$ "deserializeConstr: unrecognised serialized constructor type " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Word8 -> [Char]
forall a. Show a => a -> [Char]
show Word8
x [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ " in context " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Word8] -> [Char]
forall a. Show a => a -> [Char]
show [Word8]
bytes


serializeFixedWidthNum :: forall a. (Integral a, FiniteBits a) => a -> [Word8] -> [Word8]
serializeFixedWidthNum :: a -> [Word8] -> [Word8]
serializeFixedWidthNum what :: a
what = ConIndex -> a -> [Word8] -> [Word8]
go (a -> ConIndex
forall b. FiniteBits b => b -> ConIndex
finiteBitSize a
what) a
what
  where
    go :: Int -> a -> [Word8] -> [Word8]
    go :: ConIndex -> a -> [Word8] -> [Word8]
go size :: ConIndex
size current :: a
current rest :: [Word8]
rest
      | ConIndex
size ConIndex -> ConIndex -> Bool
forall a. Ord a => a -> a -> Bool
<= 0 = [Word8]
rest
      | Bool
otherwise = a -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (a
current a -> a -> a
forall a. Bits a => a -> a -> a
.&. 255) Word8 -> [Word8] -> [Word8]
forall a. a -> [a] -> [a]
: ConIndex -> a -> [Word8] -> [Word8]
go (ConIndex
size ConIndex -> ConIndex -> ConIndex
forall a. Num a => a -> a -> a
- 8) (a
current a -> ConIndex -> a
forall a. Bits a => a -> ConIndex -> a
`shiftR` 8) [Word8]
rest

deserializeFixedWidthNum :: forall a b. (Integral a, FiniteBits a) => [Word8] -> (a -> [Word8] -> b) -> b
deserializeFixedWidthNum :: [Word8] -> (a -> [Word8] -> b) -> b
deserializeFixedWidthNum bytes :: [Word8]
bytes k :: a -> [Word8] -> b
k = ConIndex -> [Word8] -> (a -> [Word8] -> b) -> b
go (a -> ConIndex
forall b. FiniteBits b => b -> ConIndex
finiteBitSize (a
forall a. HasCallStack => a
undefined :: a)) [Word8]
bytes a -> [Word8] -> b
k
  where
    go :: Int -> [Word8] -> (a -> [Word8] -> b) -> b
    go :: ConIndex -> [Word8] -> (a -> [Word8] -> b) -> b
go size :: ConIndex
size bytes :: [Word8]
bytes k :: a -> [Word8] -> b
k
      | ConIndex
size ConIndex -> ConIndex -> Bool
forall a. Ord a => a -> a -> Bool
<= 0 = a -> [Word8] -> b
k 0 [Word8]
bytes
      | Bool
otherwise = case [Word8]
bytes of
                        (byte :: Word8
byte:bytes :: [Word8]
bytes) -> ConIndex -> [Word8] -> (a -> [Word8] -> b) -> b
go (ConIndex
size ConIndex -> ConIndex -> ConIndex
forall a. Num a => a -> a -> a
- 8) [Word8]
bytes (\x :: a
x -> a -> [Word8] -> b
k ((a
x a -> ConIndex -> a
forall a. Bits a => a -> ConIndex -> a
`shiftL` 8) a -> a -> a
forall a. Bits a => a -> a -> a
.|. Word8 -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
byte))
                        []           -> [Char] -> b
forall a. HasCallStack => [Char] -> a
error "deserializeFixedWidthNum: unexpected end of stream"


serializeEnum :: (Enum a) => a -> [Word8] -> [Word8]
serializeEnum :: a -> [Word8] -> [Word8]
serializeEnum = ConIndex -> [Word8] -> [Word8]
serializeInt (ConIndex -> [Word8] -> [Word8])
-> (a -> ConIndex) -> a -> [Word8] -> [Word8]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> ConIndex
forall a. Enum a => a -> ConIndex
fromEnum

deserializeEnum :: Enum a => [Word8] -> (a -> [Word8] -> b) -> b
deserializeEnum :: [Word8] -> (a -> [Word8] -> b) -> b
deserializeEnum bytes :: [Word8]
bytes k :: a -> [Word8] -> b
k = [Word8] -> (ConIndex -> [Word8] -> b) -> b
forall a. [Word8] -> (ConIndex -> [Word8] -> a) -> a
deserializeInt [Word8]
bytes (a -> [Word8] -> b
k (a -> [Word8] -> b) -> (ConIndex -> a) -> ConIndex -> [Word8] -> b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ConIndex -> a
forall a. Enum a => ConIndex -> a
toEnum)


serializeWord8 :: Word8 -> [Word8] -> [Word8]
serializeWord8 :: Word8 -> [Word8] -> [Word8]
serializeWord8 x :: Word8
x = (Word8
xWord8 -> [Word8] -> [Word8]
forall a. a -> [a] -> [a]
:)

deserializeWord8 :: [Word8] -> (Word8 -> [Word8] -> a) -> a
deserializeWord8 :: [Word8] -> (Word8 -> [Word8] -> a) -> a
deserializeWord8 (byte :: Word8
byte:bytes :: [Word8]
bytes) k :: Word8 -> [Word8] -> a
k = Word8 -> [Word8] -> a
k Word8
byte [Word8]
bytes
deserializeWord8 []           _ = [Char] -> a
forall a. HasCallStack => [Char] -> a
error "deserializeWord8: unexpected end of stream"


serializeInt :: Int -> [Word8] -> [Word8]
serializeInt :: ConIndex -> [Word8] -> [Word8]
serializeInt = ConIndex -> [Word8] -> [Word8]
forall a. (Integral a, FiniteBits a) => a -> [Word8] -> [Word8]
serializeFixedWidthNum

deserializeInt :: [Word8] -> (Int -> [Word8] -> a) -> a
deserializeInt :: [Word8] -> (ConIndex -> [Word8] -> a) -> a
deserializeInt = [Word8] -> (ConIndex -> [Word8] -> a) -> a
forall a b.
(Integral a, FiniteBits a) =>
[Word8] -> (a -> [Word8] -> b) -> b
deserializeFixedWidthNum


serializeRational :: (Real a) => a -> [Word8] -> [Word8]
serializeRational :: a -> [Word8] -> [Word8]
serializeRational = [Char] -> [Word8] -> [Word8]
serializeString ([Char] -> [Word8] -> [Word8])
-> (a -> [Char]) -> a -> [Word8] -> [Word8]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Rational -> [Char]
forall a. Show a => a -> [Char]
show (Rational -> [Char]) -> (a -> Rational) -> a -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Rational
forall a. Real a => a -> Rational
toRational

deserializeRational :: (Fractional a) => [Word8] -> (a -> [Word8] -> b) -> b
deserializeRational :: [Word8] -> (a -> [Word8] -> b) -> b
deserializeRational bytes :: [Word8]
bytes k :: a -> [Word8] -> b
k = [Word8] -> ([Char] -> [Word8] -> b) -> b
forall a. [Word8] -> ([Char] -> [Word8] -> a) -> a
deserializeString [Word8]
bytes (a -> [Word8] -> b
k (a -> [Word8] -> b) -> ([Char] -> a) -> [Char] -> [Word8] -> b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Rational -> a
forall a. Fractional a => Rational -> a
fromRational (Rational -> a) -> ([Char] -> Rational) -> [Char] -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> Rational
forall a. Read a => [Char] -> a
read)


serializeInteger :: Integer -> [Word8] -> [Word8]
serializeInteger :: Integer -> [Word8] -> [Word8]
serializeInteger = [Char] -> [Word8] -> [Word8]
serializeString ([Char] -> [Word8] -> [Word8])
-> (Integer -> [Char]) -> Integer -> [Word8] -> [Word8]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> [Char]
forall a. Show a => a -> [Char]
show

deserializeInteger :: [Word8] -> (Integer -> [Word8] -> a) -> a
deserializeInteger :: [Word8] -> (Integer -> [Word8] -> a) -> a
deserializeInteger bytes :: [Word8]
bytes k :: Integer -> [Word8] -> a
k = [Word8] -> ([Char] -> [Word8] -> a) -> a
forall a. [Word8] -> ([Char] -> [Word8] -> a) -> a
deserializeString [Word8]
bytes (Integer -> [Word8] -> a
k (Integer -> [Word8] -> a)
-> ([Char] -> Integer) -> [Char] -> [Word8] -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> Integer
forall a. Read a => [Char] -> a
read)


serializeChar :: Char -> [Word8] -> [Word8]
serializeChar :: Char -> [Word8] -> [Word8]
serializeChar = [Char] -> [Word8] -> [Word8]
serializeString ([Char] -> [Word8] -> [Word8])
-> (Char -> [Char]) -> Char -> [Word8] -> [Word8]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> [Char]
forall a. Show a => a -> [Char]
show

deserializeChar :: [Word8] -> (Char -> [Word8] -> a) -> a
deserializeChar :: [Word8] -> (Char -> [Word8] -> a) -> a
deserializeChar bytes :: [Word8]
bytes k :: Char -> [Word8] -> a
k = [Word8] -> ([Char] -> [Word8] -> a) -> a
forall a. [Word8] -> ([Char] -> [Word8] -> a) -> a
deserializeString [Word8]
bytes (Char -> [Word8] -> a
k (Char -> [Word8] -> a)
-> ([Char] -> Char) -> [Char] -> [Word8] -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> Char
forall a. Read a => [Char] -> a
read)


serializeString :: String -> [Word8] -> [Word8]
serializeString :: [Char] -> [Word8] -> [Word8]
serializeString = (Char -> [Word8] -> [Word8]) -> [Char] -> [Word8] -> [Word8]
forall a. (a -> [Word8] -> [Word8]) -> [a] -> [Word8] -> [Word8]
serializeList Char -> [Word8] -> [Word8]
forall a. Enum a => a -> [Word8] -> [Word8]
serializeEnum

deserializeString :: [Word8] -> (String -> [Word8] -> a) -> a
deserializeString :: [Word8] -> ([Char] -> [Word8] -> a) -> a
deserializeString = (forall a. [Word8] -> (Char -> [Word8] -> a) -> a)
-> [Word8] -> ([Char] -> [Word8] -> a) -> a
forall a b.
(forall c. [Word8] -> (a -> [Word8] -> c) -> c)
-> [Word8] -> ([a] -> [Word8] -> b) -> b
deserializeList forall a. [Word8] -> (Char -> [Word8] -> a) -> a
forall a b. Enum a => [Word8] -> (a -> [Word8] -> b) -> b
deserializeEnum


serializeList :: (a -> [Word8] -> [Word8]) -> [a] -> [Word8] -> [Word8]
serializeList :: (a -> [Word8] -> [Word8]) -> [a] -> [Word8] -> [Word8]
serializeList serialize_element :: a -> [Word8] -> [Word8]
serialize_element xs :: [a]
xs = ConIndex -> [Word8] -> [Word8]
serializeInt ([a] -> ConIndex
forall (t :: * -> *) a. Foldable t => t a -> ConIndex
length [a]
xs) ([Word8] -> [Word8]) -> ([Word8] -> [Word8]) -> [Word8] -> [Word8]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (([Word8] -> [Word8])
 -> ([Word8] -> [Word8]) -> [Word8] -> [Word8])
-> ([Word8] -> [Word8])
-> [[Word8] -> [Word8]]
-> [Word8]
-> [Word8]
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr ([Word8] -> [Word8]) -> ([Word8] -> [Word8]) -> [Word8] -> [Word8]
forall b c a. (b -> c) -> (a -> b) -> a -> c
(.) [Word8] -> [Word8]
forall a. a -> a
id ((a -> [Word8] -> [Word8]) -> [a] -> [[Word8] -> [Word8]]
forall a b. (a -> b) -> [a] -> [b]
map a -> [Word8] -> [Word8]
serialize_element [a]
xs)

deserializeList :: forall a b. (forall c. [Word8] -> (a -> [Word8] -> c) -> c)
                -> [Word8] -> ([a] -> [Word8] -> b) -> b
deserializeList :: (forall c. [Word8] -> (a -> [Word8] -> c) -> c)
-> [Word8] -> ([a] -> [Word8] -> b) -> b
deserializeList deserialize_element :: forall c. [Word8] -> (a -> [Word8] -> c) -> c
deserialize_element bytes :: [Word8]
bytes k :: [a] -> [Word8] -> b
k = [Word8] -> (ConIndex -> [Word8] -> b) -> b
forall a. [Word8] -> (ConIndex -> [Word8] -> a) -> a
deserializeInt [Word8]
bytes ((ConIndex -> [Word8] -> b) -> b)
-> (ConIndex -> [Word8] -> b) -> b
forall a b. (a -> b) -> a -> b
$ \len :: ConIndex
len bytes :: [Word8]
bytes -> ConIndex -> [Word8] -> ([a] -> [Word8] -> b) -> b
go ConIndex
len [Word8]
bytes [a] -> [Word8] -> b
k
  where
    go :: Int -> [Word8] -> ([a] -> [Word8] -> b) -> b
    go :: ConIndex -> [Word8] -> ([a] -> [Word8] -> b) -> b
go len :: ConIndex
len bytes :: [Word8]
bytes k :: [a] -> [Word8] -> b
k
      | ConIndex
len ConIndex -> ConIndex -> Bool
forall a. Ord a => a -> a -> Bool
<= 0  = [a] -> [Word8] -> b
k [] [Word8]
bytes
      | Bool
otherwise = [Word8] -> (a -> [Word8] -> b) -> b
forall c. [Word8] -> (a -> [Word8] -> c) -> c
deserialize_element [Word8]
bytes (\elt :: a
elt bytes :: [Word8]
bytes -> ConIndex -> [Word8] -> ([a] -> [Word8] -> b) -> b
go (ConIndex
len ConIndex -> ConIndex -> ConIndex
forall a. Num a => a -> a -> a
- 1) [Word8]
bytes ([a] -> [Word8] -> b
k ([a] -> [Word8] -> b) -> ([a] -> [a]) -> [a] -> [Word8] -> b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a
elta -> [a] -> [a]
forall a. a -> [a] -> [a]
:)))