{-# LANGUAGE BangPatterns
           , UnboxedTuples #-}

{-# OPTIONS_HADDOCK hide #-}

module Codec.JSON.Decoder.Composite.Internal
  ( isWhitespace
  , endOfInputP

  , nextValueP
  , determineP

  , firstKeyP
  , nextKeyP
  , nextColonP
  , nextPairP

  , firstElementP
  , nextElementP
  ) where

import           Codec.JSON.Decoder.Internal

import           Data.Word
import           Parser.Lathe
import           Parser.Lathe.Binary (word8)
import           Parser.Lathe.Radix



nextValueP :: Path -> Parser (Path, Error) K
nextValueP :: Path -> Parser (Path, Error) K
nextValueP Path
path = do
  _ <- (Word8 -> Bool) -> Parser (Path, Error) ()
forall never. (Word8 -> Bool) -> Parser never ()
skipUntilEndOr (Bool -> Bool
not (Bool -> Bool) -> (Word8 -> Bool) -> Word8 -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word8 -> Bool
isWhitespace)
  determineP path

determineP :: Path -> Parser (Path, Error) K
determineP :: Path -> Parser (Path, Error) K
determineP Path
path =
  ( do w <- Either Error K -> Parser (Either Error K) Word8
forall end. end -> Parser end Word8
word8 (Either Error K -> Parser (Either Error K) Word8)
-> Either Error K -> Parser (Either Error K) Word8
forall a b. (a -> b) -> a -> b
$ Error -> Either Error K
forall a b. a -> Either a b
Left Error
AbruptEnd

       let !(# e #) = case w of
                        Word8
0x22 -> (# K -> Either Error K
forall a b. b -> Either a b
Right K
S #)
                        Word8
0x2D -> (# K -> Either Error K
forall a b. b -> Either a b
Right K
N #)
                        Word8
0x5B -> (# K -> Either Error K
forall a b. b -> Either a b
Right K
A #)
                        Word8
0x66 -> (# K -> Either Error K
forall a b. b -> Either a b
Right K
F #)
                        Word8
0x6E -> (# K -> Either Error K
forall a b. b -> Either a b
Right K
X #)
                        Word8
0x74 -> (# K -> Either Error K
forall a b. b -> Either a b
Right K
T #)
                        Word8
0x7B -> (# K -> Either Error K
forall a b. b -> Either a b
Right K
O #)
                        Word8
_    ->
                          case Word8 -> Maybe Word8
dec Word8
w of
                            Just Word8
_ -> (# K -> Either Error K
forall a b. b -> Either a b
Right K
N #)
                            Maybe Word8
_      ->
                              let str :: String
str = String
"Expected a JSON value"
                              in (# Error -> Either Error K
forall a b. a -> Either a b
Left (Gravity -> String -> Error
Malformed Gravity
Fatal String
str) #)
       err e
   )
    Parser (Either Error K) K
-> (Either Error K -> Parser (Path, Error) K)
-> Parser (Path, Error) K
forall e a x. Parser e a -> (e -> Parser x a) -> Parser x a
`catch` \Either Error K
eiK ->
      case Either Error K
eiK of
        Right K
k -> K -> Parser (Path, Error) K
forall a. a -> Parser (Path, Error) a
forall (f :: * -> *) a. Applicative f => a -> f a
pure K
k
        Left Error
e  -> (Path, Error) -> Parser (Path, Error) K
forall e a. e -> Parser e a
err (Path
path, Error
e)



firstKeyP :: Path -> Parser (Path, Error) Bool
firstKeyP :: Path -> Parser (Path, Error) Bool
firstKeyP Path
path = do
  _ <- (Word8 -> Bool) -> Parser (Path, Error) ()
forall never. (Word8 -> Bool) -> Parser never ()
skipUntilEndOr (Bool -> Bool
not (Bool -> Bool) -> (Word8 -> Bool) -> Word8 -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word8 -> Bool
isWhitespace)
  ( do w <- word8 $ Just AbruptEnd
       case w of
         Word8
0x22 -> Maybe Error -> Parser (Maybe Error) Bool
forall e a. e -> Parser e a
err Maybe Error
forall a. Maybe a
Nothing
         Word8
0x7D -> Bool -> Parser (Maybe Error) Bool
forall a. a -> Parser (Maybe Error) a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
False
         Word8
_    ->
           let str :: String
str = String
"Expected a JSON object pair name or a right curly bracket"
           in Maybe Error -> Parser (Maybe Error) Bool
forall e a. e -> Parser e a
err (Maybe Error -> Parser (Maybe Error) Bool)
-> Maybe Error -> Parser (Maybe Error) Bool
forall a b. (a -> b) -> a -> b
$ Error -> Maybe Error
forall a. a -> Maybe a
Just (Gravity -> String -> Error
Malformed Gravity
Fatal String
str)
   )
    `catch` \Maybe Error
mayK ->
      case Maybe Error
mayK of
        Maybe Error
Nothing -> Bool -> Parser (Path, Error) Bool
forall a. a -> Parser (Path, Error) a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
True
        Just Error
e  -> (Path, Error) -> Parser (Path, Error) Bool
forall e a. e -> Parser e a
err (Path
path, Error
e)



firstElementP :: Path -> Parser (Path, Error) (Maybe K)
firstElementP :: Path -> Parser (Path, Error) (Maybe K)
firstElementP Path
path = do
  _ <- (Word8 -> Bool) -> Parser (Path, Error) ()
forall never. (Word8 -> Bool) -> Parser never ()
skipUntilEndOr (Bool -> Bool
not (Bool -> Bool) -> (Word8 -> Bool) -> Word8 -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word8 -> Bool
isWhitespace)
  ( do w <- word8 $ Left AbruptEnd
       case w of
         Word8
0x22 -> Either Error K -> Parser (Either Error K) (Maybe K)
forall e a. e -> Parser e a
err (Either Error K -> Parser (Either Error K) (Maybe K))
-> Either Error K -> Parser (Either Error K) (Maybe K)
forall a b. (a -> b) -> a -> b
$ K -> Either Error K
forall a b. b -> Either a b
Right K
S
         Word8
0x2D -> Either Error K -> Parser (Either Error K) (Maybe K)
forall e a. e -> Parser e a
err (Either Error K -> Parser (Either Error K) (Maybe K))
-> Either Error K -> Parser (Either Error K) (Maybe K)
forall a b. (a -> b) -> a -> b
$ K -> Either Error K
forall a b. b -> Either a b
Right K
N
         Word8
0x5B -> Either Error K -> Parser (Either Error K) (Maybe K)
forall e a. e -> Parser e a
err (Either Error K -> Parser (Either Error K) (Maybe K))
-> Either Error K -> Parser (Either Error K) (Maybe K)
forall a b. (a -> b) -> a -> b
$ K -> Either Error K
forall a b. b -> Either a b
Right K
A
         Word8
0x5D -> Maybe K -> Parser (Either Error K) (Maybe K)
forall a. a -> Parser (Either Error K) a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe K
forall a. Maybe a
Nothing
         Word8
0x66 -> Either Error K -> Parser (Either Error K) (Maybe K)
forall e a. e -> Parser e a
err (Either Error K -> Parser (Either Error K) (Maybe K))
-> Either Error K -> Parser (Either Error K) (Maybe K)
forall a b. (a -> b) -> a -> b
$ K -> Either Error K
forall a b. b -> Either a b
Right K
F
         Word8
0x6E -> Either Error K -> Parser (Either Error K) (Maybe K)
forall e a. e -> Parser e a
err (Either Error K -> Parser (Either Error K) (Maybe K))
-> Either Error K -> Parser (Either Error K) (Maybe K)
forall a b. (a -> b) -> a -> b
$ K -> Either Error K
forall a b. b -> Either a b
Right K
X
         Word8
0x74 -> Either Error K -> Parser (Either Error K) (Maybe K)
forall e a. e -> Parser e a
err (Either Error K -> Parser (Either Error K) (Maybe K))
-> Either Error K -> Parser (Either Error K) (Maybe K)
forall a b. (a -> b) -> a -> b
$ K -> Either Error K
forall a b. b -> Either a b
Right K
T
         Word8
0x7B -> Either Error K -> Parser (Either Error K) (Maybe K)
forall e a. e -> Parser e a
err (Either Error K -> Parser (Either Error K) (Maybe K))
-> Either Error K -> Parser (Either Error K) (Maybe K)
forall a b. (a -> b) -> a -> b
$ K -> Either Error K
forall a b. b -> Either a b
Right K
O
         Word8
_    ->
           case Word8 -> Maybe Word8
dec Word8
w of
             Just Word8
_ -> Either Error K -> Parser (Either Error K) (Maybe K)
forall e a. e -> Parser e a
err (Either Error K -> Parser (Either Error K) (Maybe K))
-> Either Error K -> Parser (Either Error K) (Maybe K)
forall a b. (a -> b) -> a -> b
$ K -> Either Error K
forall a b. b -> Either a b
Right K
N
             Maybe Word8
_      ->
               let str :: String
str = String
"Expected a JSON value or a right square bracket"
               in Either Error K -> Parser (Either Error K) (Maybe K)
forall e a. e -> Parser e a
err (Either Error K -> Parser (Either Error K) (Maybe K))
-> Either Error K -> Parser (Either Error K) (Maybe K)
forall a b. (a -> b) -> a -> b
$ Error -> Either Error K
forall a b. a -> Either a b
Left (Gravity -> String -> Error
Malformed Gravity
Fatal String
str)
   )
    `catch` \Either Error K
eiK ->
      case Either Error K
eiK of
        Right K
k -> Maybe K -> Parser (Path, Error) (Maybe K)
forall a. a -> Parser (Path, Error) a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (K -> Maybe K
forall a. a -> Maybe a
Just K
k)
        Left Error
e  -> (Path, Error) -> Parser (Path, Error) (Maybe K)
forall e a. e -> Parser e a
err (Path
path, Error
e)



-- | Check whether a byte is a JSON whitespace character.
isWhitespace :: Word8 -> Bool
isWhitespace :: Word8 -> Bool
isWhitespace Word8
w = Word8
w Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x20 Bool -> Bool -> Bool
|| Word8
w Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x09 Bool -> Bool -> Bool
|| Word8
w Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x0A Bool -> Bool -> Bool
|| Word8
w Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x0D

{-# INLINE endOfInputP #-}
endOfInputP :: e -> Parser e ()
endOfInputP :: forall e. e -> Parser e ()
endOfInputP e
e = do
  _ <- (Word8 -> Bool) -> Parser e ()
forall never. (Word8 -> Bool) -> Parser never ()
skipUntilEndOr (Bool -> Bool
not (Bool -> Bool) -> (Word8 -> Bool) -> Word8 -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word8 -> Bool
isWhitespace)
  end <- atEnd
  if end
    then pure ()
    else err e



nextKeyP :: Path -> Parser (Path, Error) ()
nextKeyP :: Path -> Parser (Path, Error) ()
nextKeyP Path
path = do
  _ <- (Word8 -> Bool) -> Parser (Path, Error) ()
forall never. (Word8 -> Bool) -> Parser never ()
skipUntilEndOr (Bool -> Bool
not (Bool -> Bool) -> (Word8 -> Bool) -> Word8 -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word8 -> Bool
isWhitespace)
  ( do w <- word8 $ Just (path, AbruptEnd)

       let !(# e #) = case w of
                        Word8
0x22 -> (# Maybe (Path, Error)
forall a. Maybe a
Nothing #)
                        Word8
_    ->
                          let str :: String
str = String
"Expected a JSON object pair name"
                          in (# (Path, Error) -> Maybe (Path, Error)
forall a. a -> Maybe a
Just (Path
path, Gravity -> String -> Error
Malformed Gravity
Fatal String
str) #)
       err e
   )
    `catch` \Maybe (Path, Error)
ei ->
      case Maybe (Path, Error)
ei of
        Maybe (Path, Error)
Nothing -> () -> Parser (Path, Error) ()
forall a. a -> Parser (Path, Error) a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
        Just (Path, Error)
e  -> (Path, Error) -> Parser (Path, Error) ()
forall e a. e -> Parser e a
err (Path, Error)
e

nextColonP :: Path -> Parser (Path, Error) ()
nextColonP :: Path -> Parser (Path, Error) ()
nextColonP Path
path = do
  _ <- (Word8 -> Bool) -> Parser (Path, Error) ()
forall never. (Word8 -> Bool) -> Parser never ()
skipUntilEndOr (Bool -> Bool
not (Bool -> Bool) -> (Word8 -> Bool) -> Word8 -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word8 -> Bool
isWhitespace)
  w <- word8 (path, AbruptEnd)
  case w of
    Word8
0x3A -> () -> Parser (Path, Error) ()
forall a. a -> Parser (Path, Error) a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
    Word8
_    ->
      let str :: String
str = String
"Expected a colon"
      in (Path, Error) -> Parser (Path, Error) ()
forall e a. e -> Parser e a
err (Path
path, Gravity -> String -> Error
Malformed Gravity
Fatal String
str)

nextPairP :: Path -> Parser (Path, Error) Bool
nextPairP :: Path -> Parser (Path, Error) Bool
nextPairP Path
path = do
  _ <- (Word8 -> Bool) -> Parser (Path, Error) ()
forall never. (Word8 -> Bool) -> Parser never ()
skipUntilEndOr (Bool -> Bool
not (Bool -> Bool) -> (Word8 -> Bool) -> Word8 -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word8 -> Bool
isWhitespace)
  w <- word8 (path, AbruptEnd)
  case w of
    Word8
0x2C -> Bool -> Parser (Path, Error) Bool
forall a. a -> Parser (Path, Error) a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
True
    Word8
0x7D -> Bool -> Parser (Path, Error) Bool
forall a. a -> Parser (Path, Error) a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
False
    Word8
_    ->
      let str :: String
str = String
"Expected a comma or a right curly bracket"
      in (Path, Error) -> Parser (Path, Error) Bool
forall e a. e -> Parser e a
err (Path
path, Gravity -> String -> Error
Malformed Gravity
Fatal String
str)



nextElementP :: Path -> Parser (Path, Error) Bool
nextElementP :: Path -> Parser (Path, Error) Bool
nextElementP Path
path = do
  _ <- (Word8 -> Bool) -> Parser (Path, Error) ()
forall never. (Word8 -> Bool) -> Parser never ()
skipUntilEndOr (Bool -> Bool
not (Bool -> Bool) -> (Word8 -> Bool) -> Word8 -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word8 -> Bool
isWhitespace)
  w <- word8 (path, AbruptEnd)
  case w of
    Word8
0x2C -> Bool -> Parser (Path, Error) Bool
forall a. a -> Parser (Path, Error) a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
True
    Word8
0x5D -> Bool -> Parser (Path, Error) Bool
forall a. a -> Parser (Path, Error) a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
False
    Word8
_    ->
      let str :: String
str = String
"Expected a comma or a right square bracket"
      in (Path, Error) -> Parser (Path, Error) Bool
forall e a. e -> Parser e a
err (Path
path, Gravity -> String -> Error
Malformed Gravity
Fatal String
str)