    {-# 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)