module Data.Pack.ByteString
(
bytes
, bytesCopy
, bytesWhile
, bytesUntil
, cstring
, varchar
, signature
, remainingBytes
, remainingBytesCopy
) where
import Data.ByteString as B
import qualified Data.ByteString.Internal as B
import Data.Pack.Packet
import Data.Pack.Primitives (i8)
import Data.Pack.Utils (getRemaining)
import Data.Vector.Storable.Internal (getPtr)
import Foreign
bytes :: Int -> Packer ByteString
bytes n = simpleBS $ \bs -> do
let res = B.take n bs
return (B.length res, Right res)
bytesCopy :: Int -> Packer ByteString
bytesCopy n = fmap B.copy . bytes n
bytesWhile :: (Word8 -> Bool) -> Packer ByteString
bytesWhile pred = simpleBS $ \bs -> do
let res = B.takeWhile pred bs
return (B.length res, Right res)
bytesUntil :: Word8 -> Packer ByteString
bytesUntil word = simpleBS $ \bs -> do
let res = fst $ B.break (== word) bs
return (B.length res, Right res)
remainingBytes :: Packer ByteString
remainingBytes = simpleBS $ \bs ->
return (B.length bs, Right bs)
remainingBytesCopy :: Packer ByteString
remainingBytesCopy = fmap B.copy . remainingBytes
cstring :: Packer ByteString
cstring str = do
bs <- bytesUntil 0 str
i8 0
return bs
varchar :: Int -> Packer ByteString
varchar upperLimit value = flip simpleBS (pp value) $ \bs -> do
let field = B.take upperLimit bs
let str = fst $ B.break (== 0) field
return (B.length field, Right str)
where
pp v =
let b = B.take upperLimit v
in B.concat [b, B.replicate (upperLimit B.length b) 0]
signature :: ByteString -> Packet String (Maybe ByteString)
signature sig = flip simpleBS sig $ \bs -> return $
if B.isPrefixOf sig bs
then (B.length sig, Right Nothing)
else ( B.length (B.take (B.length sig) bs)
, Right $ Just (B.take (B.length sig) bs) )
simpleBS :: (ByteString -> IO (Int, Either String a)) -> ByteString -> Packet String a
simpleBS get bs = asymmPacket get put size
where
size = B.length bs
put cur = do
top <- getTop bs
B.memcpy (castPtr cur) top (fromIntegral size)