{-# LANGUAGE UnboxedTuples #-}
module Bytezap.PokeCPS where
import GHC.Exts ( Int#, Addr#, Ptr )
import Data.Text.Internal ( Text(Text) )
import Data.Text.Array qualified as Text
import Data.Word ( Word8 )
import Data.ByteString ( ByteString )
import Data.Primitive.ByteArray ( ByteArray(ByteArray), indexByteArray )
import GHC.Storable ( writeWord8OffPtr )
import Tmp.BSExt qualified as B
type PokeCPS# r = Addr# -> Int# -> (Int# -> IO ByteString) -> IO r
newtype PokeCPS r = PokeCPS { forall r. PokeCPS r -> PokeCPS# r
unPokeCPS:: PokeCPS# r }
emptyPokeCPS :: PokeCPS ByteString
emptyPokeCPS :: PokeCPS ByteString
emptyPokeCPS = PokeCPS# ByteString -> PokeCPS ByteString
forall r. PokeCPS# r -> PokeCPS r
PokeCPS (PokeCPS# ByteString -> PokeCPS ByteString)
-> PokeCPS# ByteString -> PokeCPS ByteString
forall a b. (a -> b) -> a -> b
$ \Addr#
_base# Int#
os# Int# -> IO ByteString
finalize -> Int# -> IO ByteString
finalize Int#
os#
full
:: ByteArray -> Ptr Word8
-> (Int -> IO r) -> (Word8 -> IO r)
-> (Word8 -> IO r)
-> Int -> Int -> Int
-> IO r
full :: forall r.
ByteArray
-> Ptr Word8
-> (Int -> IO r)
-> (Word8 -> IO r)
-> (Word8 -> IO r)
-> Int
-> Int
-> Int
-> IO r
full ByteArray
bufIn Ptr Word8
bufOut Int -> IO r
fCont Word8 -> IO r
fErrEof Word8 -> IO r
fErrNotHexDigit Int
bufInMax = Int -> Int -> IO r
go
where
go :: Int -> Int -> IO r
go = \Int
bufInOs Int
bufOutOs -> do
let bufInRemaining :: Int
bufInRemaining = Int
bufInMax Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
bufInOs
if Int
bufInRemaining Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
2
then case forall a. Prim a => ByteArray -> Int -> a
indexByteArray @Word8 ByteArray
bufIn Int
bufInOs of
Word8
0x20 ->
case forall a. Prim a => ByteArray -> Int -> a
indexByteArray @Word8 ByteArray
bufIn (Int
bufInOsInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) of
Word8
0x20 ->
Int -> Int -> IO r
go (Int
bufInOsInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
2) Int
bufOutOs
Word8
d1 ->
if Int
bufInRemaining Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
3
then do let d0 :: Word8
d0 = forall a. Prim a => ByteArray -> Int -> a
indexByteArray @Word8 ByteArray
bufIn (Int
bufInOsInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
2)
(Word8 -> IO r) -> Word8 -> Word8 -> (Word8 -> IO r) -> IO r
forall r. (Word8 -> r) -> Word8 -> Word8 -> (Word8 -> r) -> r
withHexNibbles Word8 -> IO r
fErrNotHexDigit Word8
d1 Word8
d0 ((Word8 -> IO r) -> IO r) -> (Word8 -> IO r) -> IO r
forall a b. (a -> b) -> a -> b
$ \Word8
b -> do
Ptr Word8 -> Int -> Word8 -> IO ()
writeWord8OffPtr Ptr Word8
bufOut Int
bufOutOs Word8
b
Int -> Int -> IO r
go (Int
bufInOsInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
3) (Int
bufOutOsInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1)
else Word8 -> IO r
fErrEof Word8
d1
Word8
d1 -> do
let d0 :: Word8
d0 = forall a. Prim a => ByteArray -> Int -> a
indexByteArray @Word8 ByteArray
bufIn (Int
bufInOsInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1)
(Word8 -> IO r) -> Word8 -> Word8 -> (Word8 -> IO r) -> IO r
forall r. (Word8 -> r) -> Word8 -> Word8 -> (Word8 -> r) -> r
withHexNibbles Word8 -> IO r
fErrNotHexDigit Word8
d1 Word8
d0 ((Word8 -> IO r) -> IO r) -> (Word8 -> IO r) -> IO r
forall a b. (a -> b) -> a -> b
$ \Word8
b -> do
Ptr Word8 -> Int -> Word8 -> IO ()
writeWord8OffPtr Ptr Word8
bufOut Int
bufOutOs Word8
b
Int -> Int -> IO r
go (Int
bufInOsInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
2) (Int
bufOutOsInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1)
else if Int
bufInRemaining Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0
then Int -> IO r
fCont Int
bufOutOs
else
case forall a. Prim a => ByteArray -> Int -> a
indexByteArray @Word8 ByteArray
bufIn Int
bufInOs of
Word8
0x20 -> Int -> IO r
fCont Int
bufOutOs
Word8
d1 -> Word8 -> IO r
fErrEof Word8
d1
{-# INLINE full #-}
withHexNibbles ::
(Word8 -> r) -> Word8 -> Word8 -> (Word8 -> r) -> r
withHexNibbles :: forall r. (Word8 -> r) -> Word8 -> Word8 -> (Word8 -> r) -> r
withHexNibbles Word8 -> r
fFail Word8
d1 Word8
d0 Word8 -> r
fCont =
Word8 -> (Word8 -> r) -> (Word8 -> r) -> r
forall r. Word8 -> (Word8 -> r) -> (Word8 -> r) -> r
withByteAsHexDigit Word8
d1 Word8 -> r
fFail ((Word8 -> r) -> r) -> (Word8 -> r) -> r
forall a b. (a -> b) -> a -> b
$ \Word8
n1 ->
Word8 -> (Word8 -> r) -> (Word8 -> r) -> r
forall r. Word8 -> (Word8 -> r) -> (Word8 -> r) -> r
withByteAsHexDigit Word8
d0 Word8 -> r
fFail ((Word8 -> r) -> r) -> (Word8 -> r) -> r
forall a b. (a -> b) -> a -> b
$ \Word8
n0 ->
Word8 -> r
fCont (Word8 -> r) -> Word8 -> r
forall a b. (a -> b) -> a -> b
$ Word8
0x10Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
*Word8
n1 Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
+ Word8
n0
{-# INLINE withHexNibbles #-}
withByteAsHexDigit :: Word8 -> (Word8 -> r) -> (Word8 -> r) -> r
withByteAsHexDigit :: forall r. Word8 -> (Word8 -> r) -> (Word8 -> r) -> r
withByteAsHexDigit Word8
c Word8 -> r
fFail Word8 -> r
f
| Word8
dec Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
<= Word8
9 = Word8 -> r
f Word8
dec
| Word8
hexl Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
<= Word8
5 = Word8 -> r
f (Word8 -> r) -> Word8 -> r
forall a b. (a -> b) -> a -> b
$ Word8
hexl Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
+ Word8
10
| Word8
hexu Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
<= Word8
5 = Word8 -> r
f (Word8 -> r) -> Word8 -> r
forall a b. (a -> b) -> a -> b
$ Word8
hexu Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
+ Word8
10
| Bool
otherwise = Word8 -> r
fFail Word8
c
where
dec :: Word8
dec = Word8
c Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
- Word8
ord_0
hexl :: Word8
hexl = Word8
c Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
- Word8
ord_a
hexu :: Word8
hexu = Word8
c Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
- Word8
ord_A
ord_0 :: Word8
ord_0 = Word8
0x30
ord_a :: Word8
ord_a = Word8
0x61
ord_A :: Word8
ord_A = Word8
0x41
{-# INLINE withByteAsHexDigit #-}
textToByteStringUptoIO :: Text -> IO (Either String ByteString)
textToByteStringUptoIO :: Text -> IO (Either String ByteString)
textToByteStringUptoIO = \(Text (Text.ByteArray ByteArray#
tarr) Int
tos Int
tlen) ->
Int
-> (ForeignPtr Word8 -> Int -> IO (Either String ByteString))
-> ((Int -> IO (Either String ByteString))
-> Ptr Word8 -> IO (Either String ByteString))
-> IO (Either String ByteString)
forall r.
Int
-> (ForeignPtr Word8 -> Int -> IO r)
-> ((Int -> IO r) -> Ptr Word8 -> IO r)
-> IO r
B.createCPS (Int
tlen Int -> Int -> Int
forall a. Integral a => a -> a -> a
`quot` Int
2) ForeignPtr Word8 -> Int -> IO (Either String ByteString)
forall {a}. ForeignPtr Word8 -> Int -> IO (Either a ByteString)
finalizer (((Int -> IO (Either String ByteString))
-> Ptr Word8 -> IO (Either String ByteString))
-> IO (Either String ByteString))
-> ((Int -> IO (Either String ByteString))
-> Ptr Word8 -> IO (Either String ByteString))
-> IO (Either String ByteString)
forall a b. (a -> b) -> a -> b
$ \Int -> IO (Either String ByteString)
finalize Ptr Word8
buf ->
ByteArray
-> Ptr Word8
-> (Int -> IO (Either String ByteString))
-> (Word8 -> IO (Either String ByteString))
-> (Word8 -> IO (Either String ByteString))
-> Int
-> Int
-> Int
-> IO (Either String ByteString)
forall r.
ByteArray
-> Ptr Word8
-> (Int -> IO r)
-> (Word8 -> IO r)
-> (Word8 -> IO r)
-> Int
-> Int
-> Int
-> IO r
full (ByteArray# -> ByteArray
ByteArray ByteArray#
tarr) Ptr Word8
buf Int -> IO (Either String ByteString)
finalize Word8 -> IO (Either String ByteString)
forall {p} {b}. p -> IO (Either String b)
fErrEof Word8 -> IO (Either String ByteString)
forall {b}. Word8 -> IO (Either String b)
fErrNotHexDigit Int
tlen Int
tos Int
0
where
fErrNotHexDigit :: Word8 -> IO (Either String b)
fErrNotHexDigit = \Word8
b -> Either String b -> IO (Either String b)
forall a. a -> IO a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure (Either String b -> IO (Either String b))
-> Either String b -> IO (Either String b)
forall a b. (a -> b) -> a -> b
$ String -> Either String b
forall a b. a -> Either a b
Left (String
"not a hexadecimal digit: " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Word8 -> String
forall a. Show a => a -> String
show Word8
b)
finalizer :: ForeignPtr Word8 -> Int -> IO (Either a ByteString)
finalizer = \ForeignPtr Word8
fp Int
len -> ByteString -> Either a ByteString
forall a b. b -> Either a b
Right (ByteString -> Either a ByteString)
-> IO ByteString -> IO (Either a ByteString)
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> ForeignPtr Word8 -> Int -> IO ByteString
B.mkDeferredByteString ForeignPtr Word8
fp Int
len
fErrEof :: p -> IO (Either String b)
fErrEof = \p
_ -> Either String b -> IO (Either String b)
forall a. a -> IO a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure (Either String b -> IO (Either String b))
-> Either String b -> IO (Either String b)
forall a b. (a -> b) -> a -> b
$ String -> Either String b
forall a b. a -> Either a b
Left String
"ended during byte (TODO)"
{-# INLINE textToByteStringUptoIO #-}