{-# OPTIONS_GHC -Wno-incomplete-patterns #-}

module Codec.Borsh.Incremental.Decoder (
    -- * Definition
    Decoder(..)
    -- * Operations supported by any decoder
  , liftDecoder
  , decodeLittleEndian
  , decodeLargeToken
  , decodeIncremental
  , decodeIncremental_
    -- * Running
  , DecodeResult(..)
  , deserialiseByteString
  ) where

import Control.Applicative
import Control.Monad
import Control.Monad.Fail
import Control.Monad.ST
import Data.Word

import qualified Data.ByteString      as S
import qualified Data.ByteString.Lazy as L

import Codec.Borsh.Incremental.Located
import Codec.Borsh.Incremental.Monad
import Codec.Borsh.Internal.Util.ByteString
import Codec.Borsh.Internal.Util.ByteSwap

{-------------------------------------------------------------------------------
  Definition
-------------------------------------------------------------------------------}

-- | Decoder
--
-- A decoder describes how to match against a single chunk of the input.
--
-- For decoders for primitive types, use 'Codec.Borsh.FromBorsh' instances.
newtype Decoder s a = Decoder {
      forall s a.
Decoder s a
-> LocatedChunk -> ST s (LocatedChunk, DecodeResult s a)
matchChunk :: LocatedChunk -> ST s (LocatedChunk, DecodeResult s a)
    }

{-------------------------------------------------------------------------------
  Operations supported by the 'Decoder' monad
-------------------------------------------------------------------------------}

-- | Lift an 'ST' operation into the 'Decoder' monad.
liftDecoder :: ST s a -> Decoder s a
liftDecoder :: forall s a. ST s a -> Decoder s a
liftDecoder ST s a
sa = forall s a.
(LocatedChunk -> ST s (LocatedChunk, DecodeResult s a))
-> Decoder s a
Decoder forall a b. (a -> b) -> a -> b
$ \LocatedChunk
chunk -> (LocatedChunk
chunk, ) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a s. a -> DecodeResult s a
DecodeDone forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ST s a
sa

-- | Decode a value encoded in little endian byte order (e.g. as mandated by the
-- [Borsh](https://borsh.io) spec).
decodeLittleEndian :: forall s a. ByteSwap a => Decoder s a
decodeLittleEndian :: forall s a. ByteSwap a => Decoder s a
decodeLittleEndian = forall s a.
(LocatedChunk -> ST s (LocatedChunk, DecodeResult s a))
-> Decoder s a
Decoder LocatedChunk -> ST s (LocatedChunk, DecodeResult s a)
aux
  where
    aux :: LocatedChunk -> ST s (LocatedChunk, DecodeResult s a)
    aux :: LocatedChunk -> ST s (LocatedChunk, DecodeResult s a)
aux chunk :: LocatedChunk
chunk@(L ByteString
bs ByteOffset
off) =
        case forall a.
ByteSwap a =>
ByteString -> Maybe (a, ByteOffset, ByteString)
peekByteString ByteString
bs of
          Just (a
x, ByteOffset
sizeX, ByteString
bs') ->
            forall (m :: * -> *) a. Monad m => a -> m a
return (forall a. a -> ByteOffset -> Located a
L ByteString
bs' (ByteOffset
off forall a. Num a => a -> a -> a
+ ByteOffset
sizeX), forall a s. a -> DecodeResult s a
DecodeDone a
x)
          Maybe (a, ByteOffset, ByteString)
Nothing ->
            forall (m :: * -> *) a. Monad m => a -> m a
return (LocatedChunk
chunk, forall s a. Decoder s a -> DecodeResult s a
DecodeNeedsData forall s a. ByteSwap a => Decoder s a
decodeLittleEndian)

-- | Large token of known length that spans multiple chunks
--
-- This is NOT incremental: all chunks will be read into memory before the
-- result is returned. Primarily useful for large types that are not
-- easily split into (valid) chunks, such as UTF8-encoded text (if were
-- wanted to split that, we'd have to split it at UTF8 boundaries).
decodeLargeToken ::
     Word32 -- ^ Number of bytes to decode
  -> Decoder s L.ByteString
decodeLargeToken :: forall s. ByteOffset -> Decoder s ByteString
decodeLargeToken ByteOffset
n = forall s a.
(LocatedChunk -> ST s (LocatedChunk, DecodeResult s a))
-> Decoder s a
Decoder forall a b. (a -> b) -> a -> b
$ \LocatedChunk
chunk ->
    forall (m :: * -> *) a. Monad m => a -> m a
return (LocatedChunk
chunk, forall s a.
ByteOffset -> (ByteString -> Decoder s a) -> DecodeResult s a
DecodeLargeToken ByteOffset
n forall (m :: * -> *) a. Monad m => a -> m a
return)

-- | Incremental interface
--
-- When decoding large objects such as lists, we do not want to bring all
-- required chunks into memory before decoding the list. Instead, we want to
-- decode the list elements as we go. In this case, 'DecodeIncremental' can
-- be used to repeatedly decode a value using decoder for the elements.
--
-- NOTE: This interface is incremental in the sense that the /input chunks/
-- are read one at a time. It is /NOT/ incremental in the generated /output/.
decodeIncremental ::
     Word32      -- ^ Number of elements in the sequence to decode
  -> Decoder s a -- ^ 'Decoder' to run for the individual elements
  -> Decoder s [a]
decodeIncremental :: forall s a. ByteOffset -> Decoder s a -> Decoder s [a]
decodeIncremental ByteOffset
n Decoder s a
d = forall s a.
(LocatedChunk -> ST s (LocatedChunk, DecodeResult s a))
-> Decoder s a
Decoder forall a b. (a -> b) -> a -> b
$ \LocatedChunk
chunk ->
    forall (m :: * -> *) a. Monad m => a -> m a
return (LocatedChunk
chunk, forall s a b.
ByteOffset
-> Decoder s a -> ([a] -> Decoder s b) -> DecodeResult s b
DecodeIncremental ByteOffset
n Decoder s a
d forall (m :: * -> *) a. Monad m => a -> m a
return)

-- | Variation on 'decoreIncremental', where we do not accumulate results
--
-- This is useful for example for datatypes that we can update imperatively
-- (using the 'ST' monad), such as mutable arrays. It could also be used to skip
-- over unused parts of the input.
decodeIncremental_ ::
     Word32       -- ^ Number of elements in the sequence to decode
  -> Decoder s () -- ^ 'Decoder' to run for the individual elements
  -> Decoder s ()
decodeIncremental_ :: forall s. ByteOffset -> Decoder s () -> Decoder s ()
decodeIncremental_ ByteOffset
n Decoder s ()
d = forall s a.
(LocatedChunk -> ST s (LocatedChunk, DecodeResult s a))
-> Decoder s a
Decoder forall a b. (a -> b) -> a -> b
$ \LocatedChunk
chunk ->
    forall (m :: * -> *) a. Monad m => a -> m a
return (LocatedChunk
chunk, forall s a.
ByteOffset -> Decoder s () -> Decoder s a -> DecodeResult s a
DecodeIncremental_ ByteOffset
n Decoder s ()
d forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. Monad m => a -> m a
return ())

{-------------------------------------------------------------------------------
  Results
-------------------------------------------------------------------------------}

data DecodeResult s a where
  -- | The decoder terminated successfully: we can stop decoding
  DecodeDone :: a -> DecodeResult s a

  -- | The decoder failed: we should abort
  DecodeFail :: String -> DecodeResult s a

  -- | The decoder needs more data before it can continue
  --
  -- NOTE: The decoder that is waiting for more data may not be (and typically
  -- will not be) the decoder we started with in 'matchChunk': in the typical
  -- case, a bunch of values will have been decoded successfully before we get
  -- to a (continuation) decoder that requires data beyond the current chunk.
  DecodeNeedsData :: Decoder s a -> DecodeResult s a

  -- | Large token of known length that spans multiple chunks
  --
  -- See 'decodeLargeToken' for discussion.
  --
  -- The continuation will be called with a lazy bytestring of precisely the
  -- requested length (provided enough input is available, of course), along
  -- with the remaining input token to be provided to the continuation decoder.
  DecodeLargeToken ::
       Word32  -- ^ Required number of bytes
    -> (L.ByteString -> Decoder s a)
    -> DecodeResult s a

  -- | Incremental interface
  --
  -- See 'decodeIncremental' for discussion.
  DecodeIncremental ::
       Word32               -- ^ How often to repeat the smaller decoder
    -> Decoder s a          -- ^ Decoder to repeat
    -> ([a] -> Decoder s b) -- ^ Process all elements
    -> DecodeResult s b

  -- | Variation on 'DecodeIncremental', where we do not accumulate results
  --
  -- See 'decodeIncremental_' for discussion.
  DecodeIncremental_ ::
       Word32        -- ^ How often to repeat the smaller decoder
    -> Decoder s ()  -- ^ Decoder to repeat (imperatively handling each element)
    -> Decoder s a   -- ^ Continuation
    -> DecodeResult s a

{-------------------------------------------------------------------------------
  Monad instance
-------------------------------------------------------------------------------}

instance Functor (Decoder s) where
  fmap :: forall a b. (a -> b) -> Decoder s a -> Decoder s b
fmap = forall (f :: * -> *) a b. Applicative f => (a -> b) -> f a -> f b
liftA

instance Applicative (Decoder s) where
  pure :: forall a. a -> Decoder s a
pure a
x = forall s a.
(LocatedChunk -> ST s (LocatedChunk, DecodeResult s a))
-> Decoder s a
Decoder forall a b. (a -> b) -> a -> b
$ \LocatedChunk
chunk -> forall (m :: * -> *) a. Monad m => a -> m a
return (LocatedChunk
chunk, forall a s. a -> DecodeResult s a
DecodeDone a
x)
  <*> :: forall a b. Decoder s (a -> b) -> Decoder s a -> Decoder s b
(<*>)  = forall (m :: * -> *) a b. Monad m => m (a -> b) -> m a -> m b
ap

instance Monad (Decoder s) where
  return :: forall a. a -> Decoder s a
return  = forall (f :: * -> *) a. Applicative f => a -> f a
pure
  Decoder s a
x >>= :: forall a b. Decoder s a -> (a -> Decoder s b) -> Decoder s b
>>= a -> Decoder s b
f = forall s a.
(LocatedChunk -> ST s (LocatedChunk, DecodeResult s a))
-> Decoder s a
Decoder forall a b. (a -> b) -> a -> b
$ \LocatedChunk
chunk -> do
      (LocatedChunk
chunk', DecodeResult s a
result) <- forall s a.
Decoder s a
-> LocatedChunk -> ST s (LocatedChunk, DecodeResult s a)
matchChunk Decoder s a
x LocatedChunk
chunk
      case DecodeResult s a
result of
        DecodeDone a
a ->
          forall s a.
Decoder s a
-> LocatedChunk -> ST s (LocatedChunk, DecodeResult s a)
matchChunk (a -> Decoder s b
f a
a) LocatedChunk
chunk'
        DecodeFail String
e ->
          forall (m :: * -> *) a. Monad m => a -> m a
return (LocatedChunk
chunk', forall s a. String -> DecodeResult s a
DecodeFail String
e)
        DecodeNeedsData Decoder s a
d ->
          forall (m :: * -> *) a. Monad m => a -> m a
return (LocatedChunk
chunk', forall s a. Decoder s a -> DecodeResult s a
DecodeNeedsData (Decoder s a
d forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= a -> Decoder s b
f))
        DecodeLargeToken ByteOffset
reqLen ByteString -> Decoder s a
k ->
          forall (m :: * -> *) a. Monad m => a -> m a
return (LocatedChunk
chunk', forall s a.
ByteOffset -> (ByteString -> Decoder s a) -> DecodeResult s a
DecodeLargeToken ByteOffset
reqLen (ByteString -> Decoder s a
k forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> a -> Decoder s b
f))
        DecodeIncremental ByteOffset
count Decoder s a
d [a] -> Decoder s a
k ->
          forall (m :: * -> *) a. Monad m => a -> m a
return (LocatedChunk
chunk', forall s a b.
ByteOffset
-> Decoder s a -> ([a] -> Decoder s b) -> DecodeResult s b
DecodeIncremental ByteOffset
count Decoder s a
d ([a] -> Decoder s a
k forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> a -> Decoder s b
f))
        DecodeIncremental_ ByteOffset
count Decoder s ()
d Decoder s a
k ->
          forall (m :: * -> *) a. Monad m => a -> m a
return (LocatedChunk
chunk', forall s a.
ByteOffset -> Decoder s () -> Decoder s a -> DecodeResult s a
DecodeIncremental_ ByteOffset
count Decoder s ()
d (Decoder s a
k forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= a -> Decoder s b
f))

instance MonadFail (Decoder s) where
  fail :: forall a. String -> Decoder s a
fail String
e = forall s a.
(LocatedChunk -> ST s (LocatedChunk, DecodeResult s a))
-> Decoder s a
Decoder forall a b. (a -> b) -> a -> b
$ \LocatedChunk
chunk -> forall (m :: * -> *) a. Monad m => a -> m a
return (LocatedChunk
chunk, forall s a. String -> DecodeResult s a
DecodeFail String
e)

{-------------------------------------------------------------------------------
  Running decoders
-------------------------------------------------------------------------------}

-- | Top-level entry point
--
-- We start without any input at all (and depending on the specific decoder,
-- we may never need any).
runDecoder :: Decoder s a -> Incr s (LocatedChunk, a)
runDecoder :: forall s a. Decoder s a -> Incr s (LocatedChunk, a)
runDecoder = forall s a. LocatedChunk -> Decoder s a -> Incr s (LocatedChunk, a)
runWith forall a b. (a -> b) -> a -> b
$ forall a. a -> ByteOffset -> Located a
L ByteString
S.empty ByteOffset
0

-- | Run decoder against specified chunk
runWith :: LocatedChunk -> Decoder s a -> Incr s (LocatedChunk, a)
runWith :: forall s a. LocatedChunk -> Decoder s a -> Incr s (LocatedChunk, a)
runWith LocatedChunk
chunk Decoder s a
d = forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry forall s a.
LocatedChunk -> DecodeResult s a -> Incr s (LocatedChunk, a)
processResult forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall s a. ST s a -> Incr s a
liftIncr (forall s a.
Decoder s a
-> LocatedChunk -> ST s (LocatedChunk, DecodeResult s a)
matchChunk Decoder s a
d LocatedChunk
chunk)

{-------------------------------------------------------------------------------
  Processing the result of a decoder
-------------------------------------------------------------------------------}

-- | Process decoder result
processResult :: LocatedChunk -> DecodeResult s a -> Incr s (LocatedChunk, a)
processResult :: forall s a.
LocatedChunk -> DecodeResult s a -> Incr s (LocatedChunk, a)
processResult LocatedChunk
chunk = \case
    DecodeDone a
x -> forall (m :: * -> *) a. Monad m => a -> m a
return    (LocatedChunk
chunk, a
x)
    DecodeFail String
e -> forall s a. LocatedChunk -> String -> Incr s a
decodeFail LocatedChunk
chunk  String
e

    DecodeNeedsData      Decoder s a
d   -> forall s a. Decoder s a -> LocatedChunk -> Incr s (LocatedChunk, a)
processNeedsData      Decoder s a
d   LocatedChunk
chunk
    DecodeLargeToken   ByteOffset
n   ByteString -> Decoder s a
k -> forall s a.
ByteOffset
-> (ByteString -> Decoder s a)
-> LocatedChunk
-> Incr s (LocatedChunk, a)
processLargeToken   ByteOffset
n   ByteString -> Decoder s a
k LocatedChunk
chunk
    DecodeIncremental  ByteOffset
n Decoder s a
d [a] -> Decoder s a
k -> forall s a b.
ByteOffset
-> Decoder s a
-> ([a] -> Decoder s b)
-> LocatedChunk
-> Incr s (LocatedChunk, b)
processIncremental  ByteOffset
n Decoder s a
d [a] -> Decoder s a
k LocatedChunk
chunk
    DecodeIncremental_ ByteOffset
n Decoder s ()
d Decoder s a
k -> forall s a.
ByteOffset
-> Decoder s ()
-> Decoder s a
-> LocatedChunk
-> Incr s (LocatedChunk, a)
processIncremental_ ByteOffset
n Decoder s ()
d Decoder s a
k LocatedChunk
chunk

processNeedsData ::
     Decoder s a
  -> Located S.ByteString
  -> Incr s (LocatedChunk, a)
processNeedsData :: forall s a. Decoder s a -> LocatedChunk -> Incr s (LocatedChunk, a)
processNeedsData Decoder s a
d chunk :: LocatedChunk
chunk@(L ByteString
bs ByteOffset
off) = forall s. Incr s (Maybe ByteString)
needChunk forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
    Maybe ByteString
Nothing   -> forall s a. LocatedChunk -> String -> Incr s a
decodeFail LocatedChunk
chunk String
"end of input"
    Just ByteString
next -> forall s a. LocatedChunk -> Decoder s a -> Incr s (LocatedChunk, a)
runWith (forall a. a -> ByteOffset -> Located a
L (ByteString
bs forall a. Semigroup a => a -> a -> a
<> ByteString
next) ByteOffset
off) Decoder s a
d

-- | Auxiliary to 'processResult': process token that spans multple chunks
--
-- Precondition: if the accumulated length exceeds the required length, we must
-- be able to split the mostly added chunk to make up for the difference.
processLargeToken :: forall s a.
     Word32                         -- ^ Required total size
  -> (L.ByteString -> Decoder s a)  -- ^ Continuation
  -> LocatedChunk                   -- ^ Current chunk
  -> Incr s (LocatedChunk, a)
processLargeToken :: forall s a.
ByteOffset
-> (ByteString -> Decoder s a)
-> LocatedChunk
-> Incr s (LocatedChunk, a)
processLargeToken ByteOffset
reqLen ByteString -> Decoder s a
k = LocatedChunks -> Incr s (LocatedChunk, a)
go forall b c a. (b -> c) -> (a -> b) -> a -> c
. LocatedChunk -> LocatedChunks
toLocatedChunks
  where
    go :: LocatedChunks -> Incr s (LocatedChunk, a)
    go :: LocatedChunks -> Incr s (LocatedChunk, a)
go LocatedChunks
acc =
        case ByteOffset -> LocatedChunks -> Maybe (ByteString, LocatedChunk)
splitChunks ByteOffset
reqLen LocatedChunks
acc of
          Maybe (ByteString, LocatedChunk)
Nothing -> forall s. Incr s (Maybe ByteString)
needChunk forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
            Maybe ByteString
Nothing   -> forall s a. LocatedChunk -> String -> Incr s a
decodeFail (LocatedChunks -> LocatedChunk
fromLocatedChunks LocatedChunks
acc) String
"end of input"
            Just ByteString
next -> LocatedChunks -> Incr s (LocatedChunk, a)
go (ByteString -> LocatedChunks -> LocatedChunks
addChunk ByteString
next LocatedChunks
acc)
          Just (ByteString
large, LocatedChunk
left) ->
            forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry forall s a.
LocatedChunk -> DecodeResult s a -> Incr s (LocatedChunk, a)
processResult forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall s a. ST s a -> Incr s a
liftIncr (forall s a.
Decoder s a
-> LocatedChunk -> ST s (LocatedChunk, DecodeResult s a)
matchChunk (ByteString -> Decoder s a
k ByteString
large) LocatedChunk
left)

-- | Auxiliary to 'processResult': incremental decoding
processIncremental :: forall s a b.
     Word32                -- ^ Number of elements required
  -> Decoder s a           -- ^ Decoder to repeat
  -> ([a] -> Decoder s b)  -- ^ Continuation once we processed all elements
  -> LocatedChunk          -- ^ Current chunk
  -> Incr s (LocatedChunk, b)
processIncremental :: forall s a b.
ByteOffset
-> Decoder s a
-> ([a] -> Decoder s b)
-> LocatedChunk
-> Incr s (LocatedChunk, b)
processIncremental ByteOffset
count Decoder s a
d [a] -> Decoder s b
k = [a] -> ByteOffset -> LocatedChunk -> Incr s (LocatedChunk, b)
go [] ByteOffset
count
  where
    go :: [a] -> Word32 -> LocatedChunk -> Incr s (LocatedChunk, b)
    go :: [a] -> ByteOffset -> LocatedChunk -> Incr s (LocatedChunk, b)
go [a]
acc ByteOffset
0 LocatedChunk
chunk = do (LocatedChunk, DecodeResult s b)
result <- forall s a. ST s a -> Incr s a
liftIncr (forall s a.
Decoder s a
-> LocatedChunk -> ST s (LocatedChunk, DecodeResult s a)
matchChunk ([a] -> Decoder s b
k (forall a. [a] -> [a]
reverse [a]
acc)) LocatedChunk
chunk)
                        forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry forall s a.
LocatedChunk -> DecodeResult s a -> Incr s (LocatedChunk, a)
processResult (LocatedChunk, DecodeResult s b)
result
    go [a]
acc ByteOffset
n LocatedChunk
chunk = do (LocatedChunk
chunk', a
a) <- forall s a. LocatedChunk -> Decoder s a -> Incr s (LocatedChunk, a)
runWith LocatedChunk
chunk Decoder s a
d
                        [a] -> ByteOffset -> LocatedChunk -> Incr s (LocatedChunk, b)
go (a
aforall a. a -> [a] -> [a]
:[a]
acc) (ByteOffset
n forall a. Num a => a -> a -> a
- ByteOffset
1) LocatedChunk
chunk'

-- | Imperative version of 'processIncremental'
--
-- See 'DecodeIncremental_' for discussion.
processIncremental_ :: forall s a.
     Word32        -- ^ Number of elements required
  -> Decoder s ()  -- ^ Decoder to repeat
  -> Decoder s a   -- ^ Continuation once we processed all elements
  -> LocatedChunk  -- ^ Current chunk
  -> Incr s (LocatedChunk, a)
processIncremental_ :: forall s a.
ByteOffset
-> Decoder s ()
-> Decoder s a
-> LocatedChunk
-> Incr s (LocatedChunk, a)
processIncremental_ ByteOffset
count Decoder s ()
d Decoder s a
k = ByteOffset -> LocatedChunk -> Incr s (LocatedChunk, a)
go ByteOffset
count
  where
    go :: Word32 -> LocatedChunk -> Incr s (LocatedChunk, a)
    go :: ByteOffset -> LocatedChunk -> Incr s (LocatedChunk, a)
go ByteOffset
0 LocatedChunk
chunk = do (LocatedChunk, DecodeResult s a)
result <- forall s a. ST s a -> Incr s a
liftIncr (forall s a.
Decoder s a
-> LocatedChunk -> ST s (LocatedChunk, DecodeResult s a)
matchChunk Decoder s a
k LocatedChunk
chunk)
                    forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry forall s a.
LocatedChunk -> DecodeResult s a -> Incr s (LocatedChunk, a)
processResult (LocatedChunk, DecodeResult s a)
result
    go ByteOffset
n LocatedChunk
chunk = do (LocatedChunk
chunk', ()) <- forall s a. LocatedChunk -> Decoder s a -> Incr s (LocatedChunk, a)
runWith LocatedChunk
chunk Decoder s ()
d
                    ByteOffset -> LocatedChunk -> Incr s (LocatedChunk, a)
go (ByteOffset
n forall a. Num a => a -> a -> a
- ByteOffset
1) LocatedChunk
chunk'

{-------------------------------------------------------------------------------
  Top-level API
-------------------------------------------------------------------------------}

-- | Run decoder
deserialiseByteString ::
     (forall s. Decoder s a)
  -- ^ Decoder
  -> L.ByteString
  -- ^ Input
  -> Either DeserialiseFailure (L.ByteString, ByteOffset, a)
  -- ^ Left-over input, offset of the left-over input relative to the start,
  -- and the result.
deserialiseByteString :: forall a.
(forall s. Decoder s a)
-> ByteString
-> Either DeserialiseFailure (ByteString, ByteOffset, a)
deserialiseByteString forall s. Decoder s a
d = forall a.
(forall s. ST s (IDecode s a))
-> ByteString
-> Either DeserialiseFailure (ByteString, ByteOffset, a)
runIDecode (forall s a. Incr s (LocatedChunk, a) -> ST s (IDecode s a)
runIncr (forall s a. Decoder s a -> Incr s (LocatedChunk, a)
runDecoder forall s. Decoder s a
d))