{-# LANGUAGE BangPatterns      #-}
{-# LANGUAGE OverloadedStrings #-}

module HaskellWorks.Data.Json.Conduit.Blank
  ( blankJson
  ) where

import           Control.Monad
import           Control.Monad.Trans.Resource         (MonadThrow)
import           Data.ByteString                      as BS
import           Data.Conduit
import           Data.Word
import           Data.Word8
import           HaskellWorks.Data.Json.Conduit.Words
import           Prelude                              as P

data BlankState
  = Escaped
  | InJson
  | InString
  | InNumber
  | InIdent

blankJson :: MonadThrow m => Conduit BS.ByteString m BS.ByteString
blankJson :: Conduit ByteString m ByteString
blankJson = BlankState -> Conduit ByteString m ByteString
forall (m :: * -> *).
MonadThrow m =>
BlankState -> Conduit ByteString m ByteString
blankJson' BlankState
InJson

blankJson' :: MonadThrow m => BlankState -> Conduit BS.ByteString m BS.ByteString
blankJson' :: BlankState -> Conduit ByteString m ByteString
blankJson' BlankState
lastState = do
  Maybe ByteString
mbs <- ConduitT ByteString ByteString m (Maybe ByteString)
forall (m :: * -> *) i. Monad m => Consumer i m (Maybe i)
await
  case Maybe ByteString
mbs of
    Just ByteString
bs -> do
      let (!ByteString
cs, Just (!BlankState
nextState, ByteString
_)) = Int
-> ((BlankState, ByteString)
    -> Maybe (Word8, (BlankState, ByteString)))
-> (BlankState, ByteString)
-> (ByteString, Maybe (BlankState, ByteString))
forall a.
Int -> (a -> Maybe (Word8, a)) -> a -> (ByteString, Maybe a)
unfoldrN (ByteString -> Int
BS.length ByteString
bs) (BlankState, ByteString) -> Maybe (Word8, (BlankState, ByteString))
blankByteString (BlankState
lastState, ByteString
bs)
      ByteString -> Conduit ByteString m ByteString
forall (m :: * -> *) o i. Monad m => o -> ConduitT i o m ()
yield ByteString
cs
      BlankState -> Conduit ByteString m ByteString
forall (m :: * -> *).
MonadThrow m =>
BlankState -> Conduit ByteString m ByteString
blankJson' BlankState
nextState
    Maybe ByteString
Nothing -> () -> Conduit ByteString m ByteString
forall (m :: * -> *) a. Monad m => a -> m a
return ()
  where
    blankByteString :: (BlankState, ByteString) -> Maybe (Word8, (BlankState, ByteString))
    blankByteString :: (BlankState, ByteString) -> Maybe (Word8, (BlankState, ByteString))
blankByteString (BlankState
InJson, ByteString
bs) = case ByteString -> Maybe (Word8, ByteString)
BS.uncons ByteString
bs of
      Just (!Word8
c, !ByteString
cs) | Word8 -> Bool
isLeadingDigit Word8
c   -> (Word8, (BlankState, ByteString))
-> Maybe (Word8, (BlankState, ByteString))
forall a. a -> Maybe a
Just (Word8
_1          , (BlankState
InNumber , ByteString
cs))
      Just (!Word8
c, !ByteString
cs) | Word8
c Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
_quotedbl     -> (Word8, (BlankState, ByteString))
-> Maybe (Word8, (BlankState, ByteString))
forall a. a -> Maybe a
Just (Word8
_parenleft  , (BlankState
InString , ByteString
cs))
      Just (!Word8
c, !ByteString
cs) | Word8 -> Bool
isAlphabetic Word8
c     -> (Word8, (BlankState, ByteString))
-> Maybe (Word8, (BlankState, ByteString))
forall a. a -> Maybe a
Just (Word8
c           , (BlankState
InIdent  , ByteString
cs))
      Just (!Word8
c, !ByteString
cs)                      -> (Word8, (BlankState, ByteString))
-> Maybe (Word8, (BlankState, ByteString))
forall a. a -> Maybe a
Just (Word8
c           , (BlankState
InJson   , ByteString
cs))
      Maybe (Word8, ByteString)
Nothing -> Maybe (Word8, (BlankState, ByteString))
forall a. Maybe a
Nothing
    blankByteString (BlankState
InString, ByteString
bs) = case ByteString -> Maybe (Word8, ByteString)
BS.uncons ByteString
bs of
      Just (!Word8
c, !ByteString
cs) | Word8
c Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
_backslash    -> (Word8, (BlankState, ByteString))
-> Maybe (Word8, (BlankState, ByteString))
forall a. a -> Maybe a
Just (Word8
_space      , (BlankState
Escaped  , ByteString
cs))
      Just (!Word8
c, !ByteString
cs) | Word8
c Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
_quotedbl     -> (Word8, (BlankState, ByteString))
-> Maybe (Word8, (BlankState, ByteString))
forall a. a -> Maybe a
Just (Word8
_parenright , (BlankState
InJson   , ByteString
cs))
      Just (Word8
_ , !ByteString
cs)                      -> (Word8, (BlankState, ByteString))
-> Maybe (Word8, (BlankState, ByteString))
forall a. a -> Maybe a
Just (Word8
_space      , (BlankState
InString , ByteString
cs))
      Maybe (Word8, ByteString)
Nothing                             -> Maybe (Word8, (BlankState, ByteString))
forall a. Maybe a
Nothing
    blankByteString (BlankState
Escaped, ByteString
bs) = case ByteString -> Maybe (Word8, ByteString)
BS.uncons ByteString
bs of
      Just (Word8
_, !ByteString
cs)                       -> (Word8, (BlankState, ByteString))
-> Maybe (Word8, (BlankState, ByteString))
forall a. a -> Maybe a
Just (Word8
_space, (BlankState
InString, ByteString
cs))
      Maybe (Word8, ByteString)
Nothing                             -> Maybe (Word8, (BlankState, ByteString))
forall a. Maybe a
Nothing
    blankByteString (BlankState
InNumber, ByteString
bs) = case ByteString -> Maybe (Word8, ByteString)
BS.uncons ByteString
bs of
      Just (!Word8
c, !ByteString
cs) | Word8 -> Bool
isTrailingDigit Word8
c  -> (Word8, (BlankState, ByteString))
-> Maybe (Word8, (BlankState, ByteString))
forall a. a -> Maybe a
Just (Word8
_0          , (BlankState
InNumber , ByteString
cs))
      Just (!Word8
c, !ByteString
cs) | Word8
c Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
_quotedbl     -> (Word8, (BlankState, ByteString))
-> Maybe (Word8, (BlankState, ByteString))
forall a. a -> Maybe a
Just (Word8
_parenleft  , (BlankState
InString , ByteString
cs))
      Just (!Word8
c, !ByteString
cs) | Word8 -> Bool
isAlphabetic Word8
c     -> (Word8, (BlankState, ByteString))
-> Maybe (Word8, (BlankState, ByteString))
forall a. a -> Maybe a
Just (Word8
c           , (BlankState
InIdent  , ByteString
cs))
      Just (!Word8
c, !ByteString
cs)                      -> (Word8, (BlankState, ByteString))
-> Maybe (Word8, (BlankState, ByteString))
forall a. a -> Maybe a
Just (Word8
c           , (BlankState
InJson   , ByteString
cs))
      Maybe (Word8, ByteString)
Nothing                             -> Maybe (Word8, (BlankState, ByteString))
forall a. Maybe a
Nothing
    blankByteString (BlankState
InIdent, ByteString
bs) = case ByteString -> Maybe (Word8, ByteString)
BS.uncons ByteString
bs of
      Just (!Word8
c, !ByteString
cs) | Word8 -> Bool
isAlphabetic Word8
c     -> (Word8, (BlankState, ByteString))
-> Maybe (Word8, (BlankState, ByteString))
forall a. a -> Maybe a
Just (Word8
_underscore , (BlankState
InIdent  , ByteString
cs))
      Just (!Word8
c, !ByteString
cs) | Word8 -> Bool
isLeadingDigit Word8
c   -> (Word8, (BlankState, ByteString))
-> Maybe (Word8, (BlankState, ByteString))
forall a. a -> Maybe a
Just (Word8
_1          , (BlankState
InNumber , ByteString
cs))
      Just (!Word8
c, !ByteString
cs) | Word8
c Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
_quotedbl     -> (Word8, (BlankState, ByteString))
-> Maybe (Word8, (BlankState, ByteString))
forall a. a -> Maybe a
Just (Word8
_parenleft  , (BlankState
InString , ByteString
cs))
      Just (!Word8
c, !ByteString
cs)                      -> (Word8, (BlankState, ByteString))
-> Maybe (Word8, (BlankState, ByteString))
forall a. a -> Maybe a
Just (Word8
c           , (BlankState
InJson   , ByteString
cs))
      Maybe (Word8, ByteString)
Nothing                             -> Maybe (Word8, (BlankState, ByteString))
forall a. Maybe a
Nothing