{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
module HsLua.Marshalling.Userdata
( pushIterator
) where
import Control.Monad (void)
import HsLua.Core as Lua
pushIterator :: forall a e. LuaError e
=> (a -> LuaE e NumResults)
-> [a]
-> LuaE e NumResults
pushIterator :: (a -> LuaE e NumResults) -> [a] -> LuaE e NumResults
pushIterator a -> LuaE e NumResults
pushValues [a]
xs = do
LuaE e NumResults -> LuaE e ()
forall e. LuaError e => HaskellFunction e -> LuaE e ()
pushHaskellFunction LuaE e NumResults
nextItem
LuaE e ()
pushInitialState
LuaE e ()
forall e. LuaE e ()
pushnil
NumResults -> LuaE e NumResults
forall (m :: * -> *) a. Monad m => a -> m a
return (CInt -> NumResults
NumResults CInt
3)
where
nextItem :: LuaE e NumResults
nextItem :: LuaE e NumResults
nextItem = do
Maybe [a]
props <- StackIndex -> Name -> LuaE e (Maybe [a])
forall a e. StackIndex -> Name -> LuaE e (Maybe a)
fromuserdata @[a] (CInt -> StackIndex
nthBottom CInt
1) Name
statename
case Maybe [a]
props of
Maybe [a]
Nothing -> String -> LuaE e NumResults
forall e a. LuaError e => String -> LuaE e a
failLua
String
"Error in iterator: could not retrieve iterator state."
Just [] -> NumResults
2 NumResults -> LuaE e () -> LuaE e NumResults
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ (LuaE e ()
forall e. LuaE e ()
pushnil LuaE e () -> LuaE e () -> LuaE e ()
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> LuaE e ()
forall e. LuaE e ()
pushnil)
Just (a
y:[a]
ys) -> do
Bool
success <- StackIndex -> Name -> [a] -> LuaE e Bool
forall a e. StackIndex -> Name -> a -> LuaE e Bool
putuserdata @[a] (CInt -> StackIndex
nthBottom CInt
1) Name
statename [a]
ys
if Bool -> Bool
not Bool
success
then String -> LuaE e NumResults
forall e a. LuaError e => String -> LuaE e a
failLua String
"Error in iterator: could not update iterator state."
else a -> LuaE e NumResults
pushValues a
y LuaE e NumResults
-> (NumResults -> LuaE e NumResults) -> LuaE e NumResults
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
NumResults
0 -> LuaE e NumResults
nextItem
NumResults
n -> NumResults -> LuaE e NumResults
forall (m :: * -> *) a. Monad m => a -> m a
return NumResults
n
statename :: Name
statename :: Name
statename = Name
"HsLua iterator state"
pushInitialState :: LuaE e ()
pushInitialState :: LuaE e ()
pushInitialState = do
[a] -> Int -> LuaE e ()
forall a e. a -> Int -> LuaE e ()
newhsuserdatauv @[a] [a]
xs Int
0
LuaE e Bool -> LuaE e ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (Name -> LuaE e Bool
forall e. Name -> LuaE e Bool
newudmetatable Name
statename)
StackIndex -> LuaE e ()
forall e. StackIndex -> LuaE e ()
setmetatable (CInt -> StackIndex
nth CInt
2)