{-# LANGUAGE CPP #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE PatternGuards #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE BangPatterns #-}
module Data.Yaml.Internal
(
ParseException(..)
, prettyPrintParseException
, Warning(..)
, parse
, Parse
, decodeHelper
, decodeHelper_
, decodeAllHelper
, decodeAllHelper_
, textToScientific
, stringScalar
, StringStyle
, defaultStringStyle
, isSpecialString
, specialStrings
, isNumeric
, objToStream
, objToEvents
) where
#if !MIN_VERSION_base(4,8,0)
import Control.Applicative ((<$>), Applicative(..))
#endif
import Control.Applicative ((<|>))
import Control.Exception
import Control.Monad (when, unless)
import Control.Monad.Trans.Resource (ResourceT, runResourceT)
import Control.Monad.State.Strict
import Control.Monad.Reader
#if MIN_VERSION_aeson(2,1,2)
import Data.Aeson hiding (AesonException)
#else
import Data.Aeson
#endif
#if MIN_VERSION_aeson(2,0,0)
import qualified Data.Aeson.Key as K
import qualified Data.Aeson.KeyMap as M
import Data.Aeson.KeyMap (KeyMap)
#else
import qualified Data.HashMap.Strict as M
#endif
#if MIN_VERSION_aeson(2,2,0)
import Data.Aeson.Types hiding (AesonException, parse)
#else
import Data.Aeson.Types hiding (parse)
import Data.Aeson.Internal (JSONPath, JSONPathElement(..), formatError)
#endif
import qualified Data.Attoparsec.Text as Atto
import Data.Bits (shiftL, (.|.))
import Data.ByteString (ByteString)
import qualified Data.ByteString.Builder as BB
import qualified Data.ByteString.Lazy as BL
import Data.ByteString.Builder.Scientific (scientificBuilder)
import Data.Char (toUpper, ord)
import qualified Data.List as List
import Data.Conduit ((.|), ConduitM, runConduit)
import qualified Data.Conduit.List as CL
import qualified Data.HashSet as HashSet
import Data.Map (Map)
import qualified Data.Map as Map
import Data.Set (Set)
import qualified Data.Set as Set
import Data.Scientific (Scientific, base10Exponent, coefficient)
import Data.Text (Text)
import qualified Data.Text as T
import Data.Text.Encoding (decodeUtf8With, encodeUtf8)
import Data.Text.Encoding.Error (lenientDecode)
import Data.Typeable
import qualified Data.Vector as V
import Data.Void (Void)
import qualified Text.Libyaml as Y
import Text.Libyaml hiding (encode, decode, encodeFile, decodeFile)
#if MIN_VERSION_aeson(2,0,0)
fromText :: T.Text -> K.Key
fromText :: Text -> Key
fromText = Text -> Key
K.fromText
toText :: K.Key -> T.Text
toText :: Key -> Text
toText = Key -> Text
K.toText
#else
fromText :: T.Text -> T.Text
fromText = id
toText :: Key -> T.Text
toText = id
type KeyMap a = M.HashMap Text a
type Key = Text
#endif
data ParseException = NonScalarKey
| UnknownAlias { ParseException -> [Char]
_anchorName :: Y.AnchorName }
| UnexpectedEvent { ParseException -> Maybe Event
_received :: Maybe Event
, ParseException -> Maybe Event
_expected :: Maybe Event
}
| InvalidYaml (Maybe YamlException)
| MultipleDocuments
| AesonException String
| OtherParseException SomeException
| NonStringKey JSONPath
| NonStringKeyAlias Y.AnchorName Value
| CyclicIncludes
| LoadSettingsException FilePath ParseException
deriving (Int -> ParseException -> ShowS
[ParseException] -> ShowS
ParseException -> [Char]
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
showList :: [ParseException] -> ShowS
$cshowList :: [ParseException] -> ShowS
show :: ParseException -> [Char]
$cshow :: ParseException -> [Char]
showsPrec :: Int -> ParseException -> ShowS
$cshowsPrec :: Int -> ParseException -> ShowS
Show, Typeable)
instance Exception ParseException where
#if MIN_VERSION_base(4, 8, 0)
displayException :: ParseException -> [Char]
displayException = ParseException -> [Char]
prettyPrintParseException
#endif
prettyPrintParseException :: ParseException -> String
prettyPrintParseException :: ParseException -> [Char]
prettyPrintParseException ParseException
pe = case ParseException
pe of
ParseException
NonScalarKey -> [Char]
"Non scalar key"
UnknownAlias [Char]
anchor -> [Char]
"Unknown alias `" forall a. [a] -> [a] -> [a]
++ [Char]
anchor forall a. [a] -> [a] -> [a]
++ [Char]
"`"
UnexpectedEvent { _expected :: ParseException -> Maybe Event
_expected = Maybe Event
mbExpected, _received :: ParseException -> Maybe Event
_received = Maybe Event
mbUnexpected } -> [[Char]] -> [Char]
unlines
[ [Char]
"Unexpected event: expected"
, [Char]
" " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> [Char]
show Maybe Event
mbExpected
, [Char]
"but received"
, [Char]
" " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> [Char]
show Maybe Event
mbUnexpected
]
InvalidYaml Maybe YamlException
mbYamlError -> case Maybe YamlException
mbYamlError of
Maybe YamlException
Nothing -> [Char]
"Unspecified YAML error"
Just YamlException
yamlError -> case YamlException
yamlError of
YamlException [Char]
s -> [Char]
"YAML exception:\n" forall a. [a] -> [a] -> [a]
++ [Char]
s
YamlParseException [Char]
problem [Char]
context YamlMark
mark -> forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
[ [Char]
"YAML parse exception at line " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> [Char]
show (YamlMark -> Int
yamlLine YamlMark
mark) forall a. [a] -> [a] -> [a]
++
[Char]
", column " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> [Char]
show (YamlMark -> Int
yamlColumn YamlMark
mark)
, case [Char]
context of
[Char]
"" -> [Char]
":\n"
[Char]
_ -> [Char]
",\n" forall a. [a] -> [a] -> [a]
++ [Char]
context forall a. [a] -> [a] -> [a]
++ [Char]
":\n"
, [Char]
problem
]
ParseException
MultipleDocuments -> [Char]
"Multiple YAML documents encountered"
AesonException [Char]
s -> [Char]
"Aeson exception:\n" forall a. [a] -> [a] -> [a]
++ [Char]
s
OtherParseException SomeException
exc -> [Char]
"Generic parse exception:\n" forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> [Char]
show SomeException
exc
NonStringKey JSONPath
path -> JSONPath -> ShowS
formatError JSONPath
path [Char]
"Non-string keys are not supported"
NonStringKeyAlias [Char]
anchor Value
value -> [[Char]] -> [Char]
unlines
[ [Char]
"Non-string key alias:"
, [Char]
" Anchor name: " forall a. [a] -> [a] -> [a]
++ [Char]
anchor
, [Char]
" Value: " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> [Char]
show Value
value
]
ParseException
CyclicIncludes -> [Char]
"Cyclic includes"
LoadSettingsException [Char]
fp ParseException
exc -> [Char]
"Could not parse file as YAML: " forall a. [a] -> [a] -> [a]
++ [Char]
fp forall a. [a] -> [a] -> [a]
++ [Char]
"\n" forall a. [a] -> [a] -> [a]
++ ParseException -> [Char]
prettyPrintParseException ParseException
exc
defineAnchor :: Value -> String -> ReaderT JSONPath (ConduitM e o Parse) ()
defineAnchor :: forall e o.
Value -> [Char] -> ReaderT JSONPath (ConduitM e o Parse) ()
defineAnchor Value
value [Char]
name = forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify ((Map [Char] Value -> Map [Char] Value) -> ParseState -> ParseState
modifyAnchors forall a b. (a -> b) -> a -> b
$ forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert [Char]
name Value
value)
where
modifyAnchors :: (Map String Value -> Map String Value) -> ParseState -> ParseState
modifyAnchors :: (Map [Char] Value -> Map [Char] Value) -> ParseState -> ParseState
modifyAnchors Map [Char] Value -> Map [Char] Value
f ParseState
st = ParseState
st {parseStateAnchors :: Map [Char] Value
parseStateAnchors = Map [Char] Value -> Map [Char] Value
f (ParseState -> Map [Char] Value
parseStateAnchors ParseState
st)}
lookupAnchor :: String -> ReaderT JSONPath (ConduitM e o Parse) (Maybe Value)
lookupAnchor :: forall e o.
[Char] -> ReaderT JSONPath (ConduitM e o Parse) (Maybe Value)
lookupAnchor [Char]
name = forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets (forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup [Char]
name forall b c a. (b -> c) -> (a -> b) -> a -> c
. ParseState -> Map [Char] Value
parseStateAnchors)
data Warning = DuplicateKey JSONPath
deriving (Warning -> Warning -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Warning -> Warning -> Bool
$c/= :: Warning -> Warning -> Bool
== :: Warning -> Warning -> Bool
$c== :: Warning -> Warning -> Bool
Eq, Int -> Warning -> ShowS
[Warning] -> ShowS
Warning -> [Char]
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
showList :: [Warning] -> ShowS
$cshowList :: [Warning] -> ShowS
show :: Warning -> [Char]
$cshow :: Warning -> [Char]
showsPrec :: Int -> Warning -> ShowS
$cshowsPrec :: Int -> Warning -> ShowS
Show)
addWarning :: Warning -> ReaderT JSONPath (ConduitM e o Parse) ()
addWarning :: forall e o. Warning -> ReaderT JSONPath (ConduitM e o Parse) ()
addWarning Warning
w = forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify (([Warning] -> [Warning]) -> ParseState -> ParseState
modifyWarnings (Warning
w forall a. a -> [a] -> [a]
:))
where
modifyWarnings :: ([Warning] -> [Warning]) -> ParseState -> ParseState
modifyWarnings :: ([Warning] -> [Warning]) -> ParseState -> ParseState
modifyWarnings [Warning] -> [Warning]
f ParseState
st = ParseState
st {parseStateWarnings :: [Warning]
parseStateWarnings = [Warning] -> [Warning]
f (ParseState -> [Warning]
parseStateWarnings ParseState
st)}
data ParseState = ParseState {
ParseState -> Map [Char] Value
parseStateAnchors :: Map String Value
, ParseState -> [Warning]
parseStateWarnings :: [Warning]
}
type Parse = StateT ParseState (ResourceT IO)
requireEvent :: Event -> ReaderT JSONPath (ConduitM Event o Parse) ()
requireEvent :: forall o. Event -> ReaderT JSONPath (ConduitM Event o Parse) ()
requireEvent Event
e = do
Maybe Event
f <- forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift forall (m :: * -> *) a o. Monad m => ConduitT a o m (Maybe a)
CL.head
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Maybe Event
f forall a. Eq a => a -> a -> Bool
== forall a. a -> Maybe a
Just Event
e) forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ forall e a. Exception e => e -> IO a
throwIO forall a b. (a -> b) -> a -> b
$ Maybe Event -> Maybe Event -> ParseException
UnexpectedEvent Maybe Event
f forall a b. (a -> b) -> a -> b
$ forall a. a -> Maybe a
Just Event
e
parse :: ReaderT JSONPath (ConduitM Event o Parse) Value
parse :: forall o. ReaderT JSONPath (ConduitM Event o Parse) Value
parse = do
[Value]
docs <- forall o. ReaderT JSONPath (ConduitM Event o Parse) [Value]
parseAll
case [Value]
docs of
[] -> forall (m :: * -> *) a. Monad m => a -> m a
return Value
Null
[Value
doc] -> forall (m :: * -> *) a. Monad m => a -> m a
return Value
doc
[Value]
_ -> forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ forall e a. Exception e => e -> IO a
throwIO ParseException
MultipleDocuments
parseAll :: ReaderT JSONPath (ConduitM Event o Parse) [Value]
parseAll :: forall o. ReaderT JSONPath (ConduitM Event o Parse) [Value]
parseAll = do
Maybe Event
streamStart <- forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift forall (m :: * -> *) a o. Monad m => ConduitT a o m (Maybe a)
CL.head
case Maybe Event
streamStart of
Maybe Event
Nothing ->
forall (m :: * -> *) a. Monad m => a -> m a
return []
Just Event
EventStreamStart ->
forall o. ReaderT JSONPath (ConduitM Event o Parse) [Value]
parseDocs
Maybe Event
_ -> forall {m :: * -> *} {a}. MonadIO m => Maybe Event -> m a
missed Maybe Event
streamStart
where
parseDocs :: ReaderT JSONPath (ConduitT Event o Parse) [Value]
parseDocs = do
Maybe Event
documentStart <- forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift forall (m :: * -> *) a o. Monad m => ConduitT a o m (Maybe a)
CL.head
case Maybe Event
documentStart of
Just Event
EventStreamEnd -> forall (m :: * -> *) a. Monad m => a -> m a
return []
Just Event
EventDocumentStart -> do
Value
res <- forall o. ReaderT JSONPath (ConduitM Event o Parse) Value
parseO
forall o. Event -> ReaderT JSONPath (ConduitM Event o Parse) ()
requireEvent Event
EventDocumentEnd
(Value
res forall a. a -> [a] -> [a]
:) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ReaderT JSONPath (ConduitT Event o Parse) [Value]
parseDocs
Maybe Event
_ -> forall {m :: * -> *} {a}. MonadIO m => Maybe Event -> m a
missed Maybe Event
documentStart
missed :: Maybe Event -> m a
missed Maybe Event
event = forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ forall e a. Exception e => e -> IO a
throwIO forall a b. (a -> b) -> a -> b
$ Maybe Event -> Maybe Event -> ParseException
UnexpectedEvent Maybe Event
event forall a. Maybe a
Nothing
parseScalar :: ByteString -> Anchor -> Style -> Tag
-> ReaderT JSONPath (ConduitM Event o Parse) Text
parseScalar :: forall o.
ByteString
-> Anchor
-> Style
-> Tag
-> ReaderT JSONPath (ConduitM Event o Parse) Text
parseScalar ByteString
v Anchor
a Style
style Tag
tag = do
let res :: Text
res = OnDecodeError -> ByteString -> Text
decodeUtf8With OnDecodeError
lenientDecode ByteString
v
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (forall e o.
Value -> [Char] -> ReaderT JSONPath (ConduitM e o Parse) ()
defineAnchor (Style -> Tag -> Text -> Value
textToValue Style
style Tag
tag Text
res)) Anchor
a
forall (m :: * -> *) a. Monad m => a -> m a
return Text
res
textToValue :: Style -> Tag -> Text -> Value
textToValue :: Style -> Tag -> Text -> Value
textToValue Style
SingleQuoted Tag
_ Text
t = Text -> Value
String Text
t
textToValue Style
DoubleQuoted Tag
_ Text
t = Text -> Value
String Text
t
textToValue Style
_ Tag
StrTag Text
t = Text -> Value
String Text
t
textToValue Style
Folded Tag
_ Text
t = Text -> Value
String Text
t
textToValue Style
_ Tag
_ Text
t
| Text
t forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Text
"null", Text
"Null", Text
"NULL", Text
"~", Text
""] = Value
Null
| forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (Text
t Text -> Text -> Bool
`isLike`) [Text
"y", Text
"yes", Text
"on", Text
"true"] = Bool -> Value
Bool Bool
True
| forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (Text
t Text -> Text -> Bool
`isLike`) [Text
"n", Text
"no", Text
"off", Text
"false"] = Bool -> Value
Bool Bool
False
| Right Scientific
x <- Text -> Either [Char] Scientific
textToScientific Text
t = Scientific -> Value
Number Scientific
x
| Bool
otherwise = Text -> Value
String Text
t
where Text
x isLike :: Text -> Text -> Bool
`isLike` Text
ref = Text
x forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Text
ref, Text -> Text
T.toUpper Text
ref, Text
titleCased]
where titleCased :: Text
titleCased = Char -> Char
toUpper (Text -> Char
T.head Text
ref) Char -> Text -> Text
`T.cons` Text -> Text
T.tail Text
ref
textToScientific :: Text -> Either String Scientific
textToScientific :: Text -> Either [Char] Scientific
textToScientific = forall a. Parser a -> Text -> Either [Char] a
Atto.parseOnly (Parser Text Scientific
num forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* forall t. Chunk t => Parser t ()
Atto.endOfInput)
where
num :: Parser Text Scientific
num = (forall a. Num a => Integer -> a
fromInteger forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Parser Text Text
"0x" forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> forall a. (Integral a, Bits a) => Parser a
Atto.hexadecimal))
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (forall a. Num a => Integer -> a
fromInteger forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Parser Text Text
"0o" forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser Text Integer
octal))
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser Text Scientific
Atto.scientific
octal :: Parser Text Integer
octal = forall a. (a -> Char -> a) -> a -> Text -> a
T.foldl' forall {a}. (Bits a, Num a) => a -> Char -> a
step Integer
0 forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Char -> Bool) -> Parser Text Text
Atto.takeWhile1 Char -> Bool
isOctalDigit
where
isOctalDigit :: Char -> Bool
isOctalDigit Char
c = (Char
c forall a. Ord a => a -> a -> Bool
>= Char
'0' Bool -> Bool -> Bool
&& Char
c forall a. Ord a => a -> a -> Bool
<= Char
'7')
step :: a -> Char -> a
step a
a Char
c = (a
a forall a. Bits a => a -> Int -> a
`shiftL` Int
3) forall a. Bits a => a -> a -> a
.|. forall a b. (Integral a, Num b) => a -> b
fromIntegral (Char -> Int
ord Char
c forall a. Num a => a -> a -> a
- Int
48)
parseO :: ReaderT JSONPath (ConduitM Event o Parse) Value
parseO :: forall o. ReaderT JSONPath (ConduitM Event o Parse) Value
parseO = do
Maybe Event
me <- forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift forall (m :: * -> *) a o. Monad m => ConduitT a o m (Maybe a)
CL.head
case Maybe Event
me of
Just (EventScalar ByteString
v Tag
tag Style
style Anchor
a) -> Style -> Tag -> Text -> Value
textToValue Style
style Tag
tag forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall o.
ByteString
-> Anchor
-> Style
-> Tag
-> ReaderT JSONPath (ConduitM Event o Parse) Text
parseScalar ByteString
v Anchor
a Style
style Tag
tag
Just (EventSequenceStart Tag
_ SequenceStyle
_ Anchor
a) -> forall o.
Int
-> Anchor
-> ([Value] -> [Value])
-> ReaderT JSONPath (ConduitM Event o Parse) Value
parseS Int
0 Anchor
a forall a. a -> a
id
Just (EventMappingStart Tag
_ MappingStyle
_ Anchor
a) -> forall o.
Set Key
-> Anchor
-> KeyMap Value
-> ReaderT JSONPath (ConduitM Event o Parse) Value
parseM forall a. Monoid a => a
mempty Anchor
a forall v. KeyMap v
M.empty
Just (EventAlias [Char]
an) -> do
Maybe Value
m <- forall e o.
[Char] -> ReaderT JSONPath (ConduitM e o Parse) (Maybe Value)
lookupAnchor [Char]
an
case Maybe Value
m of
Maybe Value
Nothing -> forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ forall e a. Exception e => e -> IO a
throwIO forall a b. (a -> b) -> a -> b
$ [Char] -> ParseException
UnknownAlias [Char]
an
Just Value
v -> forall (m :: * -> *) a. Monad m => a -> m a
return Value
v
Maybe Event
_ -> forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ forall e a. Exception e => e -> IO a
throwIO forall a b. (a -> b) -> a -> b
$ Maybe Event -> Maybe Event -> ParseException
UnexpectedEvent Maybe Event
me forall a. Maybe a
Nothing
parseS :: Int
-> Y.Anchor
-> ([Value] -> [Value])
-> ReaderT JSONPath (ConduitM Event o Parse) Value
parseS :: forall o.
Int
-> Anchor
-> ([Value] -> [Value])
-> ReaderT JSONPath (ConduitM Event o Parse) Value
parseS !Int
n Anchor
a [Value] -> [Value]
front = do
Maybe Event
me <- forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift forall (m :: * -> *) a o. Monad m => ConduitT a o m (Maybe a)
CL.peek
case Maybe Event
me of
Just Event
EventSequenceEnd -> do
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a o. Monad m => Int -> ConduitT a o m ()
CL.drop Int
1
let res :: Value
res = Array -> Value
Array forall a b. (a -> b) -> a -> b
$ forall a. [a] -> Vector a
V.fromList forall a b. (a -> b) -> a -> b
$ [Value] -> [Value]
front []
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (forall e o.
Value -> [Char] -> ReaderT JSONPath (ConduitM e o Parse) ()
defineAnchor Value
res) Anchor
a
forall (m :: * -> *) a. Monad m => a -> m a
return Value
res
Maybe Event
_ -> do
Value
o <- forall r (m :: * -> *) a. MonadReader r m => (r -> r) -> m a -> m a
local (Int -> JSONPathElement
Index Int
n forall a. a -> [a] -> [a]
:) forall o. ReaderT JSONPath (ConduitM Event o Parse) Value
parseO
forall o.
Int
-> Anchor
-> ([Value] -> [Value])
-> ReaderT JSONPath (ConduitM Event o Parse) Value
parseS (forall a. Enum a => a -> a
succ Int
n) Anchor
a forall a b. (a -> b) -> a -> b
$ [Value] -> [Value]
front forall b c a. (b -> c) -> (a -> b) -> a -> c
. (:) Value
o
parseM :: Set Key
-> Y.Anchor
-> KeyMap Value
-> ReaderT JSONPath (ConduitM Event o Parse) Value
parseM :: forall o.
Set Key
-> Anchor
-> KeyMap Value
-> ReaderT JSONPath (ConduitM Event o Parse) Value
parseM Set Key
mergedKeys Anchor
a KeyMap Value
front = do
Maybe Event
me <- forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift forall (m :: * -> *) a o. Monad m => ConduitT a o m (Maybe a)
CL.head
case Maybe Event
me of
Just Event
EventMappingEnd -> do
let res :: Value
res = KeyMap Value -> Value
Object KeyMap Value
front
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (forall e o.
Value -> [Char] -> ReaderT JSONPath (ConduitM e o Parse) ()
defineAnchor Value
res) Anchor
a
forall (m :: * -> *) a. Monad m => a -> m a
return Value
res
Maybe Event
_ -> do
Key
s <- case Maybe Event
me of
Just (EventScalar ByteString
v Tag
tag Style
style Anchor
a') -> Text -> Key
fromText forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall o.
ByteString
-> Anchor
-> Style
-> Tag
-> ReaderT JSONPath (ConduitM Event o Parse) Text
parseScalar ByteString
v Anchor
a' Style
style Tag
tag
Just (EventAlias [Char]
an) -> do
Maybe Value
m <- forall e o.
[Char] -> ReaderT JSONPath (ConduitM e o Parse) (Maybe Value)
lookupAnchor [Char]
an
case Maybe Value
m of
Maybe Value
Nothing -> forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ forall e a. Exception e => e -> IO a
throwIO forall a b. (a -> b) -> a -> b
$ [Char] -> ParseException
UnknownAlias [Char]
an
Just (String Text
t) -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Text -> Key
fromText Text
t
Just Value
v -> forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ forall e a. Exception e => e -> IO a
throwIO forall a b. (a -> b) -> a -> b
$ [Char] -> Value -> ParseException
NonStringKeyAlias [Char]
an Value
v
Maybe Event
_ -> do
JSONPath
path <- forall r (m :: * -> *). MonadReader r m => m r
ask
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ forall e a. Exception e => e -> IO a
throwIO forall a b. (a -> b) -> a -> b
$ JSONPath -> ParseException
NonStringKey JSONPath
path
(Set Key
mergedKeys', KeyMap Value
al') <- forall r (m :: * -> *) a. MonadReader r m => (r -> r) -> m a -> m a
local (Key -> JSONPathElement
Key Key
s forall a. a -> [a] -> [a]
:) forall a b. (a -> b) -> a -> b
$ do
Value
o <- forall o. ReaderT JSONPath (ConduitM Event o Parse) Value
parseO
let al :: ReaderT JSONPath (ConduitM e o Parse) (Set Key, KeyMap Value)
al = do
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (forall a. Key -> KeyMap a -> Bool
M.member Key
s KeyMap Value
front Bool -> Bool -> Bool
&& forall a. Ord a => a -> Set a -> Bool
Set.notMember Key
s Set Key
mergedKeys) forall a b. (a -> b) -> a -> b
$ do
JSONPath
path <- forall a. [a] -> [a]
reverse forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall r (m :: * -> *). MonadReader r m => m r
ask
forall e o. Warning -> ReaderT JSONPath (ConduitM e o Parse) ()
addWarning (JSONPath -> Warning
DuplicateKey JSONPath
path)
forall (m :: * -> *) a. Monad m => a -> m a
return (forall a. Ord a => a -> Set a -> Set a
Set.delete Key
s Set Key
mergedKeys, forall v. Key -> v -> KeyMap v -> KeyMap v
M.insert Key
s Value
o KeyMap Value
front)
if Key
s forall a. Eq a => a -> a -> Bool
== Key
"<<"
then case Value
o of
Object KeyMap Value
l -> forall (m :: * -> *) a. Monad m => a -> m a
return (KeyMap Value -> (Set Key, KeyMap Value)
merge KeyMap Value
l)
Array Array
l -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ KeyMap Value -> (Set Key, KeyMap Value)
merge forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
List.foldl' KeyMap Value -> Value -> KeyMap Value
mergeObjects forall v. KeyMap v
M.empty forall a b. (a -> b) -> a -> b
$ forall a. Vector a -> [a]
V.toList Array
l
Value
_ -> forall {e} {o}.
ReaderT JSONPath (ConduitM e o Parse) (Set Key, KeyMap Value)
al
else forall {e} {o}.
ReaderT JSONPath (ConduitM e o Parse) (Set Key, KeyMap Value)
al
forall o.
Set Key
-> Anchor
-> KeyMap Value
-> ReaderT JSONPath (ConduitM Event o Parse) Value
parseM Set Key
mergedKeys' Anchor
a KeyMap Value
al'
where mergeObjects :: KeyMap Value -> Value -> KeyMap Value
mergeObjects KeyMap Value
al (Object KeyMap Value
om) = forall v. KeyMap v -> KeyMap v -> KeyMap v
M.union KeyMap Value
al KeyMap Value
om
mergeObjects KeyMap Value
al Value
_ = KeyMap Value
al
merge :: KeyMap Value -> (Set Key, KeyMap Value)
merge KeyMap Value
xs = (forall a. Ord a => [a] -> Set a
Set.fromList (forall v. KeyMap v -> [Key]
M.keys KeyMap Value
xs forall a. Eq a => [a] -> [a] -> [a]
List.\\ forall v. KeyMap v -> [Key]
M.keys KeyMap Value
front), forall v. KeyMap v -> KeyMap v -> KeyMap v
M.union KeyMap Value
front KeyMap Value
xs)
parseSrc :: ReaderT JSONPath (ConduitM Event Void Parse) val
-> ConduitM () Event Parse ()
-> IO (val, ParseState)
parseSrc :: forall val.
ReaderT JSONPath (ConduitM Event Void Parse) val
-> ConduitM () Event Parse () -> IO (val, ParseState)
parseSrc ReaderT JSONPath (ConduitM Event Void Parse) val
eventParser ConduitM () Event Parse ()
src = forall (m :: * -> *) a. MonadUnliftIO m => ResourceT m a -> m a
runResourceT forall a b. (a -> b) -> a -> b
$ forall s (m :: * -> *) a. StateT s m a -> s -> m (a, s)
runStateT
(forall (m :: * -> *) r. Monad m => ConduitT () Void m r -> m r
runConduit forall a b. (a -> b) -> a -> b
$ ConduitM () Event Parse ()
src forall (m :: * -> *) a b c r.
Monad m =>
ConduitT a b m () -> ConduitT b c m r -> ConduitT a c m r
.| forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT ReaderT JSONPath (ConduitM Event Void Parse) val
eventParser [])
(Map [Char] Value -> [Warning] -> ParseState
ParseState forall k a. Map k a
Map.empty [])
mkHelper :: ReaderT JSONPath (ConduitM Event Void Parse) val
-> (SomeException -> IO (Either ParseException a))
-> ((val, ParseState) -> Either ParseException a)
-> ConduitM () Event Parse ()
-> IO (Either ParseException a)
mkHelper :: forall val a.
ReaderT JSONPath (ConduitM Event Void Parse) val
-> (SomeException -> IO (Either ParseException a))
-> ((val, ParseState) -> Either ParseException a)
-> ConduitM () Event Parse ()
-> IO (Either ParseException a)
mkHelper ReaderT JSONPath (ConduitM Event Void Parse) val
eventParser SomeException -> IO (Either ParseException a)
onOtherExc (val, ParseState) -> Either ParseException a
extractResults ConduitM () Event Parse ()
src = forall a. IO a -> [Handler a] -> IO a
catches
((val, ParseState) -> Either ParseException a
extractResults forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall val.
ReaderT JSONPath (ConduitM Event Void Parse) val
-> ConduitM () Event Parse () -> IO (val, ParseState)
parseSrc ReaderT JSONPath (ConduitM Event Void Parse) val
eventParser ConduitM () Event Parse ()
src)
[ forall a e. Exception e => (e -> IO a) -> Handler a
Handler forall a b. (a -> b) -> a -> b
$ \ParseException
pe -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a b. a -> Either a b
Left (ParseException
pe :: ParseException)
, forall a e. Exception e => (e -> IO a) -> Handler a
Handler forall a b. (a -> b) -> a -> b
$ \YamlException
ye -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a b. a -> Either a b
Left forall a b. (a -> b) -> a -> b
$ Maybe YamlException -> ParseException
InvalidYaml forall a b. (a -> b) -> a -> b
$ forall a. a -> Maybe a
Just (YamlException
ye :: YamlException)
, forall a e. Exception e => (e -> IO a) -> Handler a
Handler forall a b. (a -> b) -> a -> b
$ \SomeAsyncException
sae -> forall e a. Exception e => e -> IO a
throwIO (SomeAsyncException
sae :: SomeAsyncException)
, forall a e. Exception e => (e -> IO a) -> Handler a
Handler SomeException -> IO (Either ParseException a)
onOtherExc
]
decodeHelper :: FromJSON a
=> ConduitM () Y.Event Parse ()
-> IO (Either ParseException ([Warning], Either String a))
decodeHelper :: forall a.
FromJSON a =>
ConduitM () Event Parse ()
-> IO (Either ParseException ([Warning], Either [Char] a))
decodeHelper = forall val a.
ReaderT JSONPath (ConduitM Event Void Parse) val
-> (SomeException -> IO (Either ParseException a))
-> ((val, ParseState) -> Either ParseException a)
-> ConduitM () Event Parse ()
-> IO (Either ParseException a)
mkHelper forall o. ReaderT JSONPath (ConduitM Event o Parse) Value
parse forall e a. Exception e => e -> IO a
throwIO forall a b. (a -> b) -> a -> b
$ \(Value
v, ParseState
st) ->
forall a b. b -> Either a b
Right (ParseState -> [Warning]
parseStateWarnings ParseState
st, forall a b. (a -> Parser b) -> a -> Either [Char] b
parseEither forall a. FromJSON a => Value -> Parser a
parseJSON Value
v)
decodeAllHelper :: FromJSON a
=> ConduitM () Event Parse ()
-> IO (Either ParseException ([Warning], Either String [a]))
decodeAllHelper :: forall a.
FromJSON a =>
ConduitM () Event Parse ()
-> IO (Either ParseException ([Warning], Either [Char] [a]))
decodeAllHelper = forall val a.
ReaderT JSONPath (ConduitM Event Void Parse) val
-> (SomeException -> IO (Either ParseException a))
-> ((val, ParseState) -> Either ParseException a)
-> ConduitM () Event Parse ()
-> IO (Either ParseException a)
mkHelper forall o. ReaderT JSONPath (ConduitM Event o Parse) [Value]
parseAll forall e a. Exception e => e -> IO a
throwIO forall a b. (a -> b) -> a -> b
$ \([Value]
vs, ParseState
st) ->
forall a b. b -> Either a b
Right (ParseState -> [Warning]
parseStateWarnings ParseState
st, forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (forall a b. (a -> Parser b) -> a -> Either [Char] b
parseEither forall a. FromJSON a => Value -> Parser a
parseJSON) [Value]
vs)
catchLeft :: SomeException -> IO (Either ParseException a)
catchLeft :: forall a. SomeException -> IO (Either ParseException a)
catchLeft = forall (m :: * -> *) a. Monad m => a -> m a
return forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. a -> Either a b
Left forall b c a. (b -> c) -> (a -> b) -> a -> c
. SomeException -> ParseException
OtherParseException
decodeHelper_ :: FromJSON a
=> ConduitM () Event Parse ()
-> IO (Either ParseException ([Warning], a))
decodeHelper_ :: forall a.
FromJSON a =>
ConduitM () Event Parse ()
-> IO (Either ParseException ([Warning], a))
decodeHelper_ = forall val a.
ReaderT JSONPath (ConduitM Event Void Parse) val
-> (SomeException -> IO (Either ParseException a))
-> ((val, ParseState) -> Either ParseException a)
-> ConduitM () Event Parse ()
-> IO (Either ParseException a)
mkHelper forall o. ReaderT JSONPath (ConduitM Event o Parse) Value
parse forall a. SomeException -> IO (Either ParseException a)
catchLeft forall a b. (a -> b) -> a -> b
$ \(Value
v, ParseState
st) ->
case forall a b. (a -> Parser b) -> a -> Either [Char] b
parseEither forall a. FromJSON a => Value -> Parser a
parseJSON Value
v of
Left [Char]
e -> forall a b. a -> Either a b
Left forall a b. (a -> b) -> a -> b
$ [Char] -> ParseException
AesonException [Char]
e
Right a
x -> forall a b. b -> Either a b
Right (ParseState -> [Warning]
parseStateWarnings ParseState
st, a
x)
decodeAllHelper_ :: FromJSON a
=> ConduitM () Event Parse ()
-> IO (Either ParseException ([Warning], [a]))
decodeAllHelper_ :: forall a.
FromJSON a =>
ConduitM () Event Parse ()
-> IO (Either ParseException ([Warning], [a]))
decodeAllHelper_ = forall val a.
ReaderT JSONPath (ConduitM Event Void Parse) val
-> (SomeException -> IO (Either ParseException a))
-> ((val, ParseState) -> Either ParseException a)
-> ConduitM () Event Parse ()
-> IO (Either ParseException a)
mkHelper forall o. ReaderT JSONPath (ConduitM Event o Parse) [Value]
parseAll forall a. SomeException -> IO (Either ParseException a)
catchLeft forall a b. (a -> b) -> a -> b
$ \([Value]
vs, ParseState
st) ->
case forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (forall a b. (a -> Parser b) -> a -> Either [Char] b
parseEither forall a. FromJSON a => Value -> Parser a
parseJSON) [Value]
vs of
Left [Char]
e -> forall a b. a -> Either a b
Left forall a b. (a -> b) -> a -> b
$ [Char] -> ParseException
AesonException [Char]
e
Right [a]
xs -> forall a b. b -> Either a b
Right (ParseState -> [Warning]
parseStateWarnings ParseState
st, [a]
xs)
type StringStyle = Text -> ( Tag, Style )
stringScalar :: StringStyle -> Maybe Text -> Text -> Event
stringScalar :: StringStyle -> Maybe Text -> Text -> Event
stringScalar StringStyle
_ Maybe Text
anchor Text
"" = ByteString -> Tag -> Style -> Anchor -> Event
EventScalar ByteString
"" Tag
NoTag Style
SingleQuoted (Text -> [Char]
T.unpack forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe Text
anchor)
stringScalar StringStyle
stringStyle Maybe Text
anchor Text
s = ByteString -> Tag -> Style -> Anchor -> Event
EventScalar (Text -> ByteString
encodeUtf8 Text
s) Tag
tag Style
style (Text -> [Char]
T.unpack forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe Text
anchor)
where
( Tag
tag, Style
style ) = StringStyle
stringStyle Text
s
defaultStringStyle :: StringStyle
defaultStringStyle :: StringStyle
defaultStringStyle = \Text
s ->
case () of
()
| Text
"\n" Text -> Text -> Bool
`T.isInfixOf` Text
s -> ( Tag
NoTag, Style
Literal )
| Text -> Bool
isSpecialString Text
s -> ( Tag
NoTag, Style
SingleQuoted )
| Bool
otherwise -> ( Tag
NoTag, Style
PlainNoTag )
isSpecialString :: Text -> Bool
isSpecialString :: Text -> Bool
isSpecialString Text
s = Text
s forall a. (Eq a, Hashable a) => a -> HashSet a -> Bool
`HashSet.member` HashSet Text
specialStrings Bool -> Bool -> Bool
|| Text -> Bool
isNumeric Text
s
specialStrings :: HashSet.HashSet Text
specialStrings :: HashSet Text
specialStrings = forall a. (Eq a, Hashable a) => [a] -> HashSet a
HashSet.fromList forall a b. (a -> b) -> a -> b
$ Text -> [Text]
T.words
Text
"y Y yes Yes YES n N no No NO true True TRUE false False FALSE on On ON off Off OFF null Null NULL ~ *"
isNumeric :: Text -> Bool
isNumeric :: Text -> Bool
isNumeric = forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (forall a b. a -> b -> a
const Bool
False) (forall a b. a -> b -> a
const Bool
True) forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Either [Char] Scientific
textToScientific
objToStream :: ToJSON a => StringStyle -> a -> [Y.Event]
objToStream :: forall a. ToJSON a => StringStyle -> a -> [Event]
objToStream StringStyle
stringStyle a
o =
(:) Event
EventStreamStart
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (:) Event
EventDocumentStart
forall a b. (a -> b) -> a -> b
$ forall a. ToJSON a => StringStyle -> a -> [Event] -> [Event]
objToEvents StringStyle
stringStyle a
o
[ Event
EventDocumentEnd
, Event
EventStreamEnd
]
objToEvents :: ToJSON a => StringStyle -> a -> [Y.Event] -> [Y.Event]
objToEvents :: forall a. ToJSON a => StringStyle -> a -> [Event] -> [Event]
objToEvents StringStyle
stringStyle = Value -> [Event] -> [Event]
objToEvents' forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. ToJSON a => a -> Value
toJSON
where
objToEvents' :: Value -> [Event] -> [Event]
objToEvents' (Array Array
list) [Event]
rest =
Tag -> SequenceStyle -> Anchor -> Event
EventSequenceStart Tag
NoTag SequenceStyle
AnySequence forall a. Maybe a
Nothing
forall a. a -> [a] -> [a]
: forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr Value -> [Event] -> [Event]
objToEvents' (Event
EventSequenceEnd forall a. a -> [a] -> [a]
: [Event]
rest) (forall a. Vector a -> [a]
V.toList Array
list)
objToEvents' (Object KeyMap Value
o) [Event]
rest =
Tag -> MappingStyle -> Anchor -> Event
EventMappingStart Tag
NoTag MappingStyle
AnyMapping forall a. Maybe a
Nothing
forall a. a -> [a] -> [a]
: forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr Pair -> [Event] -> [Event]
pairToEvents (Event
EventMappingEnd forall a. a -> [a] -> [a]
: [Event]
rest) (forall v. KeyMap v -> [(Key, v)]
M.toList KeyMap Value
o)
where
pairToEvents :: Pair -> [Y.Event] -> [Y.Event]
pairToEvents :: Pair -> [Event] -> [Event]
pairToEvents (Key
k, Value
v) = Value -> [Event] -> [Event]
objToEvents' (Text -> Value
String forall a b. (a -> b) -> a -> b
$ Key -> Text
toText Key
k) forall b c a. (b -> c) -> (a -> b) -> a -> c
. Value -> [Event] -> [Event]
objToEvents' Value
v
objToEvents' (String Text
s) [Event]
rest = StringStyle -> Maybe Text -> Text -> Event
stringScalar StringStyle
stringStyle forall a. Maybe a
Nothing Text
s forall a. a -> [a] -> [a]
: [Event]
rest
objToEvents' Value
Null [Event]
rest = ByteString -> Tag -> Style -> Anchor -> Event
EventScalar ByteString
"null" Tag
NullTag Style
PlainNoTag forall a. Maybe a
Nothing forall a. a -> [a] -> [a]
: [Event]
rest
objToEvents' (Bool Bool
True) [Event]
rest = ByteString -> Tag -> Style -> Anchor -> Event
EventScalar ByteString
"true" Tag
BoolTag Style
PlainNoTag forall a. Maybe a
Nothing forall a. a -> [a] -> [a]
: [Event]
rest
objToEvents' (Bool Bool
False) [Event]
rest = ByteString -> Tag -> Style -> Anchor -> Event
EventScalar ByteString
"false" Tag
BoolTag Style
PlainNoTag forall a. Maybe a
Nothing forall a. a -> [a] -> [a]
: [Event]
rest
objToEvents' (Number Scientific
s) [Event]
rest =
let builder :: Builder
builder
| Scientific -> Int
base10Exponent Scientific
s forall a. Eq a => a -> a -> Bool
== Int
0 = Integer -> Builder
BB.integerDec forall a b. (a -> b) -> a -> b
$ Scientific -> Integer
coefficient Scientific
s
| Bool
otherwise = Scientific -> Builder
scientificBuilder Scientific
s
lbs :: ByteString
lbs = Builder -> ByteString
BB.toLazyByteString Builder
builder
bs :: ByteString
bs = ByteString -> ByteString
BL.toStrict ByteString
lbs
in ByteString -> Tag -> Style -> Anchor -> Event
EventScalar ByteString
bs Tag
IntTag Style
PlainNoTag forall a. Maybe a
Nothing forall a. a -> [a] -> [a]
: [Event]
rest