{-# LANGUAGE FlexibleInstances     #-}
{-# LANGUAGE InstanceSigs          #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings     #-}
{-# LANGUAGE ScopedTypeVariables   #-}
{-# LANGUAGE TupleSections         #-}

module HaskellWorks.Data.Json.PartialValue
  ( JsonPartialValue(..)
  , JsonPartialValueAt(..)
  ) where

import           Control.Arrow
import qualified Data.Attoparsec.ByteString.Char8             as ABC
import qualified Data.ByteString                              as BS
import           HaskellWorks.Data.Json.Succinct.PartialIndex
import           HaskellWorks.Data.Json.Value.Internal

data JsonPartialValue
  = JsonPartialString String
  | JsonPartialNumber Double
  | JsonPartialObject [(String, JsonPartialValue)]
  | JsonPartialArray [JsonPartialValue]
  | JsonPartialBool Bool
  | JsonPartialNull
  | JsonPartialError String
  deriving (JsonPartialValue -> JsonPartialValue -> Bool
(JsonPartialValue -> JsonPartialValue -> Bool)
-> (JsonPartialValue -> JsonPartialValue -> Bool)
-> Eq JsonPartialValue
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: JsonPartialValue -> JsonPartialValue -> Bool
$c/= :: JsonPartialValue -> JsonPartialValue -> Bool
== :: JsonPartialValue -> JsonPartialValue -> Bool
$c== :: JsonPartialValue -> JsonPartialValue -> Bool
Eq, Int -> JsonPartialValue -> ShowS
[JsonPartialValue] -> ShowS
JsonPartialValue -> String
(Int -> JsonPartialValue -> ShowS)
-> (JsonPartialValue -> String)
-> ([JsonPartialValue] -> ShowS)
-> Show JsonPartialValue
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [JsonPartialValue] -> ShowS
$cshowList :: [JsonPartialValue] -> ShowS
show :: JsonPartialValue -> String
$cshow :: JsonPartialValue -> String
showsPrec :: Int -> JsonPartialValue -> ShowS
$cshowsPrec :: Int -> JsonPartialValue -> ShowS
Show)

class JsonPartialValueAt a where
  jsonPartialJsonValueAt :: a -> JsonPartialValue

asString :: JsonPartialValue -> String
asString :: JsonPartialValue -> String
asString JsonPartialValue
pjv = case JsonPartialValue
pjv of
  JsonPartialString String
s -> String
s
  JsonPartialValue
_                   -> String
""

instance JsonPartialValueAt JsonPartialIndex where
  jsonPartialJsonValueAt :: JsonPartialIndex -> JsonPartialValue
jsonPartialJsonValueAt JsonPartialIndex
i = case JsonPartialIndex
i of
    JsonPartialIndexString ByteString
s  -> case Parser String -> ByteString -> Result String
forall a. Parser a -> ByteString -> Result a
ABC.parse Parser String
forall t. (Parser t, IsString t) => Parser t String
parseJsonString ByteString
s of
      ABC.Fail    {}          -> String -> JsonPartialValue
JsonPartialError (String
"Invalid string: '" String -> ShowS
forall a. [a] -> [a] -> [a]
++ ByteString -> String
forall a. Show a => a -> String
show (Int -> ByteString -> ByteString
BS.take Int
20 ByteString
s) String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"...'")
      ABC.Partial ByteString -> Result String
_           -> String -> JsonPartialValue
JsonPartialError String
"Unexpected end of string"
      ABC.Done    ByteString
_ String
r         -> String -> JsonPartialValue
JsonPartialString String
r
    JsonPartialIndexNumber ByteString
s  -> case Parser Double -> ByteString -> Result Double
forall a. Parser a -> ByteString -> Result a
ABC.parse Parser Double
forall a. Fractional a => Parser a
ABC.rational ByteString
s of
      ABC.Fail    {}    -> String -> JsonPartialValue
JsonPartialError (String
"Invalid number: '" String -> ShowS
forall a. [a] -> [a] -> [a]
++ ByteString -> String
forall a. Show a => a -> String
show (Int -> ByteString -> ByteString
BS.take Int
20 ByteString
s) String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"...'")
      ABC.Partial ByteString -> Result Double
f     -> case ByteString -> Result Double
f ByteString
" " of
        ABC.Fail    {}    -> String -> JsonPartialValue
JsonPartialError (String
"Invalid number: '" String -> ShowS
forall a. [a] -> [a] -> [a]
++ ByteString -> String
forall a. Show a => a -> String
show (Int -> ByteString -> ByteString
BS.take Int
20 ByteString
s) String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"...'")
        ABC.Partial ByteString -> Result Double
_     -> String -> JsonPartialValue
JsonPartialError String
"Unexpected end of number"
        ABC.Done    ByteString
_ Double
r   -> Double -> JsonPartialValue
JsonPartialNumber Double
r
      ABC.Done    ByteString
_ Double
r   -> Double -> JsonPartialValue
JsonPartialNumber Double
r
    JsonPartialIndexObject  [(ByteString, JsonPartialIndex)]
fs -> [(String, JsonPartialValue)] -> JsonPartialValue
JsonPartialObject (((ByteString, JsonPartialIndex) -> (String, JsonPartialValue))
-> [(ByteString, JsonPartialIndex)] -> [(String, JsonPartialValue)]
forall a b. (a -> b) -> [a] -> [b]
map ((JsonPartialValue -> String
asString (JsonPartialValue -> String)
-> (ByteString -> JsonPartialValue) -> ByteString -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> JsonPartialValue
parseString) (ByteString -> String)
-> (JsonPartialIndex -> JsonPartialValue)
-> (ByteString, JsonPartialIndex)
-> (String, JsonPartialValue)
forall (a :: * -> * -> *) b c b' c'.
Arrow a =>
a b c -> a b' c' -> a (b, b') (c, c')
*** JsonPartialIndex -> JsonPartialValue
forall a. JsonPartialValueAt a => a -> JsonPartialValue
jsonPartialJsonValueAt) [(ByteString, JsonPartialIndex)]
fs)
    JsonPartialIndexArray   [JsonPartialIndex]
es -> [JsonPartialValue] -> JsonPartialValue
JsonPartialArray ((JsonPartialIndex -> JsonPartialValue)
-> [JsonPartialIndex] -> [JsonPartialValue]
forall a b. (a -> b) -> [a] -> [b]
map JsonPartialIndex -> JsonPartialValue
forall a. JsonPartialValueAt a => a -> JsonPartialValue
jsonPartialJsonValueAt [JsonPartialIndex]
es)
    JsonPartialIndexBool    Bool
v  -> Bool -> JsonPartialValue
JsonPartialBool Bool
v
    JsonPartialIndex
JsonPartialIndexNull       -> JsonPartialValue
JsonPartialNull
    JsonPartialIndexError String
s    -> String -> JsonPartialValue
JsonPartialError String
s
    where parseString :: ByteString -> JsonPartialValue
parseString ByteString
bs = case Parser String -> ByteString -> Result String
forall a. Parser a -> ByteString -> Result a
ABC.parse Parser String
forall t. (Parser t, IsString t) => Parser t String
parseJsonString ByteString
bs of
            ABC.Fail    {}  -> String -> JsonPartialValue
JsonPartialError (String
"Invalid field: '" String -> ShowS
forall a. [a] -> [a] -> [a]
++ ByteString -> String
forall a. Show a => a -> String
show (Int -> ByteString -> ByteString
BS.take Int
20 ByteString
bs) String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"...'")
            ABC.Partial ByteString -> Result String
_   -> String -> JsonPartialValue
JsonPartialError String
"Unexpected end of field"
            ABC.Done    ByteString
_ String
s -> String -> JsonPartialValue
JsonPartialString String
s