module Data.Yaml.Marked.Value
  ( Value (..)
  , MarkedObject
  , MarkedArray
  , valueAsJSON
  , valueToValue
  ) where

import Prelude

import Data.Aeson (FromJSON (..))
import qualified Data.Aeson as Aeson
import Data.Aeson.Compat (parseEither)
import Data.Aeson.Compat.KeyMap (KeyMap)
import Data.Scientific (Scientific)
import Data.Text (Text)
import Data.Vector (Vector)
import Data.Yaml.Marked

data Value
  = Object !MarkedObject
  | Array !MarkedArray
  | String !Text
  | Number !Scientific
  | Bool !Bool
  | Null
  deriving stock (Value -> Value -> Bool
(Value -> Value -> Bool) -> (Value -> Value -> Bool) -> Eq Value
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Value -> Value -> Bool
== :: Value -> Value -> Bool
$c/= :: Value -> Value -> Bool
/= :: Value -> Value -> Bool
Eq, Int -> Value -> ShowS
[Value] -> ShowS
Value -> String
(Int -> Value -> ShowS)
-> (Value -> String) -> ([Value] -> ShowS) -> Show Value
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Value -> ShowS
showsPrec :: Int -> Value -> ShowS
$cshow :: Value -> String
show :: Value -> String
$cshowList :: [Value] -> ShowS
showList :: [Value] -> ShowS
Show)

type MarkedObject = KeyMap (Marked Value)

type MarkedArray = Vector (Marked Value)

-- | Parse the value using its 'FromJSON', discarding any marks
valueAsJSON :: FromJSON a => Value -> Either String a
valueAsJSON :: forall a. FromJSON a => Value -> Either String a
valueAsJSON = (Value -> Parser a) -> Value -> Either String a
forall a b. (a -> Parser b) -> a -> Either String b
parseEither Value -> Parser a
forall a. FromJSON a => Value -> Parser a
parseJSON (Value -> Either String a)
-> (Value -> Value) -> Value -> Either String a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Value -> Value
valueToValue

-- | Convert a 'Value' to an equivalent 'Data.Aeson.Value'
valueToValue :: Value -> Aeson.Value
valueToValue :: Value -> Value
valueToValue = \case
  Object MarkedObject
km -> Object -> Value
Aeson.Object (Object -> Value) -> Object -> Value
forall a b. (a -> b) -> a -> b
$ Value -> Value
valueToValue (Value -> Value)
-> (Marked Value -> Value) -> Marked Value -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Marked Value -> Value
forall a. Marked a -> a
markedItem (Marked Value -> Value) -> MarkedObject -> Object
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> MarkedObject
km
  Array MarkedArray
v -> Array -> Value
Aeson.Array (Array -> Value) -> Array -> Value
forall a b. (a -> b) -> a -> b
$ Value -> Value
valueToValue (Value -> Value)
-> (Marked Value -> Value) -> Marked Value -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Marked Value -> Value
forall a. Marked a -> a
markedItem (Marked Value -> Value) -> MarkedArray -> Array
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> MarkedArray
v
  String Text
x -> Text -> Value
Aeson.String Text
x
  Number Scientific
x -> Scientific -> Value
Aeson.Number Scientific
x
  Bool Bool
x -> Bool -> Value
Aeson.Bool Bool
x
  Value
Null -> Value
Aeson.Null