-- TODO automate this sort of high level wrapper boilerplate -- or look at upstream plans: https://github.com/well-typed/hs-bindgen/issues?q=state%3Aopen%20label%3A%22highlevel%22 module GarnetRs.Wrapped ( T (..), Shape (..), hello, helloStruct, helloShape, add, ) where import Data.ByteString import Data.Word import Foreign import Foreign.C import GarnetRs qualified as Raw import GarnetRs.Safe qualified as Raw import HsBindgen.Runtime.PtrConst import Unsafe.Coerce data T = T { a :: Bool , b :: Word8 } convertT :: T -> Raw.T convertT T{a, b} = Raw.T{a = CBool $ fromBool a, b} data Shape = Circle CDouble | Rectangle CDouble CDouble convertShape :: Shape -> Raw.Shape convertShape = \case Circle r -> Raw.Shape (Raw.Shape_Tag 0) $ Raw.set_shape_body_circle $ Raw.Circle_Body r Rectangle w h -> Raw.Shape (Raw.Shape_Tag 1) $ Raw.set_shape_body_rectangle $ Raw.Rectangle_Body w h hello :: ByteString -> IO () hello s = useAsCString s $ Raw.hello . unsafeFromPtr helloStruct :: T -> IO () helloStruct = Raw.hello_struct . convertT helloShape :: Shape -> IO () helloShape = Raw.hello_shape . convertShape add :: Int -> Int -> IO Int add a b = from <$> Raw.add (to a) (to b) where -- these types should be the same in practice - both are pointer-sized to = unsafeCoerce @Int @CIntPtr from = unsafeCoerce @CIntPtr @Int