-- | Small helpers over 'Circuit.Parser.Json.Json' for the free-agent wire
-- codecs.  These are the shapes that 'Free.Agent.Acp', 'Free.Agent.Gateway',
-- and 'Free.Agent.BusStats' need; they are not a general JSON utility library.
module Free.Agent.Json
  ( -- * Lookup
    objLookup,
    arrToList,
    textAt,
    numAt,
    boolAt,
    intAt,

    -- * Construction
    jtext,
    jnum,
    jbool,
    jobject,
    jarray,

    -- * Encoding
    encodeJsonText,
  )
where

import Circuit.Parser.Json (Json (..), encodeJson)
import Data.Scientific (Scientific, toBoundedInteger, toRealFloat)
import Data.Text (Text)
import Data.Text qualified as T
import Data.Text.Encoding (decodeUtf8)
import Data.Vector qualified as V

-- | Look up a key in a JSON object.
objLookup :: Text -> Json -> Maybe Json
objLookup :: Text -> Json -> Maybe Json
objLookup Text
k (JObject [(Text, Json)]
ps) = Text -> [(Text, Json)] -> Maybe Json
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup Text
k [(Text, Json)]
ps
objLookup Text
_ Json
_ = Maybe Json
forall a. Maybe a
Nothing

-- | Convert a JSON array to a list.
arrToList :: Json -> [Json]
arrToList :: Json -> [Json]
arrToList (JArray Vector Json
v) = Vector Json -> [Json]
forall a. Vector a -> [a]
V.toList Vector Json
v
arrToList Json
_ = []

-- | Extract a text value from a JSON object field.
textAt :: Text -> Json -> Maybe Text
textAt :: Text -> Json -> Maybe Text
textAt Text
k Json
j = case Text -> Json -> Maybe Json
objLookup Text
k Json
j of
  Just (JString Text
t) -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
t
  Maybe Json
_ -> Maybe Text
forall a. Maybe a
Nothing

-- | Extract a numeric value from a JSON object field.
numAt :: Text -> Json -> Maybe Scientific
numAt :: Text -> Json -> Maybe Scientific
numAt Text
k Json
j = case Text -> Json -> Maybe Json
objLookup Text
k Json
j of
  Just (JNumber Scientific
n) -> Scientific -> Maybe Scientific
forall a. a -> Maybe a
Just Scientific
n
  Maybe Json
_ -> Maybe Scientific
forall a. Maybe a
Nothing

-- | Extract a boolean value from a JSON object field.
boolAt :: Text -> Json -> Maybe Bool
boolAt :: Text -> Json -> Maybe Bool
boolAt Text
k Json
j = case Text -> Json -> Maybe Json
objLookup Text
k Json
j of
  Just (JBool Bool
b) -> Bool -> Maybe Bool
forall a. a -> Maybe a
Just Bool
b
  Maybe Json
_ -> Maybe Bool
forall a. Maybe a
Nothing

-- | Extract a bounded integer value from a JSON object field.
intAt :: Text -> Json -> Maybe Int
intAt :: Text -> Json -> Maybe Int
intAt Text
k Json
j = Text -> Json -> Maybe Scientific
numAt Text
k Json
j Maybe Scientific -> (Scientific -> Maybe Int) -> Maybe Int
forall a b. Maybe a -> (a -> Maybe b) -> Maybe b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Scientific -> Maybe Int
forall i. (Integral i, Bounded i) => Scientific -> Maybe i
toBoundedInteger

-- | JSON string value.
jtext :: Text -> Json
jtext :: Text -> Json
jtext = Text -> Json
JString

-- | JSON number value from an integral literal.
jnum :: (Integral a) => a -> Json
jnum :: forall a. Integral a => a -> Json
jnum = Scientific -> Json
JNumber (Scientific -> Json) -> (a -> Scientific) -> a -> Json
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Scientific
forall a b. (Integral a, Num b) => a -> b
fromIntegral

-- | JSON boolean value.
jbool :: Bool -> Json
jbool :: Bool -> Json
jbool = Bool -> Json
JBool

-- | JSON object from key/value pairs.
jobject :: [(Text, Json)] -> Json
jobject :: [(Text, Json)] -> Json
jobject = [(Text, Json)] -> Json
JObject

-- | JSON array from a list.
jarray :: [Json] -> Json
jarray :: [Json] -> Json
jarray = Vector Json -> Json
JArray (Vector Json -> Json) -> ([Json] -> Vector Json) -> [Json] -> Json
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Json] -> Vector Json
forall a. [a] -> Vector a
V.fromList

-- | Render a 'Json' value to 'Text'.
encodeJsonText :: Json -> Text
encodeJsonText :: Json -> Text
encodeJsonText = ByteString -> Text
decodeUtf8 (ByteString -> Text) -> (Json -> ByteString) -> Json -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Json -> ByteString
encodeJson