{-# LANGUAGE FlexibleInstances   #-}
{-# LANGUAGE OverloadedStrings   #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-|
Module      : HsLua.Class.Peekable
Copyright   : © 2007–2012 Gracjan Polak;
              © 2012–2016 Ömer Sinan Ağacan;
              © 2017-2023 Albert Krewinkel
License     : MIT
Maintainer  : Albert Krewinkel <tarleb@hslua.org>
Stability   : beta
Portability : non-portable (depends on GHC)

Sending haskell objects to the lua stack.
-}
module HsLua.Class.Peekable
  ( Peekable (..)
  , peek
  ) where

import Data.Map (Map)
import Data.Set (Set)
import Data.Text (Text)
import HsLua.Core as Lua
import HsLua.Marshalling
import Foreign.Ptr (Ptr)

import qualified Data.ByteString as B
import qualified Data.ByteString.Lazy as BL
import qualified HsLua.Marshalling.Peekers as Peekers

-- | A value that can be read from the Lua stack.
class Peekable a where
  -- | Function that retrieves a value from the Lua stack.
  safepeek :: LuaError e => Peeker e a

-- | Retrieves a 'Peekable' value from the stack. Throws an exception of
-- type @e@ if the given stack index does not a suitable value.
peek :: forall a e. (LuaError e, Peekable a) => StackIndex -> LuaE e a
peek :: forall a e. (LuaError e, Peekable a) => StackIndex -> LuaE e a
peek = forall e a. LuaError e => Peek e a -> LuaE e a
forcePeek forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a e. (Peekable a, LuaError e) => Peeker e a
safepeek

instance Peekable () where
  safepeek :: forall e. LuaError e => Peeker e ()
safepeek = forall e. Peeker e ()
peekNil

instance Peekable Lua.Integer where
  safepeek :: forall e. LuaError e => Peeker e Integer
safepeek = forall e a. Name -> (StackIndex -> LuaE e (Maybe a)) -> Peeker e a
reportValueOnFailure Name
"integer" forall e. StackIndex -> LuaE e (Maybe Integer)
tointeger

instance Peekable Lua.Number where
  safepeek :: forall e. LuaError e => Peeker e Number
safepeek = forall e a. Name -> (StackIndex -> LuaE e (Maybe a)) -> Peeker e a
reportValueOnFailure Name
"number" forall e. StackIndex -> LuaE e (Maybe Number)
tonumber

instance Peekable B.ByteString where
  safepeek :: forall e. LuaError e => Peeker e ByteString
safepeek = forall e. Peeker e ByteString
peekByteString

instance Peekable Bool where
  safepeek :: forall e. LuaError e => Peeker e Bool
safepeek = forall e. Peeker e Bool
peekBool

instance Peekable CFunction where
  safepeek :: forall e. LuaError e => Peeker e CFunction
safepeek = forall e a. Name -> (StackIndex -> LuaE e (Maybe a)) -> Peeker e a
reportValueOnFailure Name
"C function" forall e. StackIndex -> LuaE e (Maybe CFunction)
tocfunction

instance Peekable (Ptr a) where
  safepeek :: forall e. LuaError e => Peeker e (Ptr a)
safepeek = forall e a. Name -> (StackIndex -> LuaE e (Maybe a)) -> Peeker e a
reportValueOnFailure Name
"userdata" forall e a. StackIndex -> LuaE e (Maybe (Ptr a))
touserdata

instance Peekable Lua.State where
  safepeek :: forall e. LuaError e => Peeker e State
safepeek = forall e a. Name -> (StackIndex -> LuaE e (Maybe a)) -> Peeker e a
reportValueOnFailure Name
"Lua state (i.e., a thread)" forall e. StackIndex -> LuaE e (Maybe State)
tothread

instance Peekable Text where
  safepeek :: forall e. LuaError e => Peeker e Text
safepeek = forall e. Peeker e Text
peekText

instance Peekable BL.ByteString where
  safepeek :: forall e. LuaError e => Peeker e ByteString
safepeek = forall e. Peeker e ByteString
peekLazyByteString

instance Peekable Prelude.Integer where
  safepeek :: forall e. LuaError e => Peeker e Integer
safepeek = forall a e. (Integral a, Read a) => Peeker e a
peekIntegral

instance Peekable Int where
  safepeek :: forall e. LuaError e => Peeker e Int
safepeek = forall a e. (Integral a, Read a) => Peeker e a
peekIntegral

instance Peekable Float where
  safepeek :: forall e. LuaError e => Peeker e Float
safepeek = forall a e. (RealFloat a, Read a) => Peeker e a
peekRealFloat

instance Peekable Double where
  safepeek :: forall e. LuaError e => Peeker e Double
safepeek = forall a e. (RealFloat a, Read a) => Peeker e a
peekRealFloat

instance {-# OVERLAPS #-} Peekable [Char] where
  safepeek :: forall e. LuaError e => Peeker e [Char]
safepeek = forall e. Peeker e [Char]
peekString

instance Peekable a => Peekable [a] where
  safepeek :: forall e. LuaError e => Peeker e [a]
safepeek = forall a e. LuaError e => Peeker e a -> Peeker e [a]
peekList forall a e. (Peekable a, LuaError e) => Peeker e a
safepeek

instance (Ord a, Peekable a, Peekable b) => Peekable (Map a b) where
  safepeek :: forall e. LuaError e => Peeker e (Map a b)
safepeek = forall e a b.
(LuaError e, Ord a) =>
Peeker e a -> Peeker e b -> Peeker e (Map a b)
peekMap forall a e. (Peekable a, LuaError e) => Peeker e a
safepeek forall a e. (Peekable a, LuaError e) => Peeker e a
safepeek

instance (Ord a, Peekable a) => Peekable (Set a) where
  safepeek :: forall e. LuaError e => Peeker e (Set a)
safepeek = forall e a. (LuaError e, Ord a) => Peeker e a -> Peeker e (Set a)
peekSet forall a e. (Peekable a, LuaError e) => Peeker e a
safepeek

--
-- Tuples
--

instance {-# OVERLAPPABLE #-}
  (Peekable a, Peekable b) =>
  Peekable (a, b)
 where
  safepeek :: forall e. LuaError e => Peeker e (a, b)
safepeek = forall e a b.
LuaError e =>
Peeker e a -> Peeker e b -> Peeker e (a, b)
peekPair forall a e. (Peekable a, LuaError e) => Peeker e a
safepeek forall a e. (Peekable a, LuaError e) => Peeker e a
safepeek

instance {-# OVERLAPPABLE #-}
  (Peekable a, Peekable b, Peekable c) =>
  Peekable (a, b, c)
 where
  safepeek :: forall e. LuaError e => Peeker e (a, b, c)
safepeek = forall e a b c.
LuaError e =>
Peeker e a -> Peeker e b -> Peeker e c -> Peeker e (a, b, c)
peekTriple forall a e. (Peekable a, LuaError e) => Peeker e a
safepeek forall a e. (Peekable a, LuaError e) => Peeker e a
safepeek forall a e. (Peekable a, LuaError e) => Peeker e a
safepeek

instance {-# OVERLAPPABLE #-}
  (Peekable a, Peekable b, Peekable c, Peekable d) =>
  Peekable (a, b, c, d)
 where
  safepeek :: forall e. LuaError e => Peeker e (a, b, c, d)
safepeek = forall e a.
Name -> (StackIndex -> LuaE e Bool) -> Peeker e a -> Peeker e a
typeChecked Name
"table" forall e. StackIndex -> LuaE e Bool
istable forall a b. (a -> b) -> a -> b
$ \StackIndex
idx ->
    (,,,) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall e a.
(LuaError e, Peekable a) =>
StackIndex -> Integer -> Peek e a
nthValue StackIndex
idx Integer
1 forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall e a.
(LuaError e, Peekable a) =>
StackIndex -> Integer -> Peek e a
nthValue StackIndex
idx Integer
2 forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall e a.
(LuaError e, Peekable a) =>
StackIndex -> Integer -> Peek e a
nthValue StackIndex
idx Integer
3
          forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall e a.
(LuaError e, Peekable a) =>
StackIndex -> Integer -> Peek e a
nthValue StackIndex
idx Integer
4

instance {-# OVERLAPPABLE #-}
  (Peekable a, Peekable b, Peekable c, Peekable d, Peekable e) =>
  Peekable (a, b, c, d, e)
 where
  safepeek :: forall e. LuaError e => Peeker e (a, b, c, d, e)
safepeek = forall e a.
Name -> (StackIndex -> LuaE e Bool) -> Peeker e a -> Peeker e a
typeChecked Name
"table" forall e. StackIndex -> LuaE e Bool
istable forall a b. (a -> b) -> a -> b
$ \StackIndex
idx ->
    (,,,,) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall e a.
(LuaError e, Peekable a) =>
StackIndex -> Integer -> Peek e a
nthValue StackIndex
idx Integer
1 forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall e a.
(LuaError e, Peekable a) =>
StackIndex -> Integer -> Peek e a
nthValue StackIndex
idx Integer
2 forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall e a.
(LuaError e, Peekable a) =>
StackIndex -> Integer -> Peek e a
nthValue StackIndex
idx Integer
3
           forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall e a.
(LuaError e, Peekable a) =>
StackIndex -> Integer -> Peek e a
nthValue StackIndex
idx Integer
4 forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall e a.
(LuaError e, Peekable a) =>
StackIndex -> Integer -> Peek e a
nthValue StackIndex
idx Integer
5

instance {-# OVERLAPPABLE #-}
  (Peekable a, Peekable b, Peekable c, Peekable d, Peekable e, Peekable f) =>
  Peekable (a, b, c, d, e, f)
 where
  safepeek :: forall e. LuaError e => Peeker e (a, b, c, d, e, f)
safepeek = forall e a.
Name -> (StackIndex -> LuaE e Bool) -> Peeker e a -> Peeker e a
typeChecked Name
"table" forall e. StackIndex -> LuaE e Bool
istable forall a b. (a -> b) -> a -> b
$ \StackIndex
idx ->
    (,,,,,) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall e a.
(LuaError e, Peekable a) =>
StackIndex -> Integer -> Peek e a
nthValue StackIndex
idx Integer
1 forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall e a.
(LuaError e, Peekable a) =>
StackIndex -> Integer -> Peek e a
nthValue StackIndex
idx Integer
2 forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall e a.
(LuaError e, Peekable a) =>
StackIndex -> Integer -> Peek e a
nthValue StackIndex
idx Integer
3
            forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall e a.
(LuaError e, Peekable a) =>
StackIndex -> Integer -> Peek e a
nthValue StackIndex
idx Integer
4 forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall e a.
(LuaError e, Peekable a) =>
StackIndex -> Integer -> Peek e a
nthValue StackIndex
idx Integer
5 forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall e a.
(LuaError e, Peekable a) =>
StackIndex -> Integer -> Peek e a
nthValue StackIndex
idx Integer
6


instance {-# OVERLAPPABLE #-}
  (Peekable a, Peekable b, Peekable c, Peekable d,
   Peekable e, Peekable f, Peekable g) =>
  Peekable (a, b, c, d, e, f, g)
 where
  safepeek :: forall e. LuaError e => Peeker e (a, b, c, d, e, f, g)
safepeek = forall e a.
Name -> (StackIndex -> LuaE e Bool) -> Peeker e a -> Peeker e a
typeChecked Name
"table" forall e. StackIndex -> LuaE e Bool
istable forall a b. (a -> b) -> a -> b
$ \StackIndex
idx ->
    (,,,,,,) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall e a.
(LuaError e, Peekable a) =>
StackIndex -> Integer -> Peek e a
nthValue StackIndex
idx Integer
1 forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall e a.
(LuaError e, Peekable a) =>
StackIndex -> Integer -> Peek e a
nthValue StackIndex
idx Integer
2 forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall e a.
(LuaError e, Peekable a) =>
StackIndex -> Integer -> Peek e a
nthValue StackIndex
idx Integer
3
             forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall e a.
(LuaError e, Peekable a) =>
StackIndex -> Integer -> Peek e a
nthValue StackIndex
idx Integer
4 forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall e a.
(LuaError e, Peekable a) =>
StackIndex -> Integer -> Peek e a
nthValue StackIndex
idx Integer
5 forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall e a.
(LuaError e, Peekable a) =>
StackIndex -> Integer -> Peek e a
nthValue StackIndex
idx Integer
6
             forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall e a.
(LuaError e, Peekable a) =>
StackIndex -> Integer -> Peek e a
nthValue StackIndex
idx Integer
7

instance {-# OVERLAPPABLE #-}
  (Peekable a, Peekable b, Peekable c, Peekable d,
   Peekable e, Peekable f, Peekable g, Peekable h) =>
  Peekable (a, b, c, d, e, f, g, h)
 where
  safepeek :: forall e. LuaError e => Peeker e (a, b, c, d, e, f, g, h)
safepeek = forall e a.
Name -> (StackIndex -> LuaE e Bool) -> Peeker e a -> Peeker e a
typeChecked Name
"table" forall e. StackIndex -> LuaE e Bool
istable forall a b. (a -> b) -> a -> b
$ \StackIndex
idx ->
    (,,,,,,,) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall e a.
(LuaError e, Peekable a) =>
StackIndex -> Integer -> Peek e a
nthValue StackIndex
idx Integer
1 forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall e a.
(LuaError e, Peekable a) =>
StackIndex -> Integer -> Peek e a
nthValue StackIndex
idx Integer
2 forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall e a.
(LuaError e, Peekable a) =>
StackIndex -> Integer -> Peek e a
nthValue StackIndex
idx Integer
3
              forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall e a.
(LuaError e, Peekable a) =>
StackIndex -> Integer -> Peek e a
nthValue StackIndex
idx Integer
4 forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall e a.
(LuaError e, Peekable a) =>
StackIndex -> Integer -> Peek e a
nthValue StackIndex
idx Integer
5 forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall e a.
(LuaError e, Peekable a) =>
StackIndex -> Integer -> Peek e a
nthValue StackIndex
idx Integer
6
              forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall e a.
(LuaError e, Peekable a) =>
StackIndex -> Integer -> Peek e a
nthValue StackIndex
idx Integer
7 forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall e a.
(LuaError e, Peekable a) =>
StackIndex -> Integer -> Peek e a
nthValue StackIndex
idx Integer
8

-- | Helper function to get the nth table value
nthValue :: (LuaError e, Peekable a)
         => StackIndex -> Lua.Integer -> Peek e a
nthValue :: forall e a.
(LuaError e, Peekable a) =>
StackIndex -> Integer -> Peek e a
nthValue StackIndex
idx Integer
n = forall e a. LuaError e => Integer -> Peeker e a -> Peeker e a
Peekers.peekIndexRaw Integer
n forall a e. (Peekable a, LuaError e) => Peeker e a
safepeek StackIndex
idx