   , ifoldl'
   , blockConduit
   , unsafeBlockConduit
+  , blockSink
 
   , unDataset
   , unBand

writeBandBlock
  :: forall s a. GDALType a
  => RWBand s a -> BlockIx  -> U.Vector (Value a) -> GDAL s ()
writeBandBlock band blockIx uvec = do
  when (bandBlockLen band /= len) $
    throwBindingException (InvalidBlockSize len)
  writeMasked band write writeMask uvec
  where
    write
      | dtBand == dtBuf = writeNative
      | otherwise       = writeTranslated
    dtBand = bandDataType (band)
    dtBuf  = dataType (undefined :: a)
    len = G.length uvec
    bi  = fmap fromIntegral blockIx

    writeNative _ buf =
      liftIO $
      St.unsafeWith buf $ \pBuf ->
      checkCPLError "WriteBlock" $
      {#call WriteBlock as ^#}
        (unBand band)
        (pFst bi)
        (pSnd bi)
        (castPtr pBuf)

    writeTranslated _ buf = liftIO $
      allocaBytes (len*sizeOfDataType dtBand) $ \pWork ->
      St.unsafeWith buf $ \pBuf -> do
        {#call unsafe CopyWords as ^#}
          (castPtr pBuf)
          (fromEnumC dtBuf)
          (fromIntegral (sizeOfDataType dtBuf))
          pWork
          (fromEnumC dtBand)
          (fromIntegral (sizeOfDataType dtBand))
          (fromIntegral len)
        checkCPLError "WriteBlock" $
          {#call WriteBlock as ^#}
            (unBand band)
            (pFst bi)
            (pSnd bi)
            pWork

    bs  = fmap fromIntegral (bandBlockSize band)
    rs  = fmap fromIntegral (bandSize band)
    off = bi * bs
    win = liftA2 min bs (rs - off)

    writeMask mBand buf =
      liftIO $
      checkCPLError "WriteBlock" $
      St.unsafeWith buf $ \pBuf ->
        {#call RasterIO as ^#}
          (unBand mBand)
          (fromEnumC GF_Write)
          (pFst off)
          (pSnd off)

import Foreign.ForeignPtr (withForeignPtr, mallocForeignPtrBytes)
import Foreign.Ptr (Ptr, FunPtr, castPtr, nullPtr)
import Foreign.Storable (Storable(..))
import Foreign.Marshal.Alloc (alloca)
import Foreign.Marshal.Array (withArrayLen)
import Foreign.Marshal.Utils (toBool, fromBool, with)

