{-
  Copyright (c) Meta Platforms, Inc. and affiliates.
  All rights reserved.

  This source code is licensed under the BSD-style license found in the
  LICENSE file in the root directory of this source tree.
-}

module Foreign.CPP.HsStruct.Utils
  ( withCxxObject
  , withDefaultCxxObject
  ) where


import Control.Exception (bracket)
import Foreign (Ptr)
import Foreign.CPP.Addressable
import Foreign.CPP.Marshallable

import Util.Memory

-- | allocates space for an object, calls `constructValue` with a value
-- and `destruct`s the object when done.
withCxxObject
  :: (Constructible a, Destructible a, Addressable a)
  => a
  -> (Ptr a -> IO b)
  -> IO b
withCxxObject val func =
  allocaBytesAligned (sizeOf val) (alignment val) $ \s ->
    bracket (constructValue s val >> return s) destruct func

-- | allocates space for an object, calls `constructDefault`
-- and `destruct`s the object when done.
withDefaultCxxObject
  :: forall a b . (DefaultConstructible a, Destructible a, Addressable a)
  => (Ptr a -> IO b)
  -> IO b
withDefaultCxxObject func =
  allocaBytesAligned (sizeOf val) (alignment val) $ \s ->
    bracket (constructDefault s >> return s) destruct func
  where
    val = undefined :: a