    -- |
    -- Module      : Data.ASN1.Get
    -- License     : BSD-style
    -- Maintainer  : Vincent Hanquez <vincent@snarc.org>
    -- Stability   : experimental
    -- Portability : unknown
    --
    -- Simple get module with really simple accessor for ASN1.
    --
    -- Original code is pulled from the Get module from cereal
    -- which is covered by:
    -- Copyright   : Lennart Kolmodin, Galois Inc. 2009
    -- License     : BSD3-style (see LICENSE)
    --
    -- The original code has been tailored and reduced to only cover the useful
    -- case for asn1 and augmented by a position.
    --
    {-# LANGUAGE Rank2Types #-}
    {-# LANGUAGE CPP #-}
    module Data.ASN1.Get
        ( Result(..)
        , Input
        , Get
        , runGetPos
        , runGet
        , getBytes
        , getBytesCopy
        , getWord8
        ) where

    import Control.Applicative (Applicative(..),Alternative(..))
    import Control.Monad (ap,MonadPlus(..))
    import Data.Maybe (fromMaybe)
    import Foreign

    import qualified Data.ByteString          as B

    -- | The result of a parse.
    data Result r = Fail String
                  -- ^ The parse failed. The 'String' is the
                  --   message describing the error, if any.
                  | Partial (B.ByteString -> Result r)
                  -- ^ Supply this continuation with more input so that
                  --   the parser can resume. To indicate that no more
                  --   input is available, use an 'B.empty' string.
                  | Done r Position B.ByteString
                  -- ^ The parse succeeded.  The 'B.ByteString' is the
                  --   input that had not yet been consumed (if any) when
                  --   the parse succeeded.

    instance Show r => Show (Result r) where
        show :: Result r -> String
    show (Fail String
    msg)  = String
    "Fail " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ ShowS
    forall a. Show a => a -> String
    show String
    msg
        show (Partial ByteString -> Result r
    _) = String
    "Partial _"
        show (Done r
    r Position
    pos ByteString
    bs) = String
    "Done " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ r -> String
    forall a. Show a => a -> String
    show r
    r String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ String
    " " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ Position -> String
    forall a. Show a => a -> String
    show Position
    pos String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ String
    " " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ ByteString -> String
    forall a. Show a => a -> String
    show ByteString
    bs

    instance Functor Result where
        fmap :: forall a b. (a -> b) -> Result a -> Result b
    fmap a -> b
    _ (Fail String
    msg)  = String -> Result b
    forall r. String -> Result r
    Fail String
    msg
        fmap a -> b
    f (Partial ByteString -> Result a
    k) = (ByteString -> Result b) -> Result b
    forall r. (ByteString -> Result r) -> Result r
    Partial ((a -> b) -> Result a -> Result b
    forall a b. (a -> b) -> Result a -> Result b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap a -> b
    f (Result a -> Result b)
    -> (ByteString -> Result a) -> ByteString -> Result b
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ByteString -> Result a
    k)
        fmap a -> b
    f (Done a
    r Position
    p ByteString
    bs) = b -> Position -> ByteString -> Result b
    forall r. r -> Position -> ByteString -> Result r
    Done (a -> b
    f a
    r) Position
    p ByteString
    bs

    type Input  = B.ByteString
    type Buffer = Maybe B.ByteString

    type Failure   r = Input -> Buffer -> More -> Position -> String -> Result r
    type Success a r = Input -> Buffer -> More -> Position -> a      -> Result r
    type Position    = Word64

    -- | Have we read all available input?
    data More = Complete
              | Incomplete (Maybe Int)
              deriving (More -> More -> Bool
    (More -> More -> Bool) -> (More -> More -> Bool) -> Eq More
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: More -> More -> Bool
    == :: More -> More -> Bool
    $c/= :: More -> More -> Bool
    /= :: More -> More -> Bool
    Eq)

    -- | The Get monad is an Exception and State monad.
    newtype Get a = Get
        { forall a.
    Get a
    -> forall r.
       ByteString
       -> Buffer
       -> More
       -> Position
       -> Failure r
       -> Success a r
       -> Result r
    unGet :: forall r. Input -> Buffer -> More -> Position -> Failure r -> Success a r -> Result r }

    append :: Buffer -> Buffer -> Buffer
    append :: Buffer -> Buffer -> Buffer
    append Buffer
    l Buffer
    r = ByteString -> ByteString -> ByteString
    B.append (ByteString -> ByteString -> ByteString)
    -> Buffer -> Maybe (ByteString -> ByteString)
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    `fmap` Buffer
    l Maybe (ByteString -> ByteString) -> Buffer -> Buffer
    forall a b. Maybe (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Buffer
    r
    {-# INLINE append #-}

    bufferBytes :: Buffer -> B.ByteString
    bufferBytes :: Buffer -> ByteString
    bufferBytes  = ByteString -> Buffer -> ByteString
    forall a. a -> Maybe a -> a
    fromMaybe ByteString
    B.empty
    {-# INLINE bufferBytes #-}

    instance Functor Get where
        fmap :: forall a b. (a -> b) -> Get a -> Get b
    fmap a -> b
    p Get a
    m =
          (forall r.
     ByteString
     -> Buffer
     -> More
     -> Position
     -> Failure r
     -> Success b r
     -> Result r)
    -> Get b
    forall a.
    (forall r.
     ByteString
     -> Buffer
     -> More
     -> Position
     -> Failure r
     -> Success a r
     -> Result r)
    -> Get a
    Get ((forall r.
      ByteString
      -> Buffer
      -> More
      -> Position
      -> Failure r
      -> Success b r
      -> Result r)
     -> Get b)
    -> (forall r.
        ByteString
        -> Buffer
        -> More
        -> Position
        -> Failure r
        -> Success b r
        -> Result r)
    -> Get b
    forall a b. (a -> b) -> a -> b
    $ \ByteString
    s0 Buffer
    b0 More
    m0 Position
    p0 Failure r
    kf Success b r
    ks ->
            let ks' :: ByteString -> Buffer -> More -> Position -> a -> Result r
    ks' ByteString
    s1 Buffer
    b1 More
    m1 Position
    p1 a
    a = Success b r
    ks ByteString
    s1 Buffer
    b1 More
    m1 Position
    p1 (a -> b
    p a
    a)
             in Get a
    -> forall r.
       ByteString
       -> Buffer
       -> More
       -> Position
       -> Failure r
       -> Success a r
       -> Result r
    forall a.
    Get a
    -> forall r.
       ByteString
       -> Buffer
       -> More
       -> Position
       -> Failure r
       -> Success a r
       -> Result r
    unGet Get a
    m ByteString
    s0 Buffer
    b0 More
    m0 Position
    p0 Failure r
    kf ByteString -> Buffer -> More -> Position -> a -> Result r
    ks'

    instance Applicative Get where
        pure :: forall a. a -> Get a
    pure  = a -> Get a
    forall a. a -> Get a
    forall (m :: * -> *) a. Monad m => a -> m a
    return
        <*> :: forall a b. Get (a -> b) -> Get a -> Get b
    (<*>) = Get (a -> b) -> Get a -> Get b
    forall (m :: * -> *) a b. Monad m => m (a -> b) -> m a -> m b
    ap

    instance Alternative Get where
        empty :: forall a. Get a
    empty = String -> Get a
    forall a. String -> Get a
    failDesc String
    "empty"
        <|> :: forall a. Get a -> Get a -> Get a
    (<|>) = Get a -> Get a -> Get a
    forall a. Get a -> Get a -> Get a
    forall (m :: * -> *) a. MonadPlus m => m a -> m a -> m a
    mplus

    -- Definition directly from Control.Monad.State.Strict
    instance Monad Get where
        return :: forall a. a -> Get a
    return a
    a = (forall r.
     ByteString
     -> Buffer
     -> More
     -> Position
     -> Failure r
     -> Success a r
     -> Result r)
    -> Get a
    forall a.
    (forall r.
     ByteString
     -> Buffer
     -> More
     -> Position
     -> Failure r
     -> Success a r
     -> Result r)
    -> Get a
    Get ((forall r.
      ByteString
      -> Buffer
      -> More
      -> Position
      -> Failure r
      -> Success a r
      -> Result r)
     -> Get a)
    -> (forall r.
        ByteString
        -> Buffer
        -> More
        -> Position
        -> Failure r
        -> Success a r
        -> Result r)
    -> Get a
    forall a b. (a -> b) -> a -> b
    $ \ ByteString
    s0 Buffer
    b0 More
    m0 Position
    p0 Failure r
    _ Success a r
    ks -> Success a r
    ks ByteString
    s0 Buffer
    b0 More
    m0 Position
    p0 a
    a

        Get a
    m >>= :: forall a b. Get a -> (a -> Get b) -> Get b
    >>= a -> Get b
    g  = (forall r.
     ByteString
     -> Buffer
     -> More
     -> Position
     -> Failure r
     -> Success b r
     -> Result r)
    -> Get b
    forall a.
    (forall r.
     ByteString
     -> Buffer
     -> More
     -> Position
     -> Failure r
     -> Success a r
     -> Result r)
    -> Get a
    Get ((forall r.
      ByteString
      -> Buffer
      -> More
      -> Position
      -> Failure r
      -> Success b r
      -> Result r)
     -> Get b)
    -> (forall r.
        ByteString
        -> Buffer
        -> More
        -> Position
        -> Failure r
        -> Success b r
        -> Result r)
    -> Get b
    forall a b. (a -> b) -> a -> b
    $ \ByteString
    s0 Buffer
    b0 More
    m0 Position
    p0 Failure r
    kf Success b r
    ks ->
            let ks' :: ByteString -> Buffer -> More -> Position -> a -> Result r
    ks' ByteString
    s1 Buffer
    b1 More
    m1 Position
    p1 a
    a = Get b
    -> forall r.
       ByteString
       -> Buffer
       -> More
       -> Position
       -> Failure r
       -> Success b r
       -> Result r
    forall a.
    Get a
    -> forall r.
       ByteString
       -> Buffer
       -> More
       -> Position
       -> Failure r
       -> Success a r
       -> Result r
    unGet (a -> Get b
    g a
    a) ByteString
    s1 Buffer
    b1 More
    m1 Position
    p1 Failure r
    kf Success b r
    ks
             in Get a
    -> forall r.
       ByteString
       -> Buffer
       -> More
       -> Position
       -> Failure r
       -> Success a r
       -> Result r
    forall a.
    Get a
    -> forall r.
       ByteString
       -> Buffer
       -> More
       -> Position
       -> Failure r
       -> Success a r
       -> Result r
    unGet Get a
    m ByteString
    s0 Buffer
    b0 More
    m0 Position
    p0 Failure r
    kf ByteString -> Buffer -> More -> Position -> a -> Result r
    ks'

    #if MIN_VERSION_base(4,13,0)
    instance MonadFail Get where
    #endif
        fail :: forall a. String -> Get a
    fail = String -> Get a
    forall a. String -> Get a
    failDesc

    instance MonadPlus Get where
        mzero :: forall a. Get a
    mzero     = String -> Get a
    forall a. String -> Get a
    failDesc String
    "mzero"
        mplus :: forall a. Get a -> Get a -> Get a
    mplus Get a
    a Get a
    b =
          (forall r.
     ByteString
     -> Buffer
     -> More
     -> Position
     -> Failure r
     -> Success a r
     -> Result r)
    -> Get a
    forall a.
    (forall r.
     ByteString
     -> Buffer
     -> More
     -> Position
     -> Failure r
     -> Success a r
     -> Result r)
    -> Get a
    Get ((forall r.
      ByteString
      -> Buffer
      -> More
      -> Position
      -> Failure r
      -> Success a r
      -> Result r)
     -> Get a)
    -> (forall r.
        ByteString
        -> Buffer
        -> More
        -> Position
        -> Failure r
        -> Success a r
        -> Result r)
    -> Get a
    forall a b. (a -> b) -> a -> b
    $ \ByteString
    s0 Buffer
    b0 More
    m0 Position
    p0 Failure r
    kf Success a r
    ks ->
            let kf' :: p -> Buffer -> More -> Position -> p -> Result r
    kf' p
    _ Buffer
    b1 More
    m1 Position
    p1 p
    _ = Get a
    -> forall r.
       ByteString
       -> Buffer
       -> More
       -> Position
       -> Failure r
       -> Success a r
       -> Result r
    forall a.
    Get a
    -> forall r.
       ByteString
       -> Buffer
       -> More
       -> Position
       -> Failure r
       -> Success a r
       -> Result r
    unGet Get a
    b (ByteString
    s0 ByteString -> ByteString -> ByteString
    `B.append` Buffer -> ByteString
    bufferBytes Buffer
    b1)
                                           (Buffer
    b0 Buffer -> Buffer -> Buffer
    `append` Buffer
    b1) More
    m1 Position
    p1 Failure r
    kf Success a r
    ks
             in Get a
    -> forall r.
       ByteString
       -> Buffer
       -> More
       -> Position
       -> Failure r
       -> Success a r
       -> Result r
    forall a.
    Get a
    -> forall r.
       ByteString
       -> Buffer
       -> More
       -> Position
       -> Failure r
       -> Success a r
       -> Result r
    unGet Get a
    a ByteString
    s0 (ByteString -> Buffer
    forall a. a -> Maybe a
    Just ByteString
    B.empty) More
    m0 Position
    p0 Failure r
    forall {p} {p}. p -> Buffer -> More -> Position -> p -> Result r
    kf' Success a r
    ks

    ------------------------------------------------------------------------

    put :: Position -> B.ByteString -> Get ()
    put :: Position -> ByteString -> Get ()
    put Position
    pos ByteString
    s = (forall r.
     ByteString
     -> Buffer
     -> More
     -> Position
     -> Failure r
     -> Success () r
     -> Result r)
    -> Get ()
    forall a.
    (forall r.
     ByteString
     -> Buffer
     -> More
     -> Position
     -> Failure r
     -> Success a r
     -> Result r)
    -> Get a
    Get (\ByteString
    _ Buffer
    b0 More
    m Position
    p0 Failure r
    _ Success () r
    k -> Success () r
    k ByteString
    s Buffer
    b0 More
    m (Position
    p0Position -> Position -> Position
    forall a. Num a => a -> a -> a
    +Position
    pos) ())
    {-# INLINE put #-}

    finalK :: B.ByteString -> t -> t1 -> Position -> r -> Result r
    finalK :: forall t t1 r. ByteString -> t -> t1 -> Position -> r -> Result r
    finalK ByteString
    s t
    _ t1
    _ Position
    p r
    a = r -> Position -> ByteString -> Result r
    forall r. r -> Position -> ByteString -> Result r
    Done r
    a Position
    p ByteString
    s

    failK :: Failure a
    failK :: forall a. Failure a
    failK ByteString
    _ Buffer
    _ More
    _ Position
    p String
    s = String -> Result a
    forall r. String -> Result r
    Fail (Position -> String
    forall a. Show a => a -> String
    show Position
    p String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ String
    ":" String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ String
    s)

    -- | Run the Get monad applies a 'get'-based parser on the input ByteString
    runGetPos :: Position -> Get a -> B.ByteString -> Result a
    runGetPos :: forall a. Position -> Get a -> ByteString -> Result a
    runGetPos Position
    pos Get a
    m ByteString
    str = Get a
    -> forall r.
       ByteString
       -> Buffer
       -> More
       -> Position
       -> Failure r
       -> Success a r
       -> Result r
    forall a.
    Get a
    -> forall r.
       ByteString
       -> Buffer
       -> More
       -> Position
       -> Failure r
       -> Success a r
       -> Result r
    unGet Get a
    m ByteString
    str Buffer
    forall a. Maybe a
    Nothing (Maybe Int -> More
    Incomplete Maybe Int
    forall a. Maybe a
    Nothing) Position
    pos Failure a
    forall a. Failure a
    failK Success a a
    forall t t1 r. ByteString -> t -> t1 -> Position -> r -> Result r
    finalK
    {-# INLINE runGetPos #-}

    runGet :: Get a -> B.ByteString -> Result a
    runGet :: forall a. Get a -> ByteString -> Result a
    runGet = Position -> Get a -> ByteString -> Result a
    forall a. Position -> Get a -> ByteString -> Result a
    runGetPos Position
    0
    {-# INLINE runGet #-}

    -- | If at least @n@ bytes of input are available, return the current
    --   input, otherwise fail.
    ensure :: Int -> Get B.ByteString
    ensure :: Int -> Get ByteString
    ensure Int
    n = Int
    n Int -> Get ByteString -> Get ByteString
    forall a b. a -> b -> b
    `seq` (forall r.
     ByteString
     -> Buffer
     -> More
     -> Position
     -> Failure r
     -> Success ByteString r
     -> Result r)
    -> Get ByteString
    forall a.
    (forall r.
     ByteString
     -> Buffer
     -> More
     -> Position
     -> Failure r
     -> Success a r
     -> Result r)
    -> Get a
    Get ((forall r.
      ByteString
      -> Buffer
      -> More
      -> Position
      -> Failure r
      -> Success ByteString r
      -> Result r)
     -> Get ByteString)
    -> (forall r.
        ByteString
        -> Buffer
        -> More
        -> Position
        -> Failure r
        -> Success ByteString r
        -> Result r)
    -> Get ByteString
    forall a b. (a -> b) -> a -> b
    $ \ ByteString
    s0 Buffer
    b0 More
    m0 Position
    p0 Failure r
    kf Success ByteString r
    ks ->
        if ByteString -> Int
    B.length ByteString
    s0 Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= Int
    n
        then Success ByteString r
    ks ByteString
    s0 Buffer
    b0 More
    m0 Position
    p0 ByteString
    s0
        else Get ByteString
    -> forall r.
       ByteString
       -> Buffer
       -> More
       -> Position
       -> Failure r
       -> Success ByteString r
       -> Result r
    forall a.
    Get a
    -> forall r.
       ByteString
       -> Buffer
       -> More
       -> Position
       -> Failure r
       -> Success a r
       -> Result r
    unGet (Get ()
    demandInput Get () -> Get ByteString -> Get ByteString
    forall a b. Get a -> Get b -> Get b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> Int -> Get ByteString
    ensureRec Int
    n) ByteString
    s0 Buffer
    b0 More
    m0 Position
    p0 Failure r
    kf Success ByteString r
    ks
    {-# INLINE ensure #-}

    -- | If at least @n@ bytes of input are available, return the current
    --   input, otherwise fail.
    ensureRec :: Int -> Get B.ByteString
    ensureRec :: Int -> Get ByteString
    ensureRec Int
    n = (forall r.
     ByteString
     -> Buffer
     -> More
     -> Position
     -> Failure r
     -> Success ByteString r
     -> Result r)
    -> Get ByteString
    forall a.
    (forall r.
     ByteString
     -> Buffer
     -> More
     -> Position
     -> Failure r
     -> Success a r
     -> Result r)
    -> Get a
    Get ((forall r.
      ByteString
      -> Buffer
      -> More
      -> Position
      -> Failure r
      -> Success ByteString r
      -> Result r)
     -> Get ByteString)
    -> (forall r.
        ByteString
        -> Buffer
        -> More
        -> Position
        -> Failure r
        -> Success ByteString r
        -> Result r)
    -> Get ByteString
    forall a b. (a -> b) -> a -> b
    $ \ByteString
    s0 Buffer
    b0 More
    m0 Position
    p0 Failure r
    kf Success ByteString r
    ks ->
        if ByteString -> Int
    B.length ByteString
    s0 Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= Int
    n
        then Success ByteString r
    ks ByteString
    s0 Buffer
    b0 More
    m0 Position
    p0 ByteString
    s0
        else Get ByteString
    -> forall r.
       ByteString
       -> Buffer
       -> More
       -> Position
       -> Failure r
       -> Success ByteString r
       -> Result r
    forall a.
    Get a
    -> forall r.
       ByteString
       -> Buffer
       -> More
       -> Position
       -> Failure r
       -> Success a r
       -> Result r
    unGet (Get ()
    demandInput Get () -> Get ByteString -> Get ByteString
    forall a b. Get a -> Get b -> Get b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> Int -> Get ByteString
    ensureRec Int
    n) ByteString
    s0 Buffer
    b0 More
    m0 Position
    p0 Failure r
    kf Success ByteString r
    ks

    -- | Immediately demand more input via a 'Partial' continuation
    --   result.
    demandInput :: Get ()
    demandInput :: Get ()
    demandInput = (forall r.
     ByteString
     -> Buffer
     -> More
     -> Position
     -> Failure r
     -> Success () r
     -> Result r)
    -> Get ()
    forall a.
    (forall r.
     ByteString
     -> Buffer
     -> More
     -> Position
     -> Failure r
     -> Success a r
     -> Result r)
    -> Get a
    Get ((forall r.
      ByteString
      -> Buffer
      -> More
      -> Position
      -> Failure r
      -> Success () r
      -> Result r)
     -> Get ())
    -> (forall r.
        ByteString
        -> Buffer
        -> More
        -> Position
        -> Failure r
        -> Success () r
        -> Result r)
    -> Get ()
    forall a b. (a -> b) -> a -> b
    $ \ByteString
    s0 Buffer
    b0 More
    m0 Position
    p0 Failure r
    kf Success () r
    ks ->
      case More
    m0 of
        More
    Complete      -> Failure r
    kf ByteString
    s0 Buffer
    b0 More
    m0 Position
    p0 String
    "too few bytes"
        Incomplete Maybe Int
    mb -> (ByteString -> Result r) -> Result r
    forall r. (ByteString -> Result r) -> Result r
    Partial ((ByteString -> Result r) -> Result r)
    -> (ByteString -> Result r) -> Result r
    forall a b. (a -> b) -> a -> b
    $ \ByteString
    s ->
          if ByteString -> Bool
    B.null ByteString
    s
          then Failure r
    kf ByteString
    s0 Buffer
    b0 More
    m0 Position
    p0 String
    "too few bytes"
          else let update :: Int -> Int
    update Int
    l = Int
    l Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - ByteString -> Int
    B.length ByteString
    s
                   s1 :: ByteString
    s1 = ByteString
    s0 ByteString -> ByteString -> ByteString
    `B.append` ByteString
    s
                   b1 :: Buffer
    b1 = Buffer
    b0 Buffer -> Buffer -> Buffer
    `append` ByteString -> Buffer
    forall a. a -> Maybe a
    Just ByteString
    s
                in Success () r
    ks ByteString
    s1 Buffer
    b1 (Maybe Int -> More
    Incomplete (Int -> Int
    update (Int -> Int) -> Maybe Int -> Maybe Int
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    `fmap` Maybe Int
    mb)) Position
    p0 ()

    failDesc :: String -> Get a
    failDesc :: forall a. String -> Get a
    failDesc String
    err = (forall r.
     ByteString
     -> Buffer
     -> More
     -> Position
     -> Failure r
     -> Success a r
     -> Result r)
    -> Get a
    forall a.
    (forall r.
     ByteString
     -> Buffer
     -> More
     -> Position
     -> Failure r
     -> Success a r
     -> Result r)
    -> Get a
    Get (\ByteString
    s0 Buffer
    b0 More
    m0 Position
    p0 Failure r
    kf Success a r
    _ -> Failure r
    kf ByteString
    s0 Buffer
    b0 More
    m0 Position
    p0 (String
    "Failed reading: " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ String
    err))

    ------------------------------------------------------------------------
    -- Utility with ByteStrings

    -- | An efficient 'get' method for strict ByteStrings. Fails if fewer
    -- than @n@ bytes are left in the input. This function creates a fresh
    -- copy of the underlying bytes.
    getBytesCopy :: Int -> Get B.ByteString
    getBytesCopy :: Int -> Get ByteString
    getBytesCopy Int
    n = do
      bs <- Int -> Get ByteString
    getBytes Int
    n
      return $! B.copy bs

    ------------------------------------------------------------------------
    -- Helpers

    -- | Pull @n@ bytes from the input, as a strict ByteString.
    getBytes :: Int -> Get B.ByteString
    getBytes :: Int -> Get ByteString
    getBytes Int
    n
      | Int
    n Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    <= Int
    0    = ByteString -> Get ByteString
    forall a. a -> Get a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ByteString
    B.empty
      | Bool
    otherwise = do
        s <- Int -> Get ByteString
    ensure Int
    n
        let (b1, b2) = B.splitAt n s
        put (fromIntegral n) b2
        return b1

    getWord8 :: Get Word8
    getWord8 :: Get Word8
    getWord8 = do
        s <- Int -> Get ByteString
    ensure Int
    1
        case B.uncons s of
            Maybe (Word8, ByteString)
    Nothing     -> String -> Get Word8
    forall a. HasCallStack => String -> a
    error String
    "getWord8: ensure internal error"
            Just (Word8
    h,ByteString
    b2) -> Position -> ByteString -> Get ()
    put Position
    1 ByteString
    b2 Get () -> Get Word8 -> Get Word8
    forall a b. Get a -> Get b -> Get b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> Word8 -> Get Word8
    forall a. a -> Get a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Word8
    h