#if __GLASGOW_HASKELL__ > 706
#endif
module Codec.CBOR.Read
( deserialiseFromBytes
, deserialiseFromBytesWithSize
, deserialiseIncremental
, DeserialiseFailure(..)
, IDecode(..)
, ByteOffset
) where
#include "cbor.h"
#if !MIN_VERSION_base(4,8,0)
import Control.Applicative
#endif
import GHC.Int
import Control.Monad (ap)
import Control.Monad.ST
import Data.Array.IArray
import Data.Array.Unboxed
import qualified Data.Array.Base as A
import Data.Monoid
import Data.Bits
import Data.ByteString (ByteString)
import qualified Data.ByteString as BS
import qualified Data.ByteString.Unsafe as BS
import qualified Data.ByteString.Lazy as LBS
import qualified Data.ByteString.Lazy.Internal as LBS
import qualified Data.Text as T
import qualified Data.Text.Encoding as T
import Data.Word
import GHC.Word
#if defined(ARCH_32bit)
import GHC.IntWord64
#endif
import GHC.Exts
import GHC.Float (float2Double)
import Data.Typeable
import Control.Exception
import qualified Codec.CBOR.ByteArray as BA
import Codec.CBOR.Decoding hiding (DecodeAction(Done, Fail))
import Codec.CBOR.Decoding (DecodeAction)
import qualified Codec.CBOR.Decoding as D
import Codec.CBOR.Magic
data DeserialiseFailure = DeserialiseFailure ByteOffset String
deriving (Show, Typeable)
instance Exception DeserialiseFailure where
#if MIN_VERSION_base(4,8,0)
displayException (DeserialiseFailure off msg) =
"Codec.CBOR: deserialising failed at offset "
++ show off ++ " : " ++ msg
#endif
data IDecode s a
=
Partial (Maybe BS.ByteString -> ST s (IDecode s a))
| Done !BS.ByteString !ByteOffset a
| Fail !BS.ByteString !ByteOffset DeserialiseFailure
deserialiseFromBytes :: (forall s. Decoder s a)
-> LBS.ByteString
-> Either DeserialiseFailure (LBS.ByteString, a)
deserialiseFromBytes d lbs =
fmap f $ runIDecode (deserialiseIncremental d) lbs
where f (rest, _, x) = (rest, x)
deserialiseFromBytesWithSize :: (forall s. Decoder s a)
-> LBS.ByteString
-> Either DeserialiseFailure (LBS.ByteString, ByteOffset, a)
deserialiseFromBytesWithSize d lbs =
runIDecode (deserialiseIncremental d) lbs
runIDecode :: (forall s. ST s (IDecode s a))
-> LBS.ByteString
-> Either DeserialiseFailure (LBS.ByteString, ByteOffset, a)
runIDecode d lbs =
runST (go lbs =<< d)
where
go :: LBS.ByteString
-> IDecode s a
-> ST s (Either DeserialiseFailure (LBS.ByteString, ByteOffset, a))
go _ (Fail _ _ err) = return (Left err)
go lbs' (Done bs off x) = let rest
| BS.null bs = lbs'
| otherwise = LBS.Chunk bs lbs'
in return (Right (rest, off, x))
go LBS.Empty (Partial k) = k Nothing >>= go LBS.Empty
go (LBS.Chunk bs lbs') (Partial k) = k (Just bs) >>= go lbs'
deserialiseIncremental :: Decoder s a -> ST s (IDecode s a)
deserialiseIncremental decoder = do
da <- getDecodeAction decoder
runIncrementalDecoder (runDecodeAction da)
type ByteOffset = Int64
newtype IncrementalDecoder s a = IncrementalDecoder {
unIncrementalDecoder ::
forall r. (a -> ST s (IDecode s r)) -> ST s (IDecode s r)
}
instance Functor (IncrementalDecoder s) where
fmap f a = a >>= return . f
instance Applicative (IncrementalDecoder s) where
pure x = IncrementalDecoder $ \k -> k x
(<*>) = ap
instance Monad (IncrementalDecoder s) where
return = pure
m >>= f = IncrementalDecoder $ \k ->
unIncrementalDecoder m $ \x ->
unIncrementalDecoder (f x) k
runIncrementalDecoder :: IncrementalDecoder s (ByteString, ByteOffset, a)
-> ST s (IDecode s a)
runIncrementalDecoder (IncrementalDecoder f) =
f (\(trailing, off, x) -> return $ Done trailing off x)
decodeFail :: ByteString -> ByteOffset -> String -> IncrementalDecoder s a
decodeFail trailing off msg = IncrementalDecoder $ \_ -> return $ Fail trailing off exn
where exn = DeserialiseFailure off msg
needChunk :: IncrementalDecoder s (Maybe ByteString)
needChunk = IncrementalDecoder $ \k -> return $ Partial $ \mbs -> k mbs
lift :: ST s a -> IncrementalDecoder s a
lift action = IncrementalDecoder (\k -> action >>= k)
runDecodeAction :: DecodeAction s a
-> IncrementalDecoder s (ByteString, ByteOffset, a)
runDecodeAction (D.Fail msg) = decodeFail BS.empty 0 msg
runDecodeAction (D.Done x) = return (BS.empty, 0, x)
runDecodeAction (D.PeekAvailable k) = lift (k 0#) >>= runDecodeAction
runDecodeAction da = do
mbs <- needChunk
case mbs of
Nothing -> decodeFail BS.empty 0 "end of input"
Just bs -> go_slow da bs 0
data SlowPath s a
= FastDone !ByteString a
| SlowConsumeTokenBytes !ByteString (ByteString -> ST s (DecodeAction s a)) !Int
| SlowConsumeTokenByteArray !ByteString (BA.ByteArray -> ST s (DecodeAction s a)) !Int
| SlowConsumeTokenString !ByteString (T.Text -> ST s (DecodeAction s a)) !Int
| SlowConsumeTokenUtf8ByteArray !ByteString (BA.ByteArray -> ST s (DecodeAction s a)) !Int
| SlowDecodeAction !ByteString (DecodeAction s a)
| SlowFail !ByteString String
go_fast :: ByteString -> DecodeAction s a -> ST s (SlowPath s a)
go_fast !bs da | BS.length bs < 9 = go_fast_end bs da
go_fast !bs da@(ConsumeWord k) =
case tryConsumeWord (BS.unsafeHead bs) bs of
DecodeFailure -> go_fast_end bs da
DecodedToken sz (W# w#) -> k w# >>= go_fast (BS.unsafeDrop sz bs)
go_fast !bs da@(ConsumeWord8 k) =
case tryConsumeWord (BS.unsafeHead bs) bs of
DecodeFailure -> go_fast_end bs da
DecodedToken sz (W# w#) ->
case gtWord# w# 0xff## of
0# -> k w# >>= go_fast (BS.unsafeDrop sz bs)
_ -> go_fast_end bs da
go_fast !bs da@(ConsumeWord16 k) =
case tryConsumeWord (BS.unsafeHead bs) bs of
DecodeFailure -> go_fast_end bs da
DecodedToken sz (W# w#) ->
case gtWord# w# 0xffff## of
0# -> k w# >>= go_fast (BS.unsafeDrop sz bs)
_ -> go_fast_end bs da
go_fast !bs da@(ConsumeWord32 k) =
case tryConsumeWord (BS.unsafeHead bs) bs of
DecodeFailure -> go_fast_end bs da
DecodedToken sz (W# w#) ->
#if defined(ARCH_32bit)
k w# >>= go_fast (BS.unsafeDrop sz bs)
#else
case gtWord# w# 0xffffffff## of
0# -> k w# >>= go_fast (BS.unsafeDrop sz bs)
_ -> go_fast_end bs da
#endif
go_fast !bs da@(ConsumeNegWord k) =
case tryConsumeNegWord (BS.unsafeHead bs) bs of
DecodeFailure -> go_fast_end bs da
DecodedToken sz (W# w#) -> k w# >>= go_fast (BS.unsafeDrop sz bs)
go_fast !bs da@(ConsumeInt k) =
case tryConsumeInt (BS.unsafeHead bs) bs of
DecodeFailure -> go_fast_end bs da
DecodedToken sz (I# n#) -> k n# >>= go_fast (BS.unsafeDrop sz bs)
go_fast !bs da@(ConsumeInt8 k) =
case tryConsumeInt (BS.unsafeHead bs) bs of
DecodeFailure -> go_fast_end bs da
DecodedToken sz (I# n#) ->
case (n# ># 0x7f#) `orI#` (n# <# 0x80#) of
0# -> k n# >>= go_fast (BS.unsafeDrop sz bs)
_ -> go_fast_end bs da
go_fast !bs da@(ConsumeInt16 k) =
case tryConsumeInt (BS.unsafeHead bs) bs of
DecodeFailure -> go_fast_end bs da
DecodedToken sz (I# n#) ->
case (n# ># 0x7fff#) `orI#` (n# <# 0x8000#) of
0# -> k n# >>= go_fast (BS.unsafeDrop sz bs)
_ -> go_fast_end bs da
go_fast !bs da@(ConsumeInt32 k) =
case tryConsumeInt (BS.unsafeHead bs) bs of
DecodeFailure -> go_fast_end bs da
DecodedToken sz (I# n#) ->
#if defined(ARCH_32bit)
k n# >>= go_fast (BS.unsafeDrop sz bs)
#else
case (n# ># 0x7fffffff#) `orI#` (n# <# 0x80000000#) of
0# -> k n# >>= go_fast (BS.unsafeDrop sz bs)
_ -> go_fast_end bs da
#endif
go_fast !bs da@(ConsumeListLen k) =
case tryConsumeListLen (BS.unsafeHead bs) bs of
DecodeFailure -> go_fast_end bs da
DecodedToken sz (I# n#) -> k n# >>= go_fast (BS.unsafeDrop sz bs)
go_fast !bs da@(ConsumeMapLen k) =
case tryConsumeMapLen (BS.unsafeHead bs) bs of
DecodeFailure -> go_fast_end bs da
DecodedToken sz (I# n#) -> k n# >>= go_fast (BS.unsafeDrop sz bs)
go_fast !bs da@(ConsumeTag k) =
case tryConsumeTag (BS.unsafeHead bs) bs of
DecodeFailure -> go_fast_end bs da
DecodedToken sz (W# w#) -> k w# >>= go_fast (BS.unsafeDrop sz bs)
go_fast !bs da@(ConsumeWordCanonical k) =
case tryConsumeWord (BS.unsafeHead bs) bs of
DecodeFailure -> go_fast_end bs da
DecodedToken sz (W# w#)
| isWordCanonical sz w# -> k w# >>= go_fast (BS.unsafeDrop sz bs)
| otherwise -> go_fast_end bs da
go_fast !bs da@(ConsumeWord8Canonical k) =
case tryConsumeWord (BS.unsafeHead bs) bs of
DecodeFailure -> go_fast_end bs da
DecodedToken sz (W# w#) ->
case gtWord# w# 0xff## of
0# | isWordCanonical sz w# -> k w# >>= go_fast (BS.unsafeDrop sz bs)
_ -> go_fast_end bs da
go_fast !bs da@(ConsumeWord16Canonical k) =
case tryConsumeWord (BS.unsafeHead bs) bs of
DecodeFailure -> go_fast_end bs da
DecodedToken sz (W# w#) ->
case gtWord# w# 0xffff## of
0# | isWordCanonical sz w# -> k w# >>= go_fast (BS.unsafeDrop sz bs)
_ -> go_fast_end bs da
go_fast !bs da@(ConsumeWord32Canonical k) =
case tryConsumeWord (BS.unsafeHead bs) bs of
DecodeFailure -> go_fast_end bs da
DecodedToken sz (W# w#) ->
case w_out_of_range w# of
0# | isWordCanonical sz w# -> k w# >>= go_fast (BS.unsafeDrop sz bs)
_ -> go_fast_end bs da
where
w_out_of_range _w# =
#if defined(ARCH_32bit)
0#
#else
gtWord# _w# 0xffffffff##
#endif
go_fast !bs da@(ConsumeNegWordCanonical k) =
case tryConsumeNegWord (BS.unsafeHead bs) bs of
DecodeFailure -> go_fast_end bs da
DecodedToken sz (W# w#)
| isWordCanonical sz w# -> k w# >>= go_fast (BS.unsafeDrop sz bs)
| otherwise -> go_fast_end bs da
go_fast !bs da@(ConsumeIntCanonical k) =
case tryConsumeInt (BS.unsafeHead bs) bs of
DecodeFailure -> go_fast_end bs da
DecodedToken sz (I# n#)
| isIntCanonical sz n# -> k n# >>= go_fast (BS.unsafeDrop sz bs)
| otherwise -> go_fast_end bs da
go_fast !bs da@(ConsumeInt8Canonical k) =
case tryConsumeInt (BS.unsafeHead bs) bs of
DecodeFailure -> go_fast_end bs da
DecodedToken sz (I# n#) ->
case (n# ># 0x7f#) `orI#` (n# <# 0x80#) of
0# | isIntCanonical sz n# -> k n# >>= go_fast (BS.unsafeDrop sz bs)
_ -> go_fast_end bs da
go_fast !bs da@(ConsumeInt16Canonical k) =
case tryConsumeInt (BS.unsafeHead bs) bs of
DecodeFailure -> go_fast_end bs da
DecodedToken sz (I# n#) ->
case (n# ># 0x7fff#) `orI#` (n# <# 0x8000#) of
0# | isIntCanonical sz n# -> k n# >>= go_fast (BS.unsafeDrop sz bs)
_ -> go_fast_end bs da
go_fast !bs da@(ConsumeInt32Canonical k) =
case tryConsumeInt (BS.unsafeHead bs) bs of
DecodeFailure -> go_fast_end bs da
DecodedToken sz (I# n#) ->
case n_out_of_range n# of
0# | isIntCanonical sz n# -> k n# >>= go_fast (BS.unsafeDrop sz bs)
_ -> go_fast_end bs da
where
n_out_of_range _n# =
#if defined(ARCH_32bit)
0#
#else
(_n# ># 0x7fffffff#) `orI#` (_n# <# 0x80000000#)
#endif
go_fast !bs da@(ConsumeListLenCanonical k) =
case tryConsumeListLen (BS.unsafeHead bs) bs of
DecodeFailure -> go_fast_end bs da
DecodedToken sz (I# n#)
| isWordCanonical sz (int2Word# n#) -> k n# >>= go_fast (BS.unsafeDrop sz bs)
| otherwise -> go_fast_end bs da
go_fast !bs da@(ConsumeMapLenCanonical k) =
case tryConsumeMapLen (BS.unsafeHead bs) bs of
DecodeFailure -> go_fast_end bs da
DecodedToken sz (I# n#)
| isWordCanonical sz (int2Word# n#) -> k n# >>= go_fast (BS.unsafeDrop sz bs)
| otherwise -> go_fast_end bs da
go_fast !bs da@(ConsumeTagCanonical k) =
case tryConsumeTag (BS.unsafeHead bs) bs of
DecodeFailure -> go_fast_end bs da
DecodedToken sz (W# w#)
| isWordCanonical sz w# -> k w# >>= go_fast (BS.unsafeDrop sz bs)
| otherwise -> go_fast_end bs da
#if defined(ARCH_32bit)
go_fast !bs da@(ConsumeWord64 k) =
case tryConsumeWord64 (BS.unsafeHead bs) bs of
DecodeFailure -> go_fast_end bs da
DecodedToken sz (W64# w#) -> k w# >>= go_fast (BS.unsafeDrop sz bs)
go_fast !bs da@(ConsumeNegWord64 k) =
case tryConsumeNegWord64 (BS.unsafeHead bs) bs of
DecodeFailure -> go_fast_end bs da
DecodedToken sz (W64# w#) -> k w# >>= go_fast (BS.unsafeDrop sz bs)
go_fast !bs da@(ConsumeInt64 k) =
case tryConsumeInt64 (BS.unsafeHead bs) bs of
DecodeFailure -> go_fast_end bs da
DecodedToken sz (I64# i#) -> k i# >>= go_fast (BS.unsafeDrop sz bs)
go_fast !bs da@(ConsumeListLen64 k) =
case tryConsumeListLen64 (BS.unsafeHead bs) bs of
DecodeFailure -> go_fast_end bs da
DecodedToken sz (I64# i#) -> k i# >>= go_fast (BS.unsafeDrop sz bs)
go_fast !bs da@(ConsumeMapLen64 k) =
case tryConsumeMapLen64 (BS.unsafeHead bs) bs of
DecodeFailure -> go_fast_end bs da
DecodedToken sz (I64# i#) -> k i# >>= go_fast (BS.unsafeDrop sz bs)
go_fast !bs da@(ConsumeTag64 k) =
case tryConsumeTag64 (BS.unsafeHead bs) bs of
DecodeFailure -> go_fast_end bs da
DecodedToken sz (W64# w#) -> k w# >>= go_fast (BS.unsafeDrop sz bs)
go_fast !bs da@(ConsumeWord64Canonical k) =
case tryConsumeWord64 (BS.unsafeHead bs) bs of
DecodeFailure -> go_fast_end bs da
DecodedToken sz (W64# w#)
| isWord64Canonical -> k w# >>= go_fast (BS.unsafeDrop sz bs)
| otherwise -> go_fast_end bs da
go_fast !bs da@(ConsumeNegWord64Canonical k) =
case tryConsumeNegWord64 (BS.unsafeHead bs) bs of
DecodeFailure -> go_fast_end bs da
DecodedToken sz (W64# w#)
| isWord64Canonical sz w# -> k w# >>= go_fast (BS.unsafeDrop sz bs)
| otherwise -> go_fast_end bs da
go_fast !bs da@(ConsumeInt64Canonical k) =
case tryConsumeInt64 (BS.unsafeHead bs) bs of
DecodeFailure -> go_fast_end bs da
DecodedToken sz (I64# i#)
| isInt64Canonical sz i# -> k i# >>= go_fast (BS.unsafeDrop sz bs)
| otherwise -> go_fast_end bs da
go_fast !bs da@(ConsumeListLen64Canonical k) =
case tryConsumeListLen64 (BS.unsafeHead bs) bs of
DecodeFailure -> go_fast_end bs da
DecodedToken sz (I64# i#)
| isWord64Canonical sz (int64ToWord64 i#) -> k i# >>= go_fast (BS.unsafeDrop sz bs)
| otherwise -> go_fast_end bs da
go_fast !bs da@(ConsumeMapLen64Canonical k) =
case tryConsumeMapLen64 (BS.unsafeHead bs) bs of
DecodeFailure -> go_fast_end bs da
DecodedToken sz (I64# i#)
| isWord64Canonical sz (int64ToWord64 i#) -> k i# >>= go_fast (BS.unsafeDrop sz bs)
| otherwise -> go_fast_end bs da
go_fast !bs da@(ConsumeTag64Canonical k) =
case tryConsumeTag64 (BS.unsafeHead bs) bs of
DecodeFailure -> go_fast_end bs da
DecodedToken sz (W64# w#)
| isWord64Canonical sz w# -> k w# >>= go_fast (BS.unsafeDrop sz bs)
| otherwise -> go_fast_end bs da
#endif
go_fast !bs da@(ConsumeInteger k) =
case tryConsumeInteger (BS.unsafeHead bs) bs of
DecodedToken sz (BigIntToken _ n) -> k n >>= go_fast (BS.unsafeDrop sz bs)
_ -> go_fast_end bs da
go_fast !bs da@(ConsumeFloat k) =
case tryConsumeFloat (BS.unsafeHead bs) bs of
DecodeFailure -> go_fast_end bs da
DecodedToken sz (F# f#) -> k f# >>= go_fast (BS.unsafeDrop sz bs)
go_fast !bs da@(ConsumeDouble k) =
case tryConsumeDouble (BS.unsafeHead bs) bs of
DecodeFailure -> go_fast_end bs da
DecodedToken sz (D# f#) -> k f# >>= go_fast (BS.unsafeDrop sz bs)
go_fast !bs da@(ConsumeBytes k) =
case tryConsumeBytes (BS.unsafeHead bs) bs of
DecodeFailure -> go_fast_end bs da
DecodedToken sz (Fits bstr) -> k bstr >>= go_fast (BS.unsafeDrop sz bs)
DecodedToken sz (TooLong len) -> return $! SlowConsumeTokenBytes (BS.unsafeDrop sz bs) k len
go_fast !bs da@(ConsumeByteArray k) =
case tryConsumeBytes (BS.unsafeHead bs) bs of
DecodeFailure -> go_fast_end bs da
DecodedToken sz (Fits str) -> k (BA.fromByteString str) >>= go_fast (BS.unsafeDrop sz bs)
DecodedToken sz (TooLong len) -> return $! SlowConsumeTokenByteArray (BS.unsafeDrop sz bs) k len
go_fast !bs da@(ConsumeString k) =
case tryConsumeString (BS.unsafeHead bs) bs of
DecodeFailure -> go_fast_end bs da
DecodedToken sz (Fits str) -> case T.decodeUtf8' str of
Right t -> k t >>= go_fast (BS.unsafeDrop sz bs)
Left e -> return $! SlowFail bs (show e)
DecodedToken sz (TooLong len) -> return $! SlowConsumeTokenString (BS.unsafeDrop sz bs) k len
go_fast !bs da@(ConsumeUtf8ByteArray k) =
case tryConsumeString (BS.unsafeHead bs) bs of
DecodeFailure -> go_fast_end bs da
DecodedToken sz (Fits str) -> k (BA.fromByteString str) >>= go_fast (BS.unsafeDrop sz bs)
DecodedToken sz (TooLong len) -> return $! SlowConsumeTokenUtf8ByteArray (BS.unsafeDrop sz bs) k len
go_fast !bs da@(ConsumeBool k) =
case tryConsumeBool (BS.unsafeHead bs) of
DecodeFailure -> go_fast_end bs da
DecodedToken sz b -> k b >>= go_fast (BS.unsafeDrop sz bs)
go_fast !bs da@(ConsumeSimple k) =
case tryConsumeSimple (BS.unsafeHead bs) bs of
DecodeFailure -> go_fast_end bs da
DecodedToken sz (W# w#) -> k w# >>= go_fast (BS.unsafeDrop sz bs)
go_fast !bs da@(ConsumeIntegerCanonical k) =
case tryConsumeInteger (BS.unsafeHead bs) bs of
DecodedToken sz (BigIntToken True n) -> k n >>= go_fast (BS.unsafeDrop sz bs)
_ -> go_fast_end bs da
go_fast !bs da@(ConsumeFloat16Canonical k) =
case tryConsumeFloat (BS.unsafeHead bs) bs of
DecodeFailure -> go_fast_end bs da
DecodedToken sz (F# f#)
| isFloat16Canonical sz -> k f# >>= go_fast (BS.unsafeDrop sz bs)
| otherwise -> go_fast_end bs da
go_fast !bs da@(ConsumeFloatCanonical k) =
case tryConsumeFloat (BS.unsafeHead bs) bs of
DecodeFailure -> go_fast_end bs da
DecodedToken sz f@(F# f#)
| isFloatCanonical sz bs f -> k f# >>= go_fast (BS.unsafeDrop sz bs)
| otherwise -> go_fast_end bs da
go_fast !bs da@(ConsumeDoubleCanonical k) =
case tryConsumeDouble (BS.unsafeHead bs) bs of
DecodeFailure -> go_fast_end bs da
DecodedToken sz f@(D# f#)
| isDoubleCanonical sz bs f -> k f# >>= go_fast (BS.unsafeDrop sz bs)
| otherwise -> go_fast_end bs da
go_fast !bs da@(ConsumeSimpleCanonical k) =
case tryConsumeSimple (BS.unsafeHead bs) bs of
DecodeFailure -> go_fast_end bs da
DecodedToken sz (W# w#)
| isWordCanonical sz w# -> k w# >>= go_fast (BS.unsafeDrop sz bs)
| otherwise -> go_fast_end bs da
go_fast !bs da@(ConsumeBytesIndef k) =
case tryConsumeBytesIndef (BS.unsafeHead bs) of
DecodeFailure -> go_fast_end bs da
DecodedToken sz _ -> k >>= go_fast (BS.unsafeDrop sz bs)
go_fast !bs da@(ConsumeStringIndef k) =
case tryConsumeStringIndef (BS.unsafeHead bs) of
DecodeFailure -> go_fast_end bs da
DecodedToken sz _ -> k >>= go_fast (BS.unsafeDrop sz bs)
go_fast !bs da@(ConsumeListLenIndef k) =
case tryConsumeListLenIndef (BS.unsafeHead bs) of
DecodeFailure -> go_fast_end bs da
DecodedToken sz _ -> k >>= go_fast (BS.unsafeDrop sz bs)
go_fast !bs da@(ConsumeMapLenIndef k) =
case tryConsumeMapLenIndef (BS.unsafeHead bs) of
DecodeFailure -> go_fast_end bs da
DecodedToken sz _ -> k >>= go_fast (BS.unsafeDrop sz bs)
go_fast !bs da@(ConsumeNull k) =
case tryConsumeNull (BS.unsafeHead bs) of
DecodeFailure -> go_fast_end bs da
DecodedToken sz _ -> k >>= go_fast (BS.unsafeDrop sz bs)
go_fast !bs da@(ConsumeListLenOrIndef k) =
case tryConsumeListLenOrIndef (BS.unsafeHead bs) bs of
DecodeFailure -> go_fast_end bs da
DecodedToken sz (I# n#) -> k n# >>= go_fast (BS.unsafeDrop sz bs)
go_fast !bs da@(ConsumeMapLenOrIndef k) =
case tryConsumeMapLenOrIndef (BS.unsafeHead bs) bs of
DecodeFailure -> go_fast_end bs da
DecodedToken sz (I# n#) -> k n# >>= go_fast (BS.unsafeDrop sz bs)
go_fast !bs (ConsumeBreakOr k) =
case tryConsumeBreakOr (BS.unsafeHead bs) of
DecodeFailure -> k False >>= go_fast bs
DecodedToken sz _ -> k True >>= go_fast (BS.unsafeDrop sz bs)
go_fast !bs (PeekTokenType k) =
let !hdr = BS.unsafeHead bs
!tkty = decodeTokenTypeTable `A.unsafeAt` fromIntegral hdr
in k tkty >>= go_fast bs
go_fast !bs (PeekAvailable k) = k (case BS.length bs of I# len# -> len#) >>= go_fast bs
go_fast !bs da@D.Fail{} = go_fast_end bs da
go_fast !bs da@D.Done{} = go_fast_end bs da
go_fast_end :: ByteString -> DecodeAction s a -> ST s (SlowPath s a)
go_fast_end !bs (D.Fail msg) = return $! SlowFail bs msg
go_fast_end !bs (D.Done x) = return $! FastDone bs x
go_fast_end !bs (PeekAvailable k) = k (case BS.length bs of I# len# -> len#) >>= go_fast_end bs
go_fast_end !bs da | BS.null bs = return $! SlowDecodeAction bs da
go_fast_end !bs (ConsumeBreakOr k) =
case tryConsumeBreakOr (BS.unsafeHead bs) of
DecodeFailure -> k False >>= go_fast_end bs
DecodedToken sz _ -> k True >>= go_fast_end (BS.unsafeDrop sz bs)
go_fast_end !bs (PeekTokenType k) =
let !hdr = BS.unsafeHead bs
!tkty = decodeTokenTypeTable `A.unsafeAt` fromIntegral hdr
in k tkty >>= go_fast_end bs
go_fast_end !bs da
| let !hdr = BS.unsafeHead bs
, BS.length bs < tokenSize hdr
= return $! SlowDecodeAction bs da
go_fast_end !bs (ConsumeWord k) =
case tryConsumeWord (BS.unsafeHead bs) bs of
DecodeFailure -> return $! SlowFail bs "expected word"
DecodedToken sz (W# w#) -> k w# >>= go_fast_end (BS.unsafeDrop sz bs)
go_fast_end !bs (ConsumeWord8 k) =
case tryConsumeWord (BS.unsafeHead bs) bs of
DecodeFailure -> return $! SlowFail bs "expected word8"
DecodedToken sz (W# w#) ->
case gtWord# w# 0xff## of
0# -> k w# >>= go_fast_end (BS.unsafeDrop sz bs)
_ -> return $! SlowFail bs "expected word8"
go_fast_end !bs (ConsumeWord16 k) =
case tryConsumeWord (BS.unsafeHead bs) bs of
DecodeFailure -> return $! SlowFail bs "expected word16"
DecodedToken sz (W# w#) ->
case gtWord# w# 0xffff## of
0# -> k w# >>= go_fast_end (BS.unsafeDrop sz bs)
_ -> return $! SlowFail bs "expected word16"
go_fast_end !bs (ConsumeWord32 k) =
case tryConsumeWord (BS.unsafeHead bs) bs of
DecodeFailure -> return $! SlowFail bs "expected word32"
DecodedToken sz (W# w#) ->
#if defined(ARCH_32bit)
k w# >>= go_fast_end (BS.unsafeDrop sz bs)
#else
case gtWord# w# 0xffffffff## of
0# -> k w# >>= go_fast_end (BS.unsafeDrop sz bs)
_ -> return $! SlowFail bs "expected word32"
#endif
go_fast_end !bs (ConsumeNegWord k) =
case tryConsumeNegWord (BS.unsafeHead bs) bs of
DecodeFailure -> return $! SlowFail bs "expected negative int"
DecodedToken sz (W# w#) -> k w# >>= go_fast_end (BS.unsafeDrop sz bs)
go_fast_end !bs (ConsumeInt k) =
case tryConsumeInt (BS.unsafeHead bs) bs of
DecodeFailure -> return $! SlowFail bs "expected int"
DecodedToken sz (I# n#) -> k n# >>= go_fast_end (BS.unsafeDrop sz bs)
go_fast_end !bs (ConsumeInt8 k) =
case tryConsumeInt (BS.unsafeHead bs) bs of
DecodeFailure -> return $! SlowFail bs "expected int8"
DecodedToken sz (I# n#) ->
case (n# ># 0x7f#) `orI#` (n# <# 0x80#) of
0# -> k n# >>= go_fast_end (BS.unsafeDrop sz bs)
_ -> return $! SlowFail bs "expected int8"
go_fast_end !bs (ConsumeInt16 k) =
case tryConsumeInt (BS.unsafeHead bs) bs of
DecodeFailure -> return $! SlowFail bs "expected int16"
DecodedToken sz (I# n#) ->
case (n# ># 0x7fff#) `orI#` (n# <# 0x8000#) of
0# -> k n# >>= go_fast_end (BS.unsafeDrop sz bs)
_ -> return $! SlowFail bs "expected int16"
go_fast_end !bs (ConsumeInt32 k) =
case tryConsumeInt (BS.unsafeHead bs) bs of
DecodeFailure -> return $! SlowFail bs "expected int32"
DecodedToken sz (I# n#) ->
#if defined(ARCH_32bit)
k n# >>= go_fast_end (BS.unsafeDrop sz bs)
#else
case (n# ># 0x7fffffff#) `orI#` (n# <# 0x80000000#) of
0# -> k n# >>= go_fast_end (BS.unsafeDrop sz bs)
_ -> return $! SlowFail bs "expected int32"
#endif
go_fast_end !bs (ConsumeListLen k) =
case tryConsumeListLen (BS.unsafeHead bs) bs of
DecodeFailure -> return $! SlowFail bs "expected list len"
DecodedToken sz (I# n#) -> k n# >>= go_fast_end (BS.unsafeDrop sz bs)
go_fast_end !bs (ConsumeMapLen k) =
case tryConsumeMapLen (BS.unsafeHead bs) bs of
DecodeFailure -> return $! SlowFail bs "expected map len"
DecodedToken sz (I# n#) -> k n# >>= go_fast_end (BS.unsafeDrop sz bs)
go_fast_end !bs (ConsumeTag k) =
case tryConsumeTag (BS.unsafeHead bs) bs of
DecodeFailure -> return $! SlowFail bs "expected tag"
DecodedToken sz (W# w#) -> k w# >>= go_fast_end (BS.unsafeDrop sz bs)
go_fast_end !bs (ConsumeWordCanonical k) =
case tryConsumeWord (BS.unsafeHead bs) bs of
DecodeFailure -> return $! SlowFail bs "expected word"
DecodedToken sz (W# w#)
| isWordCanonical sz w# -> k w# >>= go_fast_end (BS.unsafeDrop sz bs)
| otherwise -> return $! SlowFail bs "non-canonical word"
go_fast_end !bs (ConsumeWord8Canonical k) =
case tryConsumeWord (BS.unsafeHead bs) bs of
DecodeFailure -> return $! SlowFail bs "expected word8"
DecodedToken sz (W# w#) -> case gtWord# w# 0xff## of
0# | isWordCanonical sz w# -> k w# >>= go_fast_end (BS.unsafeDrop sz bs)
| otherwise -> return $! SlowFail bs "non-canonical word8"
_ -> return $! SlowFail bs "expected word8"
go_fast_end !bs (ConsumeWord16Canonical k) =
case tryConsumeWord (BS.unsafeHead bs) bs of
DecodeFailure -> return $! SlowFail bs "expected word16"
DecodedToken sz (W# w#) -> case gtWord# w# 0xffff## of
0# | isWordCanonical sz w# -> k w# >>= go_fast_end (BS.unsafeDrop sz bs)
| otherwise -> return $! SlowFail bs "non-canonical word16"
_ -> return $! SlowFail bs "expected word16"
go_fast_end !bs (ConsumeWord32Canonical k) =
case tryConsumeWord (BS.unsafeHead bs) bs of
DecodeFailure -> return $! SlowFail bs "expected word32"
DecodedToken sz (W# w#) -> case w_out_of_range w# of
0# | isWordCanonical sz w# -> k w# >>= go_fast_end (BS.unsafeDrop sz bs)
| otherwise -> return $! SlowFail bs "non-canonical word32"
_ -> return $! SlowFail bs "expected word32"
where
w_out_of_range _w# =
#if defined(ARCH_32bit)
0#
#else
gtWord# _w# 0xffffffff##
#endif
go_fast_end !bs (ConsumeNegWordCanonical k) =
case tryConsumeNegWord (BS.unsafeHead bs) bs of
DecodeFailure -> return $! SlowFail bs "expected negative int"
DecodedToken sz (W# w#)
| isWordCanonical sz w# -> k w# >>= go_fast_end (BS.unsafeDrop sz bs)
| otherwise -> return $! SlowFail bs "non-canonical negative int"
go_fast_end !bs (ConsumeIntCanonical k) =
case tryConsumeInt (BS.unsafeHead bs) bs of
DecodeFailure -> return $! SlowFail bs "expected int"
DecodedToken sz (I# n#)
| isIntCanonical sz n# -> k n# >>= go_fast_end (BS.unsafeDrop sz bs)
| otherwise -> return $! SlowFail bs "non-canonical int"
go_fast_end !bs (ConsumeInt8Canonical k) =
case tryConsumeInt (BS.unsafeHead bs) bs of
DecodeFailure -> return $! SlowFail bs "expected int8"
DecodedToken sz (I# n#) ->
case (n# ># 0x7f#) `orI#` (n# <# 0x80#) of
0# | isIntCanonical sz n# -> k n# >>= go_fast_end (BS.unsafeDrop sz bs)
| otherwise -> return $! SlowFail bs "non-canonical int8"
_ -> return $! SlowFail bs "expected int8"
go_fast_end !bs (ConsumeInt16Canonical k) =
case tryConsumeInt (BS.unsafeHead bs) bs of
DecodeFailure -> return $! SlowFail bs "expected int16"
DecodedToken sz (I# n#) ->
case (n# ># 0x7fff#) `orI#` (n# <# 0x8000#) of
0# | isIntCanonical sz n# -> k n# >>= go_fast_end (BS.unsafeDrop sz bs)
| otherwise -> return $! SlowFail bs "non-canonical int16"
_ -> return $! SlowFail bs "expected int16"
go_fast_end !bs (ConsumeInt32Canonical k) =
case tryConsumeInt (BS.unsafeHead bs) bs of
DecodeFailure -> return $! SlowFail bs "expected int32"
DecodedToken sz (I# n#) ->
case n_out_of_range n# of
0# | isIntCanonical sz n# -> k n# >>= go_fast_end (BS.unsafeDrop sz bs)
| otherwise -> return $! SlowFail bs "non-canonical int32"
_ -> return $! SlowFail bs "expected int32"
where
n_out_of_range _n# =
#if defined(ARCH_32bit)
0#
#else
(_n# ># 0x7fffffff#) `orI#` (_n# <# 0x80000000#)
#endif
go_fast_end !bs (ConsumeListLenCanonical k) =
case tryConsumeListLen (BS.unsafeHead bs) bs of
DecodeFailure -> return $! SlowFail bs "expected list len"
DecodedToken sz (I# n#)
| isWordCanonical sz (int2Word# n#) -> k n# >>= go_fast_end (BS.unsafeDrop sz bs)
| otherwise -> return $! SlowFail bs "non-canonical list len"
go_fast_end !bs (ConsumeMapLenCanonical k) =
case tryConsumeMapLen (BS.unsafeHead bs) bs of
DecodeFailure -> return $! SlowFail bs "expected map len"
DecodedToken sz (I# n#)
| isWordCanonical sz (int2Word# n#) -> k n# >>= go_fast_end (BS.unsafeDrop sz bs)
| otherwise -> return $! SlowFail bs "non-canonical map len"
go_fast_end !bs (ConsumeTagCanonical k) =
case tryConsumeTag (BS.unsafeHead bs) bs of
DecodeFailure -> return $! SlowFail bs "expected tag"
DecodedToken sz (W# w#)
| isWordCanonical sz w# -> k w# >>= go_fast_end (BS.unsafeDrop sz bs)
| otherwise -> return $! SlowFail bs "non-canonical tag"
#if defined(ARCH_32bit)
go_fast_end !bs (ConsumeWord64 k) =
case tryConsumeWord64 (BS.unsafeHead bs) bs of
DecodeFailure -> return $! SlowFail bs "expected word64"
DecodedToken sz (W64# w#) -> k w# >>= go_fast_end (BS.unsafeDrop sz bs)
go_fast_end !bs (ConsumeNegWord64 k) =
case tryConsumeNegWord64 (BS.unsafeHead bs) bs of
DecodeFailure -> return $! SlowFail bs "expected negative word64"
DecodedToken sz (W64# w#) -> k w# >>= go_fast_end (BS.unsafeDrop sz bs)
go_fast_end !bs (ConsumeInt64 k) =
case tryConsumeInt64 (BS.unsafeHead bs) bs of
DecodeFailure -> return $! SlowFail bs "expected int64"
DecodedToken sz (I64# i#) -> k i# >>= go_fast_end (BS.unsafeDrop sz bs)
go_fast_end !bs (ConsumeListLen64 k) =
case tryConsumeListLen64 (BS.unsafeHead bs) bs of
DecodeFailure -> return $! SlowFail bs "expected list len 64"
DecodedToken sz (I64# i#) -> k i# >>= go_fast_end (BS.unsafeDrop sz bs)
go_fast_end !bs (ConsumeMapLen64 k) =
case tryConsumeMapLen64 (BS.unsafeHead bs) bs of
DecodeFailure -> return $! SlowFail bs "expected map len 64"
DecodedToken sz (I64# i#) -> k i# >>= go_fast_end (BS.unsafeDrop sz bs)
go_fast_end !bs (ConsumeTag64 k) =
case tryConsumeTag64 (BS.unsafeHead bs) bs of
DecodeFailure -> return $! SlowFail bs "expected tag64"
DecodedToken sz (W64# w#) -> k w# >>= go_fast_end (BS.unsafeDrop sz bs)
#endif
go_fast_end !bs (ConsumeInteger k) =
case tryConsumeInteger (BS.unsafeHead bs) bs of
DecodeFailure -> return $! SlowFail bs "expected integer"
DecodedToken sz (BigIntToken _ n) -> k n >>= go_fast_end (BS.unsafeDrop sz bs)
DecodedToken sz (BigUIntNeedBody len) -> return $! SlowConsumeTokenBytes (BS.unsafeDrop sz bs) (adjustContBigUIntNeedBody k) len
DecodedToken sz (BigNIntNeedBody len) -> return $! SlowConsumeTokenBytes (BS.unsafeDrop sz bs) (adjustContBigNIntNeedBody k) len
DecodedToken sz BigUIntNeedHeader -> return $! SlowDecodeAction (BS.unsafeDrop sz bs) (adjustContBigUIntNeedHeader k)
DecodedToken sz BigNIntNeedHeader -> return $! SlowDecodeAction (BS.unsafeDrop sz bs) (adjustContBigNIntNeedHeader k)
go_fast_end !bs (ConsumeFloat k) =
case tryConsumeFloat (BS.unsafeHead bs) bs of
DecodeFailure -> return $! SlowFail bs "expected float"
DecodedToken sz (F# f#) -> k f# >>= go_fast_end (BS.unsafeDrop sz bs)
go_fast_end !bs (ConsumeDouble k) =
case tryConsumeDouble (BS.unsafeHead bs) bs of
DecodeFailure -> return $! SlowFail bs "expected double"
DecodedToken sz (D# f#) -> k f# >>= go_fast_end (BS.unsafeDrop sz bs)
go_fast_end !bs (ConsumeBytes k) =
case tryConsumeBytes (BS.unsafeHead bs) bs of
DecodeFailure -> return $! SlowFail bs "expected bytes"
DecodedToken sz (Fits bstr) -> k bstr >>= go_fast_end (BS.unsafeDrop sz bs)
DecodedToken sz (TooLong len) -> return $! SlowConsumeTokenBytes (BS.unsafeDrop sz bs) k len
go_fast_end !bs (ConsumeByteArray k) =
case tryConsumeBytes (BS.unsafeHead bs) bs of
DecodeFailure -> return $! SlowFail bs "expected string"
DecodedToken sz (Fits str) -> (k $! BA.fromByteString str) >>= go_fast_end (BS.unsafeDrop sz bs)
DecodedToken sz (TooLong len) -> return $! SlowConsumeTokenByteArray (BS.unsafeDrop sz bs) k len
go_fast_end !bs (ConsumeString k) =
case tryConsumeString (BS.unsafeHead bs) bs of
DecodeFailure -> return $! SlowFail bs "expected string"
DecodedToken sz (Fits str) -> case T.decodeUtf8' str of
Right t -> k t >>= go_fast_end (BS.unsafeDrop sz bs)
Left e -> return $! SlowFail bs (show e)
DecodedToken sz (TooLong len) -> return $! SlowConsumeTokenString (BS.unsafeDrop sz bs) k len
go_fast_end !bs (ConsumeUtf8ByteArray k) =
case tryConsumeString (BS.unsafeHead bs) bs of
DecodeFailure -> return $! SlowFail bs "expected string"
DecodedToken sz (Fits str) -> (k $! BA.fromByteString str) >>= go_fast_end (BS.unsafeDrop sz bs)
DecodedToken sz (TooLong len) -> return $! SlowConsumeTokenUtf8ByteArray (BS.unsafeDrop sz bs) k len
go_fast_end !bs (ConsumeBool k) =
case tryConsumeBool (BS.unsafeHead bs) of
DecodeFailure -> return $! SlowFail bs "expected bool"
DecodedToken sz b -> k b >>= go_fast_end (BS.unsafeDrop sz bs)
go_fast_end !bs (ConsumeSimple k) =
case tryConsumeSimple (BS.unsafeHead bs) bs of
DecodeFailure -> return $! SlowFail bs "expected simple"
DecodedToken sz (W# w#) -> k w# >>= go_fast_end (BS.unsafeDrop sz bs)
go_fast_end !bs (ConsumeIntegerCanonical k) =
case tryConsumeInteger (BS.unsafeHead bs) bs of
DecodeFailure -> return $! SlowFail bs "expected integer"
DecodedToken sz (BigIntToken canonical n)
| canonical -> k n >>= go_fast_end (BS.unsafeDrop sz bs)
| otherwise -> return $! SlowFail bs "non-canonical integer"
DecodedToken sz (BigUIntNeedBody len) -> return $! SlowConsumeTokenBytes (BS.unsafeDrop sz bs) (adjustContBigUIntNeedBody k) len
DecodedToken sz (BigNIntNeedBody len) -> return $! SlowConsumeTokenBytes (BS.unsafeDrop sz bs) (adjustContBigNIntNeedBody k) len
DecodedToken sz BigUIntNeedHeader -> return $! SlowDecodeAction (BS.unsafeDrop sz bs) (adjustContBigUIntNeedHeader k)
DecodedToken sz BigNIntNeedHeader -> return $! SlowDecodeAction (BS.unsafeDrop sz bs) (adjustContBigNIntNeedHeader k)
go_fast_end !bs (ConsumeFloat16Canonical k) =
case tryConsumeFloat (BS.unsafeHead bs) bs of
DecodeFailure -> return $! SlowFail bs "expected float"
DecodedToken sz (F# f#)
| isFloat16Canonical sz -> k f# >>= go_fast_end (BS.unsafeDrop sz bs)
| otherwise -> return $! SlowFail bs "non-canonical float16"
go_fast_end !bs (ConsumeFloatCanonical k) =
case tryConsumeFloat (BS.unsafeHead bs) bs of
DecodeFailure -> return $! SlowFail bs "expected float"
DecodedToken sz f@(F# f#)
| isFloatCanonical sz bs f -> k f# >>= go_fast_end (BS.unsafeDrop sz bs)
| otherwise -> return $! SlowFail bs "non-canonical float"
go_fast_end !bs (ConsumeDoubleCanonical k) =
case tryConsumeDouble (BS.unsafeHead bs) bs of
DecodeFailure -> return $! SlowFail bs "expected double"
DecodedToken sz f@(D# f#)
| isDoubleCanonical sz bs f -> k f# >>= go_fast_end (BS.unsafeDrop sz bs)
| otherwise -> return $! SlowFail bs "non-canonical double"
go_fast_end !bs (ConsumeSimpleCanonical k) =
case tryConsumeSimple (BS.unsafeHead bs) bs of
DecodeFailure -> return $! SlowFail bs "expected simple"
DecodedToken sz (W# w#)
| isWordCanonical sz w# -> k w# >>= go_fast_end (BS.unsafeDrop sz bs)
| otherwise -> return $! SlowFail bs "non-canonical simple"
go_fast_end !bs (ConsumeBytesIndef k) =
case tryConsumeBytesIndef (BS.unsafeHead bs) of
DecodeFailure -> return $! SlowFail bs "expected bytes start"
DecodedToken sz _ -> k >>= go_fast_end (BS.unsafeDrop sz bs)
go_fast_end !bs (ConsumeStringIndef k) =
case tryConsumeStringIndef (BS.unsafeHead bs) of
DecodeFailure -> return $! SlowFail bs "expected string start"
DecodedToken sz _ -> k >>= go_fast_end (BS.unsafeDrop sz bs)
go_fast_end !bs (ConsumeListLenIndef k) =
case tryConsumeListLenIndef (BS.unsafeHead bs) of
DecodeFailure -> return $! SlowFail bs "expected list start"
DecodedToken sz _ -> k >>= go_fast_end (BS.unsafeDrop sz bs)
go_fast_end !bs (ConsumeMapLenIndef k) =
case tryConsumeMapLenIndef (BS.unsafeHead bs) of
DecodeFailure -> return $! SlowFail bs "expected map start"
DecodedToken sz _ -> k >>= go_fast_end (BS.unsafeDrop sz bs)
go_fast_end !bs (ConsumeNull k) =
case tryConsumeNull (BS.unsafeHead bs) of
DecodeFailure -> return $! SlowFail bs "expected null"
DecodedToken sz _ -> k >>= go_fast_end (BS.unsafeDrop sz bs)
go_fast_end !bs (ConsumeListLenOrIndef k) =
case tryConsumeListLenOrIndef (BS.unsafeHead bs) bs of
DecodeFailure -> return $! SlowFail bs "expected list len or indef"
DecodedToken sz (I# n#) -> k n# >>= go_fast_end (BS.unsafeDrop sz bs)
go_fast_end !bs (ConsumeMapLenOrIndef k) =
case tryConsumeMapLenOrIndef (BS.unsafeHead bs) bs of
DecodeFailure -> return $! SlowFail bs "expected map len or indef"
DecodedToken sz (I# n#) -> k n# >>= go_fast_end (BS.unsafeDrop sz bs)
go_slow :: DecodeAction s a -> ByteString -> ByteOffset
-> IncrementalDecoder s (ByteString, ByteOffset, a)
go_slow da bs !offset = do
slowpath <- lift $ go_fast bs da
case slowpath of
FastDone bs' x -> return (bs', offset', x)
where
!offset' = offset + fromIntegral (BS.length bs BS.length bs')
SlowConsumeTokenBytes bs' k len -> do
(bstr, bs'') <- getTokenVarLen len bs' offset'
lift (k bstr) >>= \daz -> go_slow daz bs'' (offset' + fromIntegral len)
where
!offset' = offset + fromIntegral (BS.length bs BS.length bs')
SlowConsumeTokenByteArray bs' k len -> do
(bstr, bs'') <- getTokenVarLen len bs' offset'
let !str = BA.fromByteString bstr
lift (k str) >>= \daz -> go_slow daz bs'' (offset' + fromIntegral len)
where
!offset' = offset + fromIntegral (BS.length bs BS.length bs')
SlowConsumeTokenString bs' k len -> do
(bstr, bs'') <- getTokenVarLen len bs' offset'
let !str = T.decodeUtf8 bstr
lift (k str) >>= \daz -> go_slow daz bs'' (offset' + fromIntegral len)
where
!offset' = offset + fromIntegral (BS.length bs BS.length bs')
SlowConsumeTokenUtf8ByteArray bs' k len -> do
(bstr, bs'') <- getTokenVarLen len bs' offset'
let !str = BA.fromByteString bstr
lift (k str) >>= \daz -> go_slow daz bs'' (offset' + fromIntegral len)
where
!offset' = offset + fromIntegral (BS.length bs BS.length bs')
SlowDecodeAction bs' da' | BS.null bs' -> do
mbs <- needChunk
case mbs of
Nothing -> decodeFail bs' offset' "end of input"
Just bs'' -> go_slow da' bs'' offset'
where
!offset' = offset + fromIntegral (BS.length bs BS.length bs')
SlowDecodeAction bs' da' ->
assert (BS.length bs' < tokenSize (BS.head bs')) $
go_slow_fixup da' bs' offset'
where
!offset' = offset + fromIntegral (BS.length bs BS.length bs')
SlowFail bs' msg -> decodeFail bs' offset' msg
where
!offset' = offset + fromIntegral (BS.length bs BS.length bs')
go_slow_fixup :: DecodeAction s a -> ByteString -> ByteOffset
-> IncrementalDecoder s (ByteString, ByteOffset, a)
go_slow_fixup da !bs !offset = do
let !hdr = BS.head bs
!sz = tokenSize hdr
mbs <- needChunk
case mbs of
Nothing -> decodeFail bs offset "end of input"
Just bs'
| BS.length bs + BS.length bs' >= sz
-> go_slow_overlapped da sz bs bs' offset
| otherwise
-> go_slow_fixup da (bs <> bs') offset
go_slow_overlapped :: DecodeAction s a -> Int -> ByteString -> ByteString
-> ByteOffset
-> IncrementalDecoder s (ByteString, ByteOffset, a)
go_slow_overlapped da sz bs_cur bs_next !offset =
assert (BS.length bs_cur < sz) $
assert (BS.length bs_cur + BS.length bs_next >= sz) $
let bs_tok = bs_cur <> BS.unsafeTake (sz BS.length bs_cur) bs_next
bs' = BS.unsafeDrop (sz BS.length bs_cur) bs_next
offset' = offset + fromIntegral sz in
assert (BS.length bs_tok == sz) $
assert (BS.length bs_cur + BS.length bs_next == sz + BS.length bs') $ do
slowpath <- lift $ go_fast_end bs_tok da
case slowpath of
SlowDecodeAction bs_empty da' ->
assert (BS.null bs_empty) $
go_slow da' bs' offset'
FastDone bs_empty x ->
assert (BS.null bs_empty) $
return (bs', offset', x)
SlowConsumeTokenBytes bs_empty k len -> consume id bs' offset' bs_empty k len
SlowConsumeTokenByteArray bs_empty k len -> consume BA.fromByteString bs' offset' bs_empty k len
SlowConsumeTokenString bs_empty k len -> consume T.decodeUtf8 bs' offset' bs_empty k len
SlowConsumeTokenUtf8ByteArray bs_empty k len -> consume BA.fromByteString bs' offset' bs_empty k len
SlowFail bs_unconsumed msg ->
decodeFail (bs_unconsumed <> bs') offset'' msg
where
!offset'' = offset + fromIntegral (sz BS.length bs_unconsumed)
where
consume :: (BS.ByteString -> a)
-> BS.ByteString
-> Int64
-> BS.ByteString
-> (a -> ST s (DecodeAction s r))
-> Int
-> IncrementalDecoder s (ByteString, ByteOffset, r)
consume pack bs' offset' bs_empty k len =
assert (BS.null bs_empty) $ do
(bstr, bs'') <- if BS.length bs' < len
then getTokenVarLen len bs' offset'
else let !bstr = BS.take len bs'
!bs'' = BS.drop len bs'
in return (bstr, bs'')
let !str = pack bstr
lift (k str) >>= \daz -> go_slow daz bs'' (offset' + fromIntegral len)
getTokenVarLen :: Int -> ByteString -> ByteOffset
-> IncrementalDecoder s (ByteString, ByteString)
getTokenVarLen len bs offset =
assert (len > BS.length bs) $ do
mbs <- needChunk
case mbs of
Nothing -> decodeFail BS.empty offset "end of input"
Just bs'
| let n = len BS.length bs
, BS.length bs' >= n ->
let !tok = bs <> BS.unsafeTake n bs'
in return (tok, BS.drop n bs')
| otherwise -> getTokenVarLenSlow
[bs',bs]
(len (BS.length bs + BS.length bs'))
offset
getTokenVarLenSlow :: [ByteString] -> Int -> ByteOffset
-> IncrementalDecoder s (ByteString, ByteString)
getTokenVarLenSlow bss n offset = do
mbs <- needChunk
case mbs of
Nothing -> decodeFail BS.empty offset "end of input"
Just bs
| BS.length bs >= n ->
let !tok = BS.concat (reverse (BS.unsafeTake n bs : bss))
in return (tok, BS.drop n bs)
| otherwise -> getTokenVarLenSlow (bs:bss) (n BS.length bs) offset
tokenSize :: Word8 -> Int
tokenSize hdr =
fromIntegral $
decodeTableSz `A.unsafeAt` (fromIntegral hdr .&. 0x1f)
decodeTableSz :: UArray Word8 Word8
decodeTableSz =
array (0, 0x1f) $
[ (encodeHeader 0 n, 1) | n <- [0..0x1f] ]
++ [ (encodeHeader 0 n, s) | (n, s) <- zip [24..27] [2,3,5,9] ]
decodeTokenTypeTable :: Array Word8 TokenType
decodeTokenTypeTable =
array (minBound, maxBound) $
[ (encodeHeader 0 n, TypeUInt) | n <- [0..26] ]
++ [ (encodeHeader 0 27, TypeUInt64)
, (encodeHeader 0 31, TypeInvalid) ]
++ [ (encodeHeader 1 n, TypeNInt) | n <- [0..26] ]
++ [ (encodeHeader 1 27, TypeNInt64)
, (encodeHeader 1 31, TypeInvalid) ]
++ [ (encodeHeader 2 n, TypeBytes) | n <- [0..27] ]
++ [ (encodeHeader 2 31, TypeBytesIndef) ]
++ [ (encodeHeader 3 n, TypeString) | n <- [0..27] ]
++ [ (encodeHeader 3 31, TypeStringIndef) ]
++ [ (encodeHeader 4 n, TypeListLen) | n <- [0..26] ]
++ [ (encodeHeader 4 27, TypeListLen64)
, (encodeHeader 4 31, TypeListLenIndef) ]
++ [ (encodeHeader 5 n, TypeMapLen) | n <- [0..26] ]
++ [ (encodeHeader 5 27, TypeMapLen64)
, (encodeHeader 5 31, TypeMapLenIndef) ]
++ [ (encodeHeader 6 n, TypeTag) | n <- 0:1:[4..26] ]
++ [ (encodeHeader 6 2, TypeInteger)
, (encodeHeader 6 3, TypeInteger)
, (encodeHeader 6 27, TypeTag64)
, (encodeHeader 6 31, TypeInvalid) ]
++ [ (encodeHeader 7 n, TypeSimple) | n <- [0..19] ]
++ [ (encodeHeader 7 20, TypeBool)
, (encodeHeader 7 21, TypeBool)
, (encodeHeader 7 22, TypeNull)
, (encodeHeader 7 23, TypeSimple)
, (encodeHeader 7 24, TypeSimple)
, (encodeHeader 7 25, TypeFloat16)
, (encodeHeader 7 26, TypeFloat32)
, (encodeHeader 7 27, TypeFloat64)
, (encodeHeader 7 31, TypeBreak) ]
++ [ (encodeHeader mt n, TypeInvalid) | mt <- [0..7], n <- [28..30] ]
encodeHeader :: Word -> Word -> Word8
encodeHeader mt ai = fromIntegral (mt `shiftL` 5 .|. ai)
data DecodedToken a = DecodedToken !Int !a | DecodeFailure
deriving Show
data LongToken a = Fits !a | TooLong !Int
deriving Show
isFloat16Canonical :: Int -> Bool
isFloat16Canonical sz
| sz == 3 = True
| otherwise = False
isFloatCanonical :: Int -> BS.ByteString -> Float -> Bool
isFloatCanonical sz bs f
| isNaN f = sz == 3 && "\xf9\x7e\x00" `BS.isPrefixOf` bs
| otherwise = sz == 5
isDoubleCanonical :: Int -> BS.ByteString -> Double -> Bool
isDoubleCanonical sz bs f
| isNaN f = sz == 3 && "\xf9\x7e\x00" `BS.isPrefixOf` bs
| otherwise = sz == 9
isWordCanonical :: Int -> Word# -> Bool
isWordCanonical sz w#
| sz == 2 && isTrue# (w# `leWord#` 0x17##) = False
| sz == 3 && isTrue# (w# `leWord#` 0xff##) = False
| sz == 5 && isTrue# (w# `leWord#` 0xffff##) = False
| sz == 9 && isTrue# (w# `leWord#` 0xffffffff##) = False
| otherwise = True
isIntCanonical :: Int -> Int# -> Bool
isIntCanonical sz i#
| isTrue# (i# <# 0#) = isWordCanonical sz (not# w#)
| otherwise = isWordCanonical sz w#
where
w# = int2Word# i#
#if defined(ARCH_32bit)
isWord64Canonical :: Int -> Word64# -> Bool
isWord64Canonical sz w#
| sz == 2 && isTrue# (w# `leWord64#` 0x17##) = False
| sz == 3 && isTrue# (w# `leWord64#` 0xff##) = False
| sz == 5 && isTrue# (w# `leWord64#` 0xffff##) = False
| sz == 9 && isTrue# (w# `leWord64#` 0xffffffff##) = False
| otherwise = True
isInt64Canonical :: Int -> Int64# -> Bool
isInt64Canonical sz i#
| isTrue# (i# <# 0#) = isWord64Canonical sz (not64# w#)
| otherwise = isWord64Canonical sz w#
where
w# = int64ToWord64# i#
#endif
tryConsumeWord :: Word8 -> ByteString -> DecodedToken Word
tryConsumeWord hdr !bs = case fromIntegral hdr :: Word of
0x00 -> DecodedToken 1 0
0x01 -> DecodedToken 1 1
0x02 -> DecodedToken 1 2
0x03 -> DecodedToken 1 3
0x04 -> DecodedToken 1 4
0x05 -> DecodedToken 1 5
0x06 -> DecodedToken 1 6
0x07 -> DecodedToken 1 7
0x08 -> DecodedToken 1 8
0x09 -> DecodedToken 1 9
0x0a -> DecodedToken 1 10
0x0b -> DecodedToken 1 11
0x0c -> DecodedToken 1 12
0x0d -> DecodedToken 1 13
0x0e -> DecodedToken 1 14
0x0f -> DecodedToken 1 15
0x10 -> DecodedToken 1 16
0x11 -> DecodedToken 1 17
0x12 -> DecodedToken 1 18
0x13 -> DecodedToken 1 19
0x14 -> DecodedToken 1 20
0x15 -> DecodedToken 1 21
0x16 -> DecodedToken 1 22
0x17 -> DecodedToken 1 23
0x18 -> DecodedToken 2 (eatTailWord8 bs)
0x19 -> DecodedToken 3 (eatTailWord16 bs)
0x1a -> DecodedToken 5 (eatTailWord32 bs)
0x1b -> DecodedToken 9 (fromIntegral $ eatTailWord64 bs)
_ -> DecodeFailure
tryConsumeNegWord :: Word8 -> ByteString -> DecodedToken Word
tryConsumeNegWord hdr !bs = case fromIntegral hdr :: Word of
0x20 -> DecodedToken 1 0
0x21 -> DecodedToken 1 1
0x22 -> DecodedToken 1 2
0x23 -> DecodedToken 1 3
0x24 -> DecodedToken 1 4
0x25 -> DecodedToken 1 5
0x26 -> DecodedToken 1 6
0x27 -> DecodedToken 1 7
0x28 -> DecodedToken 1 8
0x29 -> DecodedToken 1 9
0x2a -> DecodedToken 1 10
0x2b -> DecodedToken 1 11
0x2c -> DecodedToken 1 12
0x2d -> DecodedToken 1 13
0x2e -> DecodedToken 1 14
0x2f -> DecodedToken 1 15
0x30 -> DecodedToken 1 16
0x31 -> DecodedToken 1 17
0x32 -> DecodedToken 1 18
0x33 -> DecodedToken 1 19
0x34 -> DecodedToken 1 20
0x35 -> DecodedToken 1 21
0x36 -> DecodedToken 1 22
0x37 -> DecodedToken 1 23
0x38 -> DecodedToken 2 (eatTailWord8 bs)
0x39 -> DecodedToken 3 (eatTailWord16 bs)
0x3a -> DecodedToken 5 (eatTailWord32 bs)
0x3b -> DecodedToken 9 (fromIntegral $ eatTailWord64 bs)
_ -> DecodeFailure
tryConsumeInt :: Word8 -> ByteString -> DecodedToken Int
tryConsumeInt hdr !bs = case fromIntegral hdr :: Word of
0x00 -> DecodedToken 1 0
0x01 -> DecodedToken 1 1
0x02 -> DecodedToken 1 2
0x03 -> DecodedToken 1 3
0x04 -> DecodedToken 1 4
0x05 -> DecodedToken 1 5
0x06 -> DecodedToken 1 6
0x07 -> DecodedToken 1 7
0x08 -> DecodedToken 1 8
0x09 -> DecodedToken 1 9
0x0a -> DecodedToken 1 10
0x0b -> DecodedToken 1 11
0x0c -> DecodedToken 1 12
0x0d -> DecodedToken 1 13
0x0e -> DecodedToken 1 14
0x0f -> DecodedToken 1 15
0x10 -> DecodedToken 1 16
0x11 -> DecodedToken 1 17
0x12 -> DecodedToken 1 18
0x13 -> DecodedToken 1 19
0x14 -> DecodedToken 1 20
0x15 -> DecodedToken 1 21
0x16 -> DecodedToken 1 22
0x17 -> DecodedToken 1 23
0x18 -> DecodedToken 2 (fromIntegral (eatTailWord8 bs))
0x19 -> DecodedToken 3 (fromIntegral (eatTailWord16 bs))
0x1a -> DecodedToken 5 (fromIntegral (eatTailWord32 bs))
0x1b -> DecodedToken 9 (fromIntegral (eatTailWord64 bs))
0x20 -> DecodedToken 1 (1)
0x21 -> DecodedToken 1 (2)
0x22 -> DecodedToken 1 (3)
0x23 -> DecodedToken 1 (4)
0x24 -> DecodedToken 1 (5)
0x25 -> DecodedToken 1 (6)
0x26 -> DecodedToken 1 (7)
0x27 -> DecodedToken 1 (8)
0x28 -> DecodedToken 1 (9)
0x29 -> DecodedToken 1 (10)
0x2a -> DecodedToken 1 (11)
0x2b -> DecodedToken 1 (12)
0x2c -> DecodedToken 1 (13)
0x2d -> DecodedToken 1 (14)
0x2e -> DecodedToken 1 (15)
0x2f -> DecodedToken 1 (16)
0x30 -> DecodedToken 1 (17)
0x31 -> DecodedToken 1 (18)
0x32 -> DecodedToken 1 (19)
0x33 -> DecodedToken 1 (20)
0x34 -> DecodedToken 1 (21)
0x35 -> DecodedToken 1 (22)
0x36 -> DecodedToken 1 (23)
0x37 -> DecodedToken 1 (24)
0x38 -> DecodedToken 2 (1 fromIntegral (eatTailWord8 bs))
0x39 -> DecodedToken 3 (1 fromIntegral (eatTailWord16 bs))
0x3a -> DecodedToken 5 (1 fromIntegral (eatTailWord32 bs))
0x3b -> DecodedToken 9 (1 fromIntegral (eatTailWord64 bs))
_ -> DecodeFailure
tryConsumeInteger :: Word8 -> ByteString -> DecodedToken (BigIntToken Integer)
tryConsumeInteger hdr !bs = case fromIntegral hdr :: Word of
0x00 -> DecodedToken 1 (BigIntToken True 0)
0x01 -> DecodedToken 1 (BigIntToken True 1)
0x02 -> DecodedToken 1 (BigIntToken True 2)
0x03 -> DecodedToken 1 (BigIntToken True 3)
0x04 -> DecodedToken 1 (BigIntToken True 4)
0x05 -> DecodedToken 1 (BigIntToken True 5)
0x06 -> DecodedToken 1 (BigIntToken True 6)
0x07 -> DecodedToken 1 (BigIntToken True 7)
0x08 -> DecodedToken 1 (BigIntToken True 8)
0x09 -> DecodedToken 1 (BigIntToken True 9)
0x0a -> DecodedToken 1 (BigIntToken True 10)
0x0b -> DecodedToken 1 (BigIntToken True 11)
0x0c -> DecodedToken 1 (BigIntToken True 12)
0x0d -> DecodedToken 1 (BigIntToken True 13)
0x0e -> DecodedToken 1 (BigIntToken True 14)
0x0f -> DecodedToken 1 (BigIntToken True 15)
0x10 -> DecodedToken 1 (BigIntToken True 16)
0x11 -> DecodedToken 1 (BigIntToken True 17)
0x12 -> DecodedToken 1 (BigIntToken True 18)
0x13 -> DecodedToken 1 (BigIntToken True 19)
0x14 -> DecodedToken 1 (BigIntToken True 20)
0x15 -> DecodedToken 1 (BigIntToken True 21)
0x16 -> DecodedToken 1 (BigIntToken True 22)
0x17 -> DecodedToken 1 (BigIntToken True 23)
0x18 -> let !w@(W# w#) = eatTailWord8 bs
sz = 2
in DecodedToken sz (BigIntToken (isWordCanonical sz w#) (fromIntegral w))
0x19 -> let !w@(W# w#) = eatTailWord16 bs
sz = 3
in DecodedToken sz (BigIntToken (isWordCanonical sz w#) (fromIntegral w))
0x1a -> let !w@(W# w#) = eatTailWord32 bs
sz = 5
in DecodedToken sz (BigIntToken (isWordCanonical sz w#) (fromIntegral w))
0x1b -> let !w@(W64# w#) = eatTailWord64 bs
sz = 9
#if defined(ARCH_32bit)
in DecodedToken sz (BigIntToken (isWord64Canonical sz w#) (fromIntegral w))
#else
in DecodedToken sz (BigIntToken (isWordCanonical sz w#) (fromIntegral w))
#endif
0x20 -> DecodedToken 1 (BigIntToken True (1))
0x21 -> DecodedToken 1 (BigIntToken True (2))
0x22 -> DecodedToken 1 (BigIntToken True (3))
0x23 -> DecodedToken 1 (BigIntToken True (4))
0x24 -> DecodedToken 1 (BigIntToken True (5))
0x25 -> DecodedToken 1 (BigIntToken True (6))
0x26 -> DecodedToken 1 (BigIntToken True (7))
0x27 -> DecodedToken 1 (BigIntToken True (8))
0x28 -> DecodedToken 1 (BigIntToken True (9))
0x29 -> DecodedToken 1 (BigIntToken True (10))
0x2a -> DecodedToken 1 (BigIntToken True (11))
0x2b -> DecodedToken 1 (BigIntToken True (12))
0x2c -> DecodedToken 1 (BigIntToken True (13))
0x2d -> DecodedToken 1 (BigIntToken True (14))
0x2e -> DecodedToken 1 (BigIntToken True (15))
0x2f -> DecodedToken 1 (BigIntToken True (16))
0x30 -> DecodedToken 1 (BigIntToken True (17))
0x31 -> DecodedToken 1 (BigIntToken True (18))
0x32 -> DecodedToken 1 (BigIntToken True (19))
0x33 -> DecodedToken 1 (BigIntToken True (20))
0x34 -> DecodedToken 1 (BigIntToken True (21))
0x35 -> DecodedToken 1 (BigIntToken True (22))
0x36 -> DecodedToken 1 (BigIntToken True (23))
0x37 -> DecodedToken 1 (BigIntToken True (24))
0x38 -> let !w@(W# w#) = eatTailWord8 bs
sz = 2
in DecodedToken sz (BigIntToken (isWordCanonical sz w#) (1 fromIntegral w))
0x39 -> let !w@(W# w#) = eatTailWord16 bs
sz = 3
in DecodedToken sz (BigIntToken (isWordCanonical sz w#) (1 fromIntegral w))
0x3a -> let !w@(W# w#) = eatTailWord32 bs
sz = 5
in DecodedToken sz (BigIntToken (isWordCanonical sz w#) (1 fromIntegral w))
0x3b -> let !w@(W64# w#) = eatTailWord64 bs
sz = 9
#if defined(ARCH_32bit)
in DecodedToken sz (BigIntToken (isWord64Canonical sz w#) (1 fromIntegral w))
#else
in DecodedToken sz (BigIntToken (isWordCanonical sz w#) (1 fromIntegral w))
#endif
0xc2 -> readBigUInt bs
0xc3 -> readBigNInt bs
_ -> DecodeFailure
tryConsumeBytes :: Word8 -> ByteString -> DecodedToken (LongToken ByteString)
tryConsumeBytes hdr !bs = case fromIntegral hdr :: Word of
0x40 -> readBytesSmall 0 bs
0x41 -> readBytesSmall 1 bs
0x42 -> readBytesSmall 2 bs
0x43 -> readBytesSmall 3 bs
0x44 -> readBytesSmall 4 bs
0x45 -> readBytesSmall 5 bs
0x46 -> readBytesSmall 6 bs
0x47 -> readBytesSmall 7 bs
0x48 -> readBytesSmall 8 bs
0x49 -> readBytesSmall 9 bs
0x4a -> readBytesSmall 10 bs
0x4b -> readBytesSmall 11 bs
0x4c -> readBytesSmall 12 bs
0x4d -> readBytesSmall 13 bs
0x4e -> readBytesSmall 14 bs
0x4f -> readBytesSmall 15 bs
0x50 -> readBytesSmall 16 bs
0x51 -> readBytesSmall 17 bs
0x52 -> readBytesSmall 18 bs
0x53 -> readBytesSmall 19 bs
0x54 -> readBytesSmall 20 bs
0x55 -> readBytesSmall 21 bs
0x56 -> readBytesSmall 22 bs
0x57 -> readBytesSmall 23 bs
0x58 -> readBytes8 bs
0x59 -> readBytes16 bs
0x5a -> readBytes32 bs
0x5b -> readBytes64 bs
_ -> DecodeFailure
tryConsumeString :: Word8 -> ByteString -> DecodedToken (LongToken BS.ByteString)
tryConsumeString hdr !bs = case fromIntegral hdr :: Word of
0x60 -> readBytesSmall 0 bs
0x61 -> readBytesSmall 1 bs
0x62 -> readBytesSmall 2 bs
0x63 -> readBytesSmall 3 bs
0x64 -> readBytesSmall 4 bs
0x65 -> readBytesSmall 5 bs
0x66 -> readBytesSmall 6 bs
0x67 -> readBytesSmall 7 bs
0x68 -> readBytesSmall 8 bs
0x69 -> readBytesSmall 9 bs
0x6a -> readBytesSmall 10 bs
0x6b -> readBytesSmall 11 bs
0x6c -> readBytesSmall 12 bs
0x6d -> readBytesSmall 13 bs
0x6e -> readBytesSmall 14 bs
0x6f -> readBytesSmall 15 bs
0x70 -> readBytesSmall 16 bs
0x71 -> readBytesSmall 17 bs
0x72 -> readBytesSmall 18 bs
0x73 -> readBytesSmall 19 bs
0x74 -> readBytesSmall 20 bs
0x75 -> readBytesSmall 21 bs
0x76 -> readBytesSmall 22 bs
0x77 -> readBytesSmall 23 bs
0x78 -> readBytes8 bs
0x79 -> readBytes16 bs
0x7a -> readBytes32 bs
0x7b -> readBytes64 bs
_ -> DecodeFailure
tryConsumeListLen :: Word8 -> ByteString -> DecodedToken Int
tryConsumeListLen hdr !bs = case fromIntegral hdr :: Word of
0x80 -> DecodedToken 1 0
0x81 -> DecodedToken 1 1
0x82 -> DecodedToken 1 2
0x83 -> DecodedToken 1 3
0x84 -> DecodedToken 1 4
0x85 -> DecodedToken 1 5
0x86 -> DecodedToken 1 6
0x87 -> DecodedToken 1 7
0x88 -> DecodedToken 1 8
0x89 -> DecodedToken 1 9
0x8a -> DecodedToken 1 10
0x8b -> DecodedToken 1 11
0x8c -> DecodedToken 1 12
0x8d -> DecodedToken 1 13
0x8e -> DecodedToken 1 14
0x8f -> DecodedToken 1 15
0x90 -> DecodedToken 1 16
0x91 -> DecodedToken 1 17
0x92 -> DecodedToken 1 18
0x93 -> DecodedToken 1 19
0x94 -> DecodedToken 1 20
0x95 -> DecodedToken 1 21
0x96 -> DecodedToken 1 22
0x97 -> DecodedToken 1 23
0x98 -> DecodedToken 2 (fromIntegral (eatTailWord8 bs))
0x99 -> DecodedToken 3 (fromIntegral (eatTailWord16 bs))
0x9a -> DecodedToken 5 (fromIntegral (eatTailWord32 bs))
0x9b -> DecodedToken 9 (fromIntegral (eatTailWord64 bs))
_ -> DecodeFailure
tryConsumeMapLen :: Word8 -> ByteString -> DecodedToken Int
tryConsumeMapLen hdr !bs = case fromIntegral hdr :: Word of
0xa0 -> DecodedToken 1 0
0xa1 -> DecodedToken 1 1
0xa2 -> DecodedToken 1 2
0xa3 -> DecodedToken 1 3
0xa4 -> DecodedToken 1 4
0xa5 -> DecodedToken 1 5
0xa6 -> DecodedToken 1 6
0xa7 -> DecodedToken 1 7
0xa8 -> DecodedToken 1 8
0xa9 -> DecodedToken 1 9
0xaa -> DecodedToken 1 10
0xab -> DecodedToken 1 11
0xac -> DecodedToken 1 12
0xad -> DecodedToken 1 13
0xae -> DecodedToken 1 14
0xaf -> DecodedToken 1 15
0xb0 -> DecodedToken 1 16
0xb1 -> DecodedToken 1 17
0xb2 -> DecodedToken 1 18
0xb3 -> DecodedToken 1 19
0xb4 -> DecodedToken 1 20
0xb5 -> DecodedToken 1 21
0xb6 -> DecodedToken 1 22
0xb7 -> DecodedToken 1 23
0xb8 -> DecodedToken 2 (fromIntegral (eatTailWord8 bs))
0xb9 -> DecodedToken 3 (fromIntegral (eatTailWord16 bs))
0xba -> DecodedToken 5 (fromIntegral (eatTailWord32 bs))
0xbb -> DecodedToken 9 (fromIntegral (eatTailWord64 bs))
_ -> DecodeFailure
tryConsumeListLenIndef :: Word8 -> DecodedToken ()
tryConsumeListLenIndef hdr = case fromIntegral hdr :: Word of
0x9f -> DecodedToken 1 ()
_ -> DecodeFailure
tryConsumeMapLenIndef :: Word8 -> DecodedToken ()
tryConsumeMapLenIndef hdr = case fromIntegral hdr :: Word of
0xbf -> DecodedToken 1 ()
_ -> DecodeFailure
tryConsumeListLenOrIndef :: Word8 -> ByteString -> DecodedToken Int
tryConsumeListLenOrIndef hdr !bs = case fromIntegral hdr :: Word of
0x80 -> DecodedToken 1 0
0x81 -> DecodedToken 1 1
0x82 -> DecodedToken 1 2
0x83 -> DecodedToken 1 3
0x84 -> DecodedToken 1 4
0x85 -> DecodedToken 1 5
0x86 -> DecodedToken 1 6
0x87 -> DecodedToken 1 7
0x88 -> DecodedToken 1 8
0x89 -> DecodedToken 1 9
0x8a -> DecodedToken 1 10
0x8b -> DecodedToken 1 11
0x8c -> DecodedToken 1 12
0x8d -> DecodedToken 1 13
0x8e -> DecodedToken 1 14
0x8f -> DecodedToken 1 15
0x90 -> DecodedToken 1 16
0x91 -> DecodedToken 1 17
0x92 -> DecodedToken 1 18
0x93 -> DecodedToken 1 19
0x94 -> DecodedToken 1 20
0x95 -> DecodedToken 1 21
0x96 -> DecodedToken 1 22
0x97 -> DecodedToken 1 23
0x98 -> DecodedToken 2 (fromIntegral (eatTailWord8 bs))
0x99 -> DecodedToken 3 (fromIntegral (eatTailWord16 bs))
0x9a -> DecodedToken 5 (fromIntegral (eatTailWord32 bs))
0x9b -> DecodedToken 9 (fromIntegral (eatTailWord64 bs))
0x9f -> DecodedToken 1 (1)
_ -> DecodeFailure
tryConsumeMapLenOrIndef :: Word8 -> ByteString -> DecodedToken Int
tryConsumeMapLenOrIndef hdr !bs = case fromIntegral hdr :: Word of
0xa0 -> DecodedToken 1 0
0xa1 -> DecodedToken 1 1
0xa2 -> DecodedToken 1 2
0xa3 -> DecodedToken 1 3
0xa4 -> DecodedToken 1 4
0xa5 -> DecodedToken 1 5
0xa6 -> DecodedToken 1 6
0xa7 -> DecodedToken 1 7
0xa8 -> DecodedToken 1 8
0xa9 -> DecodedToken 1 9
0xaa -> DecodedToken 1 10
0xab -> DecodedToken 1 11
0xac -> DecodedToken 1 12
0xad -> DecodedToken 1 13
0xae -> DecodedToken 1 14
0xaf -> DecodedToken 1 15
0xb0 -> DecodedToken 1 16
0xb1 -> DecodedToken 1 17
0xb2 -> DecodedToken 1 18
0xb3 -> DecodedToken 1 19
0xb4 -> DecodedToken 1 20
0xb5 -> DecodedToken 1 21
0xb6 -> DecodedToken 1 22
0xb7 -> DecodedToken 1 23
0xb8 -> DecodedToken 2 (fromIntegral (eatTailWord8 bs))
0xb9 -> DecodedToken 3 (fromIntegral (eatTailWord16 bs))
0xba -> DecodedToken 5 (fromIntegral (eatTailWord32 bs))
0xbb -> DecodedToken 9 (fromIntegral (eatTailWord64 bs))
0xbf -> DecodedToken 1 (1)
_ -> DecodeFailure
tryConsumeTag :: Word8 -> ByteString -> DecodedToken Word
tryConsumeTag hdr !bs = case fromIntegral hdr :: Word of
0xc0 -> DecodedToken 1 0
0xc1 -> DecodedToken 1 1
0xc2 -> DecodedToken 1 2
0xc3 -> DecodedToken 1 3
0xc4 -> DecodedToken 1 4
0xc5 -> DecodedToken 1 5
0xc6 -> DecodedToken 1 6
0xc7 -> DecodedToken 1 7
0xc8 -> DecodedToken 1 8
0xc9 -> DecodedToken 1 9
0xca -> DecodedToken 1 10
0xcb -> DecodedToken 1 11
0xcc -> DecodedToken 1 12
0xcd -> DecodedToken 1 13
0xce -> DecodedToken 1 14
0xcf -> DecodedToken 1 15
0xd0 -> DecodedToken 1 16
0xd1 -> DecodedToken 1 17
0xd2 -> DecodedToken 1 18
0xd3 -> DecodedToken 1 19
0xd4 -> DecodedToken 1 20
0xd5 -> DecodedToken 1 21
0xd6 -> DecodedToken 1 22
0xd7 -> DecodedToken 1 23
0xd8 -> DecodedToken 2 (eatTailWord8 bs)
0xd9 -> DecodedToken 3 (eatTailWord16 bs)
0xda -> DecodedToken 5 (eatTailWord32 bs)
0xdb -> DecodedToken 9 (fromIntegral (eatTailWord64 bs))
_ -> DecodeFailure
#if defined(ARCH_32bit)
tryConsumeWord64 :: Word8 -> ByteString -> DecodedToken Word64
tryConsumeWord64 hdr !bs = case fromIntegral hdr :: Word of
0x00 -> DecodedToken 1 0
0x01 -> DecodedToken 1 1
0x02 -> DecodedToken 1 2
0x03 -> DecodedToken 1 3
0x04 -> DecodedToken 1 4
0x05 -> DecodedToken 1 5
0x06 -> DecodedToken 1 6
0x07 -> DecodedToken 1 7
0x08 -> DecodedToken 1 8
0x09 -> DecodedToken 1 9
0x0a -> DecodedToken 1 10
0x0b -> DecodedToken 1 11
0x0c -> DecodedToken 1 12
0x0d -> DecodedToken 1 13
0x0e -> DecodedToken 1 14
0x0f -> DecodedToken 1 15
0x10 -> DecodedToken 1 16
0x11 -> DecodedToken 1 17
0x12 -> DecodedToken 1 18
0x13 -> DecodedToken 1 19
0x14 -> DecodedToken 1 20
0x15 -> DecodedToken 1 21
0x16 -> DecodedToken 1 22
0x17 -> DecodedToken 1 23
0x18 -> DecodedToken 2 (fromIntegral (eatTailWord8 bs))
0x19 -> DecodedToken 3 (fromIntegral (eatTailWord16 bs))
0x1a -> DecodedToken 5 (fromIntegral (eatTailWord32 bs))
0x1b -> DecodedToken 9 (fromIntegral (eatTailWord64 bs))
_ -> DecodeFailure
tryConsumeNegWord64 :: Word8 -> ByteString -> DecodedToken Word64
tryConsumeNegWord64 hdr !bs = case fromIntegral hdr :: Word of
0x20 -> DecodedToken 1 0
0x21 -> DecodedToken 1 1
0x22 -> DecodedToken 1 2
0x23 -> DecodedToken 1 3
0x24 -> DecodedToken 1 4
0x25 -> DecodedToken 1 5
0x26 -> DecodedToken 1 6
0x27 -> DecodedToken 1 7
0x28 -> DecodedToken 1 8
0x29 -> DecodedToken 1 9
0x2a -> DecodedToken 1 10
0x2b -> DecodedToken 1 11
0x2c -> DecodedToken 1 12
0x2d -> DecodedToken 1 13
0x2e -> DecodedToken 1 14
0x2f -> DecodedToken 1 15
0x30 -> DecodedToken 1 16
0x31 -> DecodedToken 1 17
0x32 -> DecodedToken 1 18
0x33 -> DecodedToken 1 19
0x34 -> DecodedToken 1 20
0x35 -> DecodedToken 1 21
0x36 -> DecodedToken 1 22
0x37 -> DecodedToken 1 23
0x38 -> DecodedToken 2 (fromIntegral (eatTailWord8 bs))
0x39 -> DecodedToken 3 (fromIntegral (eatTailWord16 bs))
0x3a -> DecodedToken 5 (fromIntegral (eatTailWord32 bs))
0x3b -> DecodedToken 9 (fromIntegral (eatTailWord64 bs))
_ -> DecodeFailure
tryConsumeInt64 :: Word8 -> ByteString -> DecodedToken Int64
tryConsumeInt64 hdr !bs = case fromIntegral hdr :: Word of
0x00 -> DecodedToken 1 0
0x01 -> DecodedToken 1 1
0x02 -> DecodedToken 1 2
0x03 -> DecodedToken 1 3
0x04 -> DecodedToken 1 4
0x05 -> DecodedToken 1 5
0x06 -> DecodedToken 1 6
0x07 -> DecodedToken 1 7
0x08 -> DecodedToken 1 8
0x09 -> DecodedToken 1 9
0x0a -> DecodedToken 1 10
0x0b -> DecodedToken 1 11
0x0c -> DecodedToken 1 12
0x0d -> DecodedToken 1 13
0x0e -> DecodedToken 1 14
0x0f -> DecodedToken 1 15
0x10 -> DecodedToken 1 16
0x11 -> DecodedToken 1 17
0x12 -> DecodedToken 1 18
0x13 -> DecodedToken 1 19
0x14 -> DecodedToken 1 20
0x15 -> DecodedToken 1 21
0x16 -> DecodedToken 1 22
0x17 -> DecodedToken 1 23
0x18 -> DecodedToken 2 (fromIntegral (eatTailWord8 bs))
0x19 -> DecodedToken 3 (fromIntegral (eatTailWord16 bs))
0x1a -> DecodedToken 5 (fromIntegral (eatTailWord32 bs))
0x1b -> DecodedToken 9 (fromIntegral (eatTailWord64 bs))
0x20 -> DecodedToken 1 (1)
0x21 -> DecodedToken 1 (2)
0x22 -> DecodedToken 1 (3)
0x23 -> DecodedToken 1 (4)
0x24 -> DecodedToken 1 (5)
0x25 -> DecodedToken 1 (6)
0x26 -> DecodedToken 1 (7)
0x27 -> DecodedToken 1 (8)
0x28 -> DecodedToken 1 (9)
0x29 -> DecodedToken 1 (10)
0x2a -> DecodedToken 1 (11)
0x2b -> DecodedToken 1 (12)
0x2c -> DecodedToken 1 (13)
0x2d -> DecodedToken 1 (14)
0x2e -> DecodedToken 1 (15)
0x2f -> DecodedToken 1 (16)
0x30 -> DecodedToken 1 (17)
0x31 -> DecodedToken 1 (18)
0x32 -> DecodedToken 1 (19)
0x33 -> DecodedToken 1 (20)
0x34 -> DecodedToken 1 (21)
0x35 -> DecodedToken 1 (22)
0x36 -> DecodedToken 1 (23)
0x37 -> DecodedToken 1 (24)
0x38 -> DecodedToken 2 (1 fromIntegral (eatTailWord8 bs))
0x39 -> DecodedToken 3 (1 fromIntegral (eatTailWord16 bs))
0x3a -> DecodedToken 5 (1 fromIntegral (eatTailWord32 bs))
0x3b -> DecodedToken 9 (1 fromIntegral (eatTailWord64 bs))
_ -> DecodeFailure
tryConsumeListLen64 :: Word8 -> ByteString -> DecodedToken Int64
tryConsumeListLen64 hdr !bs = case fromIntegral hdr :: Word of
0x80 -> DecodedToken 1 0
0x81 -> DecodedToken 1 1
0x82 -> DecodedToken 1 2
0x83 -> DecodedToken 1 3
0x84 -> DecodedToken 1 4
0x85 -> DecodedToken 1 5
0x86 -> DecodedToken 1 6
0x87 -> DecodedToken 1 7
0x88 -> DecodedToken 1 8
0x89 -> DecodedToken 1 9
0x8a -> DecodedToken 1 10
0x8b -> DecodedToken 1 11
0x8c -> DecodedToken 1 12
0x8d -> DecodedToken 1 13
0x8e -> DecodedToken 1 14
0x8f -> DecodedToken 1 15
0x90 -> DecodedToken 1 16
0x91 -> DecodedToken 1 17
0x92 -> DecodedToken 1 18
0x93 -> DecodedToken 1 19
0x94 -> DecodedToken 1 20
0x95 -> DecodedToken 1 21
0x96 -> DecodedToken 1 22
0x97 -> DecodedToken 1 23
0x98 -> DecodedToken 2 (fromIntegral (eatTailWord8 bs))
0x99 -> DecodedToken 3 (fromIntegral (eatTailWord16 bs))
0x9a -> DecodedToken 5 (fromIntegral (eatTailWord32 bs))
0x9b -> DecodedToken 9 (fromIntegral (eatTailWord64 bs))
_ -> DecodeFailure
tryConsumeMapLen64 :: Word8 -> ByteString -> DecodedToken Int64
tryConsumeMapLen64 hdr !bs = case fromIntegral hdr :: Word of
0xa0 -> DecodedToken 1 0
0xa1 -> DecodedToken 1 1
0xa2 -> DecodedToken 1 2
0xa3 -> DecodedToken 1 3
0xa4 -> DecodedToken 1 4
0xa5 -> DecodedToken 1 5
0xa6 -> DecodedToken 1 6
0xa7 -> DecodedToken 1 7
0xa8 -> DecodedToken 1 8
0xa9 -> DecodedToken 1 9
0xaa -> DecodedToken 1 10
0xab -> DecodedToken 1 11
0xac -> DecodedToken 1 12
0xad -> DecodedToken 1 13
0xae -> DecodedToken 1 14
0xaf -> DecodedToken 1 15
0xb0 -> DecodedToken 1 16
0xb1 -> DecodedToken 1 17
0xb2 -> DecodedToken 1 18
0xb3 -> DecodedToken 1 19
0xb4 -> DecodedToken 1 20
0xb5 -> DecodedToken 1 21
0xb6 -> DecodedToken 1 22
0xb7 -> DecodedToken 1 23
0xb8 -> DecodedToken 2 (fromIntegral (eatTailWord8 bs))
0xb9 -> DecodedToken 3 (fromIntegral (eatTailWord16 bs))
0xba -> DecodedToken 5 (fromIntegral (eatTailWord32 bs))
0xbb -> DecodedToken 9 (fromIntegral (eatTailWord64 bs))
_ -> DecodeFailure
tryConsumeTag64 :: Word8 -> ByteString -> DecodedToken Word64
tryConsumeTag64 hdr !bs = case fromIntegral hdr :: Word of
0xc0 -> DecodedToken 1 0
0xc1 -> DecodedToken 1 1
0xc2 -> DecodedToken 1 2
0xc3 -> DecodedToken 1 3
0xc4 -> DecodedToken 1 4
0xc5 -> DecodedToken 1 5
0xc6 -> DecodedToken 1 6
0xc7 -> DecodedToken 1 7
0xc8 -> DecodedToken 1 8
0xc9 -> DecodedToken 1 9
0xca -> DecodedToken 1 10
0xcb -> DecodedToken 1 11
0xcc -> DecodedToken 1 12
0xcd -> DecodedToken 1 13
0xce -> DecodedToken 1 14
0xcf -> DecodedToken 1 15
0xd0 -> DecodedToken 1 16
0xd1 -> DecodedToken 1 17
0xd2 -> DecodedToken 1 18
0xd3 -> DecodedToken 1 19
0xd4 -> DecodedToken 1 20
0xd5 -> DecodedToken 1 21
0xd6 -> DecodedToken 1 22
0xd7 -> DecodedToken 1 23
0xd8 -> DecodedToken 2 (fromIntegral (eatTailWord8 bs))
0xd9 -> DecodedToken 3 (fromIntegral (eatTailWord16 bs))
0xda -> DecodedToken 5 (fromIntegral (eatTailWord32 bs))
0xdb -> DecodedToken 9 (fromIntegral (eatTailWord64 bs))
_ -> DecodeFailure
#endif
tryConsumeFloat :: Word8 -> ByteString -> DecodedToken Float
tryConsumeFloat hdr !bs = case fromIntegral hdr :: Word of
0xf9 -> DecodedToken 3 (wordToFloat16 (eatTailWord16 bs))
0xfa -> DecodedToken 5 (wordToFloat32 (eatTailWord32 bs))
_ -> DecodeFailure
tryConsumeDouble :: Word8 -> ByteString -> DecodedToken Double
tryConsumeDouble hdr !bs = case fromIntegral hdr :: Word of
0xf9 -> DecodedToken 3 (float2Double $ wordToFloat16 (eatTailWord16 bs))
0xfa -> DecodedToken 5 (float2Double $ wordToFloat32 (eatTailWord32 bs))
0xfb -> DecodedToken 9 (wordToFloat64 (eatTailWord64 bs))
_ -> DecodeFailure
tryConsumeBool :: Word8 -> DecodedToken Bool
tryConsumeBool hdr = case fromIntegral hdr :: Word of
0xf4 -> DecodedToken 1 False
0xf5 -> DecodedToken 1 True
_ -> DecodeFailure
tryConsumeSimple :: Word8 -> ByteString -> DecodedToken Word
tryConsumeSimple hdr !bs = case fromIntegral hdr :: Word of
0xe0 -> DecodedToken 1 0
0xe1 -> DecodedToken 1 1
0xe2 -> DecodedToken 1 2
0xe3 -> DecodedToken 1 3
0xe4 -> DecodedToken 1 4
0xe5 -> DecodedToken 1 5
0xe6 -> DecodedToken 1 6
0xe7 -> DecodedToken 1 7
0xe8 -> DecodedToken 1 8
0xe9 -> DecodedToken 1 9
0xea -> DecodedToken 1 10
0xeb -> DecodedToken 1 11
0xec -> DecodedToken 1 12
0xed -> DecodedToken 1 13
0xee -> DecodedToken 1 14
0xef -> DecodedToken 1 15
0xf0 -> DecodedToken 1 16
0xf1 -> DecodedToken 1 17
0xf2 -> DecodedToken 1 18
0xf3 -> DecodedToken 1 19
0xf4 -> DecodedToken 1 20
0xf5 -> DecodedToken 1 21
0xf6 -> DecodedToken 1 22
0xf7 -> DecodedToken 1 23
0xf8 -> DecodedToken 2 (eatTailWord8 bs)
_ -> DecodeFailure
tryConsumeBytesIndef :: Word8 -> DecodedToken ()
tryConsumeBytesIndef hdr = case fromIntegral hdr :: Word of
0x5f -> DecodedToken 1 ()
_ -> DecodeFailure
tryConsumeStringIndef :: Word8 -> DecodedToken ()
tryConsumeStringIndef hdr = case fromIntegral hdr :: Word of
0x7f -> DecodedToken 1 ()
_ -> DecodeFailure
tryConsumeNull :: Word8 -> DecodedToken ()
tryConsumeNull hdr = case fromIntegral hdr :: Word of
0xf6 -> DecodedToken 1 ()
_ -> DecodeFailure
tryConsumeBreakOr :: Word8 -> DecodedToken ()
tryConsumeBreakOr hdr = case fromIntegral hdr :: Word of
0xff -> DecodedToken 1 ()
_ -> DecodeFailure
readBytesSmall :: Int -> ByteString -> DecodedToken (LongToken ByteString)
readBytesSmall n bs
| n + hdrsz <= BS.length bs
= DecodedToken (n+hdrsz) $ Fits $
BS.unsafeTake n (BS.unsafeDrop hdrsz bs)
| otherwise
= DecodedToken hdrsz $ TooLong n
where
hdrsz = 1
readBytes8, readBytes16, readBytes32, readBytes64
:: ByteString -> DecodedToken (LongToken ByteString)
readBytes8 bs
| n <= BS.length bs hdrsz
= DecodedToken (n+hdrsz) $ Fits $
BS.unsafeTake n (BS.unsafeDrop hdrsz bs)
| otherwise
= DecodedToken hdrsz $ TooLong n
where
hdrsz = 2
n = fromIntegral (eatTailWord8 bs)
readBytes16 bs
| n <= BS.length bs hdrsz
= DecodedToken (n+hdrsz) $ Fits $
BS.unsafeTake n (BS.unsafeDrop hdrsz bs)
| otherwise
= DecodedToken hdrsz $ TooLong n
where
hdrsz = 3
n = fromIntegral (eatTailWord16 bs)
readBytes32 bs
| n <= BS.length bs hdrsz
= DecodedToken (n+hdrsz) $ Fits $
BS.unsafeTake n (BS.unsafeDrop hdrsz bs)
| otherwise
= DecodedToken hdrsz $ TooLong n
where
hdrsz = 5
n = fromIntegral (eatTailWord32 bs)
readBytes64 bs
| n <= BS.length bs hdrsz
= DecodedToken (n+hdrsz) $ Fits $
BS.unsafeTake n (BS.unsafeDrop hdrsz bs)
| otherwise
= DecodedToken hdrsz $ TooLong n
where
hdrsz = 5
n = fromIntegral (eatTailWord64 bs)
data BigIntToken a = BigIntToken Bool Integer
| BigUIntNeedBody Int
| BigNIntNeedBody Int
| BigUIntNeedHeader
| BigNIntNeedHeader
adjustContBigUIntNeedBody, adjustContBigNIntNeedBody
:: (Integer -> ST s (DecodeAction s a))
-> (ByteString -> ST s (DecodeAction s a))
adjustContBigUIntNeedBody k = \bs -> k $! uintegerFromBytes bs
adjustContBigNIntNeedBody k = \bs -> k $! nintegerFromBytes bs
adjustContBigUIntNeedHeader, adjustContBigNIntNeedHeader
:: (Integer -> ST s (DecodeAction s a))
-> DecodeAction s a
adjustContBigUIntNeedHeader k = ConsumeBytes (\bs -> k $! uintegerFromBytes bs)
adjustContBigNIntNeedHeader k = ConsumeBytes (\bs -> k $! nintegerFromBytes bs)
readBigUInt :: ByteString -> DecodedToken (BigIntToken a)
readBigUInt bs
| let bs' = BS.unsafeTail bs
, not (BS.null bs')
, let !hdr = BS.unsafeHead bs'
, BS.length bs' >= tokenSize hdr
= case tryConsumeBytes hdr bs' of
DecodeFailure -> DecodeFailure
DecodedToken sz (Fits bstr) -> DecodedToken (1+sz)
(BigIntToken (isBigIntRepCanonical bstr) (uintegerFromBytes bstr))
DecodedToken sz (TooLong len) -> DecodedToken (1+sz) (BigUIntNeedBody len)
| otherwise
= DecodedToken 1 BigUIntNeedHeader
readBigNInt :: ByteString -> DecodedToken (BigIntToken a)
readBigNInt bs
| let bs' = BS.unsafeTail bs
, not (BS.null bs')
, let !hdr = BS.unsafeHead bs'
, BS.length bs' >= tokenSize hdr
= case tryConsumeBytes hdr bs' of
DecodeFailure -> DecodeFailure
DecodedToken sz (Fits bstr) -> DecodedToken (1+sz)
(BigIntToken (isBigIntRepCanonical bstr) (nintegerFromBytes bstr))
DecodedToken sz (TooLong len) -> DecodedToken (1+sz) (BigNIntNeedBody len)
| otherwise
= DecodedToken 1 BigNIntNeedHeader
isBigIntRepCanonical :: ByteString -> Bool
isBigIntRepCanonical bstr = BS.length bstr > 8 && BS.unsafeHead bstr /= 0x00