content: module Foreign.HaPy.Internal (
    sizeOfList,
    peekList,
    pokeList,
    copyList
  ) where
  
  import Foreign.C ( CInt )
  import Foreign.Marshal.Array ( pokeArray, peekArray )
  import Foreign.Marshal.Alloc ( mallocBytes )
  import Foreign.Storable ( Storable(..) )
  import Foreign.Ptr ( Ptr, plusPtr, castPtr, alignPtr )
  
  cInt :: CInt
  cInt = undefined
  
  lenPtr :: Storable a => Ptr [a] -> Ptr CInt
  lenPtr = castPtr
  
  arrPtr :: Storable a => Ptr [a] -> Ptr a
  arrPtr ptr = castPtr $ (ptr `plusPtr` sizeOf cInt) `alignPtr` alignment (ptrElem ptr)
    where ptrElem :: Ptr [a] -> a
          ptrElem = undefined
  
  sizeOfList :: Storable a => [a] -> Int
  sizeOfList xs = alignedIntSize + length xs * sizeOf (head xs)
    where alignedIntSize = max (sizeOf cInt) (alignment $ head xs)
  
  peekList :: Storable a => Ptr [a] -> IO [a]
  peekList ptr = do
    len <- peek $ lenPtr ptr
    peekArray (fromIntegral len) $ arrPtr ptr
  
  pokeList :: Storable a => Ptr [a] -> [a] -> IO ()
  pokeList ptr xs = do
    poke (lenPtr ptr) (fromIntegral $ length xs)
    pokeArray (arrPtr ptr) xs
  
  copyList :: Storable a => [a] -> IO (Ptr [a])
  copyList xs = do
    ptr <- mallocBytes $ sizeOfList xs
    pokeList ptr xs
    return ptr
  