module Text.Pandoc.Lua.Marshaling.MediaBag (pushIterator) where
import Foreign.Ptr (Ptr)
import Foreign.StablePtr (StablePtr, deRefStablePtr, newStablePtr)
import Foreign.Lua (Lua, NumResults, Peekable, Pushable, StackIndex)
import Foreign.Lua.Types.Peekable (reportValueOnFailure)
import Foreign.Lua.Userdata (ensureUserdataMetatable, pushAnyWithMetatable,
toAnyWithName)
import Text.Pandoc.MediaBag (MediaBag, mediaItems)
import Text.Pandoc.MIME (MimeType)
import Text.Pandoc.Lua.Marshaling.AnyValue (AnyValue (..))
import qualified Data.ByteString.Lazy as BL
import qualified Foreign.Lua as Lua
import qualified Foreign.Storable as Storable
newtype MediaItems = MediaItems [(String, MimeType, BL.ByteString)]
instance Pushable MediaItems where
push = pushMediaItems
instance Peekable MediaItems where
peek = peekMediaItems
pushIterator :: MediaBag -> Lua NumResults
pushIterator mb = do
Lua.pushHaskellFunction nextItem
Lua.push (MediaItems $ mediaItems mb)
Lua.pushnil
return 3
mediaItemsTypeName :: String
mediaItemsTypeName = "pandoc MediaItems"
pushMediaItems :: MediaItems -> Lua ()
pushMediaItems xs = pushAnyWithMetatable pushMT xs
where
pushMT = ensureUserdataMetatable mediaItemsTypeName (return ())
peekMediaItems :: StackIndex -> Lua MediaItems
peekMediaItems = reportValueOnFailure mediaItemsTypeName
(`toAnyWithName` mediaItemsTypeName)
nextItem :: Ptr (StablePtr MediaItems) -> AnyValue -> Lua NumResults
nextItem ptr _ = do
(MediaItems items) <- Lua.liftIO $ deRefStablePtr =<< Storable.peek ptr
case items of
[] -> 2 <$ (Lua.pushnil *> Lua.pushnil)
(key, mt, content):xs -> do
Lua.liftIO $ Storable.poke ptr =<< newStablePtr (MediaItems xs)
Lua.push key
Lua.push mt
Lua.push content
return 3