{-# LANGUAGE LambdaCase           #-}
{-# LANGUAGE OverloadedStrings    #-}
{-# LANGUAGE ScopedTypeVariables  #-}
{- |
   Module      : Text.Pandoc.Lua.Marshal.PandocError
   Copyright   : © 2020-2024 Albert Krewinkel
   License     : GNU GPL, version 2 or above

   Maintainer  : Albert Krewinkel <albert+pandoc@tarleb.com>
   Stability   : alpha

Marshal of @'PandocError'@ values.
-}
module Text.Pandoc.Lua.Marshal.PandocError
  ( peekPandocError
  , pushPandocError
  , typePandocError
  )
  where

import HsLua (LuaError, Peeker, Pusher, liftLua, pushText)
import HsLua.Packaging
import Text.Pandoc.Error (PandocError (PandocLuaError), renderError)

import qualified HsLua as Lua
import qualified HsLua.Core.Utf8 as UTF8

-- | Lua userdata type definition for PandocError.
typePandocError :: LuaError e => DocumentedType e PandocError
typePandocError :: forall e. LuaError e => DocumentedType e PandocError
typePandocError = Name
-> [(Operation, DocumentedFunction e)]
-> [Member e (DocumentedFunction e) PandocError]
-> DocumentedType e PandocError
forall e a.
LuaError e =>
Name
-> [(Operation, DocumentedFunction e)]
-> [Member e (DocumentedFunction e) a]
-> DocumentedType e a
deftype Name
"PandocError"
  [ Operation
-> DocumentedFunction e -> (Operation, DocumentedFunction e)
forall e.
Operation
-> DocumentedFunction e -> (Operation, DocumentedFunction e)
operation Operation
Tostring (DocumentedFunction e -> (Operation, DocumentedFunction e))
-> DocumentedFunction e -> (Operation, DocumentedFunction e)
forall a b. (a -> b) -> a -> b
$ Name
-> (PandocError -> LuaE e Text)
-> HsFnPrecursor e (PandocError -> LuaE e Text)
forall a e. Name -> a -> HsFnPrecursor e a
defun Name
"__tostring"
    ### liftPure (\case
                     PandocLuaError e -> e
                     err              -> renderError err)
    HsFnPrecursor e (PandocError -> LuaE e Text)
-> Parameter e PandocError -> HsFnPrecursor e (LuaE e Text)
forall e a b.
HsFnPrecursor e (a -> b) -> Parameter e a -> HsFnPrecursor e b
<#> DocumentedType e PandocError
-> Text -> Text -> Parameter e PandocError
forall e a itemtype.
LuaError e =>
DocumentedTypeWithList e a itemtype
-> Text -> Text -> Parameter e a
udparam DocumentedType e PandocError
forall e. LuaError e => DocumentedType e PandocError
typePandocError Text
"obj" Text
"PandocError object"
    HsFnPrecursor e (LuaE e Text)
-> FunctionResults e Text -> DocumentedFunction e
forall e a.
HsFnPrecursor e (LuaE e a)
-> FunctionResults e a -> DocumentedFunction e
=#> Pusher e Text -> TypeSpec -> Text -> FunctionResults e Text
forall e a. Pusher e a -> TypeSpec -> Text -> FunctionResults e a
functionResult Pusher e Text
forall e. Pusher e Text
pushText TypeSpec
"string" Text
"string representation of error."
  ]
  [Member e (DocumentedFunction e) PandocError]
forall a. Monoid a => a
mempty -- no members

-- | Peek a @'PandocError'@ element to the Lua stack.
pushPandocError :: LuaError e => Pusher e PandocError
pushPandocError :: forall e. LuaError e => Pusher e PandocError
pushPandocError = DocumentedTypeWithList e PandocError Void
-> PandocError -> LuaE e ()
forall e a itemtype.
LuaError e =>
DocumentedTypeWithList e a itemtype -> a -> LuaE e ()
pushUD DocumentedTypeWithList e PandocError Void
forall e. LuaError e => DocumentedType e PandocError
typePandocError

-- | Retrieve a @'PandocError'@ from the Lua stack.
peekPandocError :: LuaError e => Peeker e PandocError
peekPandocError :: forall e. LuaError e => Peeker e PandocError
peekPandocError StackIndex
idx = Name -> Peek e PandocError -> Peek e PandocError
forall e a. Name -> Peek e a -> Peek e a
Lua.retrieving Name
"PandocError" (Peek e PandocError -> Peek e PandocError)
-> Peek e PandocError -> Peek e PandocError
forall a b. (a -> b) -> a -> b
$
  LuaE e Type -> Peek e Type
forall e a. LuaE e a -> Peek e a
liftLua (StackIndex -> LuaE e Type
forall e. StackIndex -> LuaE e Type
Lua.ltype StackIndex
idx) Peek e Type -> (Type -> Peek e PandocError) -> Peek e PandocError
forall a b. Peek e a -> (a -> Peek e b) -> Peek e b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
    Type
Lua.TypeUserdata -> DocumentedTypeWithList e PandocError Void -> Peeker e PandocError
forall e a itemtype.
LuaError e =>
DocumentedTypeWithList e a itemtype -> Peeker e a
peekUD DocumentedTypeWithList e PandocError Void
forall e. LuaError e => DocumentedType e PandocError
typePandocError StackIndex
idx
    Type
_ -> do
      msg <- LuaE e ByteString -> Peek e ByteString
forall e a. LuaE e a -> Peek e a
liftLua (LuaE e ByteString -> Peek e ByteString)
-> LuaE e ByteString -> Peek e ByteString
forall a b. (a -> b) -> a -> b
$ do
        StackIndex -> LuaE e ()
forall e. StackIndex -> LuaE e ()
Lua.pushvalue StackIndex
idx
        LuaE e State
forall e. LuaE e State
Lua.state LuaE e State -> (State -> LuaE e ByteString) -> LuaE e ByteString
forall a b. LuaE e a -> (a -> LuaE e b) -> LuaE e b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \State
l -> IO ByteString -> LuaE e ByteString
forall a. IO a -> LuaE e a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
Lua.liftIO (State -> IO ByteString
Lua.popErrorMessage State
l)
      return $ PandocLuaError (UTF8.toText msg)