packages feed

bytestring-ft-0.1.0.0: src/Data/ByteString/FingerTree/CString.hs

{-# LANGUAGE ImportQualifiedPost #-}
{-# LANGUAGE BlockArguments, LambdaCase, OverloadedStrings #-}
{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}

module Data.ByteString.FingerTree.CString (peek, poke) where

import Foreign.Ptr
import Foreign.Marshal.Utils
import Foreign.C.String
import Data.ByteString qualified as BS
import Data.ByteString.FingerTree as BSF

pokeByteString :: CStringLen -> BS.ByteString -> IO (CStringLen, BS.ByteString)
pokeByteString (p, n) bs
	| n >= n' = do
		BS.useAsCStringLen bs \(p', _) -> copyBytes p p' n'
		pure ((plusPtr p n', n - n'), "")
	| otherwise = let (t, d) = BS.splitAt n bs in do
		BS.useAsCStringLen t \(p', _) -> copyBytes p p' n
		pure ((plusPtr p n, 0), d)
	where
	n' = BS.length bs

poke :: CStringLen -> BSF.ByteString ->
	IO (CStringLen, Either CStringLen BSF.ByteString)
poke c@(p, n) bsf
	| n >= n' = ((p, n'), Left (plusPtr p n', n - n')) <$ go c bsf
	| otherwise = case BSF.splitAt' n bsf of
		Nothing -> error "never occur"
		Just (t, d) -> (c, Right d) <$ go c t
	where
	go csl = \case
		Empty -> pure ()
		bs BSF.:<| bss -> do
			(csl', "") <- pokeByteString csl bs
			go csl' bss
	n' = BSF.length bsf

peek :: CStringLen -> IO BSF.ByteString
peek csl = (BSF.:<| BSF.Empty) <$> BS.packCStringLen csl