module JSONIncrementalDecoder
(
valueToSupplementedParser,
valueToParser,
valueToByteStringToEither,
valueToLazyByteStringToEither,
Value,
null,
nullable,
bool,
numberAsInt,
numberAsInteger,
numberAsDouble,
numberAsScientific,
string,
objectRows,
objectLookup,
arrayElements,
ObjectRows,
row,
anyRow,
ObjectLookup,
atKey,
ArrayElements,
element,
anyElement,
Matcher,
equals,
satisfies,
converts,
whatever,
)
where
import JSONIncrementalDecoder.Prelude hiding (String, null, bool)
import Data.Attoparsec.ByteString.Char8 (Parser)
import qualified Data.Attoparsec.ByteString.Char8
import qualified Data.Attoparsec.ByteString.Lazy
import qualified Data.ByteString.Lazy
import qualified JSONIncrementalDecoder.SupplementedParsers as SupplementedParsers
import qualified JSONIncrementalDecoder.Parsers as Parsers
import qualified Matcher
valueToSupplementedParser :: Value a -> Supplemented Parser a
valueToSupplementedParser (Value impl) =
impl
valueToParser :: Value a -> Parser (a, Parser ())
valueToParser =
runSupplemented .
valueToSupplementedParser
valueToByteStringToEither :: Value a -> ByteString -> Either Text a
valueToByteStringToEither value input =
either (Left . fromString) Right $
Data.Attoparsec.ByteString.Char8.parseOnly parser input
where
parser =
fmap fst $
valueToParser value
valueToLazyByteStringToEither :: Value a -> Data.ByteString.Lazy.ByteString -> Either Text a
valueToLazyByteStringToEither value input =
either (Left . fromString) Right $
Data.Attoparsec.ByteString.Lazy.eitherResult $
Data.Attoparsec.ByteString.Lazy.parse parser input
where
parser =
fmap fst $
valueToParser value
newtype Value a =
Value (Supplemented Parser a)
deriving (Functor)
instance Monoid (Value a) where
mempty =
Value empty
mappend (Value a) (Value b) =
Value (a <|> b)
null :: Value ()
null =
Value $
SupplementedParsers.null
nullable :: Value a -> Value (Maybe a)
nullable (Value p) =
Value (mplus (fmap Just p) (fmap (const Nothing) SupplementedParsers.null))
bool :: Value Bool
bool =
Value (lift Parsers.bool)
numberAsInt :: Value Int
numberAsInt =
Value (lift Parsers.numberLitAsIntegral)
numberAsInteger :: Value Integer
numberAsInteger =
Value (lift Parsers.numberLitAsIntegral)
numberAsDouble :: Value Double
numberAsDouble =
Value (lift Parsers.numberLitAsDouble)
numberAsScientific :: Value Scientific
numberAsScientific =
Value (lift Parsers.numberLitAsScientific)
string :: Value Text
string =
Value $
SupplementedParsers.stringLit
stringMatcher :: Matcher Text a -> Value a
stringMatcher matcher =
Value $
SupplementedParsers.stringLit >>=
either (const mzero) return . Matcher.run matcher
objectRows :: ObjectRows a -> Value a
objectRows (ObjectRows interspersedSupplementedParser) =
Value (SupplementedParsers.object supplementedParser)
where
supplementedParser =
runInterspersed interspersedSupplementedParser SupplementedParsers.comma
objectLookup :: ObjectLookup a -> Value a
objectLookup (ObjectLookup lookupImpl) =
objectRows $
runUnsequential lookupImpl anyRow <*
remainders
where
remainders =
ObjectRows $
optional $
interspersed $
SupplementedParsers.anyRows
arrayElements :: ArrayElements a -> Value a
arrayElements (ArrayElements interspersedSupplementedParser) =
Value (SupplementedParsers.array supplementedParser)
where
supplementedParser =
runInterspersed interspersedSupplementedParser SupplementedParsers.comma
anyValue :: Value ()
anyValue =
Value SupplementedParsers.anyValue
newtype ObjectRows a =
ObjectRows (Interspersed (Supplemented Parser) a)
deriving (Functor, Applicative, Alternative, Monad, MonadPlus)
row :: (a -> b -> c) -> Matcher Text a -> Value b -> ObjectRows c
row combine keyMatcher (Value value) =
ObjectRows (lift (SupplementedParsers.row combine key value))
where
key =
SupplementedParsers.stringLit >>=
either (const mzero) return . Matcher.run keyMatcher
anyRow :: ObjectRows ()
anyRow =
ObjectRows (lift (SupplementedParsers.anyRow))
newtype ObjectLookup a =
ObjectLookup (Unsequential ObjectRows a)
deriving (Functor, Applicative)
atKey :: Text -> Value a -> ObjectLookup a
atKey key value =
ObjectLookup $
unsequential $
row (const id) (equals key) value
newtype ArrayElements a =
ArrayElements (Interspersed (Supplemented Parser) a)
deriving (Functor, Applicative, Alternative, Monad, MonadPlus)
element :: Value a -> ArrayElements a
element (Value value) =
ArrayElements (lift value)
anyElement :: ArrayElements ()
anyElement =
ArrayElements (lift (SupplementedParsers.anyValue))