{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE NamedFieldPuns #-}

module Json.Error
  ( -- * Types
    Error (..)

    -- * Encoding
  , encode
  , builderUtf8
  ) where

import Data.ByteString.Short.Internal (ShortByteString (SBS))
import Data.Bytes.Builder (Builder)
import Data.Text.Short (ShortText)
import Json.Context (Context (..))

import qualified Data.Bytes.Builder as Builder
import qualified Data.Bytes.Chunks as ByteChunks
import qualified Data.Primitive as PM
import qualified Data.Text.Short.Unsafe as TS
import qualified Json.Context as Context

-- | A single error message.
data Error = Error
  { Error -> ShortText
message :: !ShortText
  , Error -> Context
context :: !Context
  }
  deriving (Error -> Error -> Bool
(Error -> Error -> Bool) -> (Error -> Error -> Bool) -> Eq Error
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Error -> Error -> Bool
== :: Error -> Error -> Bool
$c/= :: Error -> Error -> Bool
/= :: Error -> Error -> Bool
Eq, Int -> Error -> ShowS
[Error] -> ShowS
Error -> String
(Int -> Error -> ShowS)
-> (Error -> String) -> ([Error] -> ShowS) -> Show Error
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Error -> ShowS
showsPrec :: Int -> Error -> ShowS
$cshow :: Error -> String
show :: Error -> String
$cshowList :: [Error] -> ShowS
showList :: [Error] -> ShowS
Show)

ba2st :: PM.ByteArray -> ShortText
{-# INLINE ba2st #-}
ba2st :: ByteArray -> ShortText
ba2st (PM.ByteArray ByteArray#
x) = ShortByteString -> ShortText
TS.fromShortByteStringUnsafe (ByteArray# -> ShortByteString
SBS ByteArray#
x)

encode :: Error -> ShortText
encode :: Error -> ShortText
encode Error
p = ByteArray -> ShortText
ba2st (Chunks -> ByteArray
ByteChunks.concatU (Int -> Builder -> Chunks
Builder.run Int
128 (Error -> Builder
builderUtf8 Error
p)))

builderUtf8 :: Error -> Builder
builderUtf8 :: Error -> Builder
builderUtf8 Error {ShortText
$sel:message:Error :: Error -> ShortText
message :: ShortText
message, Context
$sel:context:Error :: Error -> Context
context :: Context
context} =
  Context -> Builder
Context.builderUtf8 Context
context
    Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Char -> Char -> Builder
Builder.ascii2 Char
':' Char
' '
    Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> ShortText -> Builder
Builder.shortTextUtf8 ShortText
message