module Bindings.Utils (
  cast666,
 ) where
import Foreign

-- | This is safe regarding use of memory. Enough space is
-- allocated to store both values, and the difference between
-- sizes, if any, is filled with zeros. The result is what you
-- would expect if you have a C pointer to the first value and
-- cast it to a pointer to the result. Of course, this can have
-- undesired effects if 'peek' implementation for
-- the result type does more than just reading memory.
--
-- This function can be safely used with any datatype generated by
-- this package macro library.

cast666 :: (Storable a, Storable b) => a -> b
cast666 = unsafePerformIO . genericCast
  where
    genericCast :: (Storable a, Storable b) => a -> IO b
    genericCast v = return undefined >>= \r ->
      let size = max (sizeOf v) (sizeOf r) in
        allocaBytes size $ \p ->
          pokeArray p (replicate size (0::Word8)) >>
            poke (castPtr p) v >>
              if False then return r else peek (castPtr p)