{-# LANGUAGE CPP #-}
{-# OPTIONS -Wall #-}
{-# LANGUAGE ConstrainedClassMethods #-}

-- | Internal code to convert Haskell types to raw bytes
--
--   /NOTE: This module is only used when building for the web/
module Raylib.Internal.Web.Processable (ProcessedParam (..), ParamType (..), Processable (..)) where

import Foreign (Ptr, FunPtr, Storable (poke, sizeOf), castPtr, malloc)
import Foreign.C (CChar, CDouble, CFloat, CInt, CLong, CUChar, CUInt, CBool)

data ParamType = SignedIntParam | UnsignedIntParam | FloatParam | VoidParam deriving (Int -> ParamType
ParamType -> Int
ParamType -> [ParamType]
ParamType -> ParamType
ParamType -> ParamType -> [ParamType]
ParamType -> ParamType -> ParamType -> [ParamType]
(ParamType -> ParamType)
-> (ParamType -> ParamType)
-> (Int -> ParamType)
-> (ParamType -> Int)
-> (ParamType -> [ParamType])
-> (ParamType -> ParamType -> [ParamType])
-> (ParamType -> ParamType -> [ParamType])
-> (ParamType -> ParamType -> ParamType -> [ParamType])
-> Enum ParamType
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
$csucc :: ParamType -> ParamType
succ :: ParamType -> ParamType
$cpred :: ParamType -> ParamType
pred :: ParamType -> ParamType
$ctoEnum :: Int -> ParamType
toEnum :: Int -> ParamType
$cfromEnum :: ParamType -> Int
fromEnum :: ParamType -> Int
$cenumFrom :: ParamType -> [ParamType]
enumFrom :: ParamType -> [ParamType]
$cenumFromThen :: ParamType -> ParamType -> [ParamType]
enumFromThen :: ParamType -> ParamType -> [ParamType]
$cenumFromTo :: ParamType -> ParamType -> [ParamType]
enumFromTo :: ParamType -> ParamType -> [ParamType]
$cenumFromThenTo :: ParamType -> ParamType -> ParamType -> [ParamType]
enumFromThenTo :: ParamType -> ParamType -> ParamType -> [ParamType]
Enum)

data ProcessedParam = ProcessedParam (Ptr ()) Int Int

class Processable a where
  processableType :: a -> ParamType

  processParam :: (Storable a) => a -> IO ProcessedParam
  processParam a
val = a -> ParamType -> IO ProcessedParam
forall a. Storable a => a -> ParamType -> IO ProcessedParam
processParamRaw a
val (ParamType -> IO ProcessedParam) -> ParamType -> IO ProcessedParam
forall a b. (a -> b) -> a -> b
$ a -> ParamType
forall a. Processable a => a -> ParamType
processableType a
val

instance Processable (Ptr a) where
  processableType :: Ptr a -> ParamType
processableType Ptr a
_ = ParamType
UnsignedIntParam

instance Processable (FunPtr a) where
  processableType :: FunPtr a -> ParamType
processableType FunPtr a
_ = ParamType
UnsignedIntParam

instance Processable CInt where
  processableType :: CInt -> ParamType
processableType CInt
_ = ParamType
SignedIntParam

instance Processable CUInt where
  processableType :: CUInt -> ParamType
processableType CUInt
_ = ParamType
UnsignedIntParam

instance Processable CLong where
  processableType :: CLong -> ParamType
processableType CLong
_ = ParamType
SignedIntParam

instance Processable CChar where
  processableType :: CChar -> ParamType
processableType CChar
_ = ParamType
SignedIntParam

instance Processable CUChar where
  processableType :: CUChar -> ParamType
processableType CUChar
_ = ParamType
UnsignedIntParam

instance Processable CFloat where
  processableType :: CFloat -> ParamType
processableType CFloat
_ = ParamType
FloatParam

instance Processable CDouble where
  processableType :: CDouble -> ParamType
processableType CDouble
_ = ParamType
FloatParam

instance Processable CBool where
  processableType :: CBool -> ParamType
processableType CBool
_ = ParamType
UnsignedIntParam

instance Processable () where
  processableType :: () -> ParamType
processableType ()
_ = ParamType
VoidParam

processParamRaw :: (Storable a) => a -> ParamType -> IO ProcessedParam
processParamRaw :: forall a. Storable a => a -> ParamType -> IO ProcessedParam
processParamRaw a
val ParamType
pType = do
  Ptr a
ptr <- IO (Ptr a)
forall a. Storable a => IO (Ptr a)
malloc
  Ptr a -> a -> IO ()
forall a. Storable a => Ptr a -> a -> IO ()
poke Ptr a
ptr a
val
  ProcessedParam -> IO ProcessedParam
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (ProcessedParam -> IO ProcessedParam)
-> ProcessedParam -> IO ProcessedParam
forall a b. (a -> b) -> a -> b
$ Ptr () -> Int -> Int -> ProcessedParam
ProcessedParam (Ptr a -> Ptr ()
forall a b. Ptr a -> Ptr b
castPtr Ptr a
ptr) (a -> Int
forall a. Storable a => a -> Int
sizeOf a
val) (ParamType -> Int
forall a. Enum a => a -> Int
fromEnum ParamType
pType)