module Data.Hermes.SIMDJSON.Wrapper
( getDocumentInfo
, mkSIMDParser
, mkSIMDDocument
, mkSIMDPaddedStr
, withInputBuffer
)
where
import Control.Monad.IO.Class (liftIO)
import Data.ByteString (ByteString)
import qualified Data.ByteString.Unsafe as Unsafe
import Data.Maybe (fromMaybe)
import Data.Text (Text)
import qualified Data.Text as T
import UnliftIO.Exception (bracket, mask_)
import UnliftIO.Foreign
( ForeignPtr
, alloca
, allocaBytes
, finalizeForeignPtr
, newForeignPtr
, peek
, peekCString
, peekCStringLen
, withForeignPtr
)
import Data.Hermes.SIMDJSON.Bindings
( currentLocationImpl
, deleteDocumentImpl
, deleteInputImpl
, makeDocumentImpl
, makeInputImpl
, parserDestroy
, parserInit
, toDebugStringImpl
)
import Data.Hermes.SIMDJSON.Types
( Document
, InputBuffer(..)
, PaddedString
, SIMDDocument
, SIMDErrorCode(..)
, SIMDParser
)
mkSIMDParser :: Maybe Int -> IO (ForeignPtr SIMDParser)
mkSIMDParser :: Maybe Int -> IO (ForeignPtr SIMDParser)
mkSIMDParser Maybe Int
mCap = forall (m :: * -> *) a. MonadUnliftIO m => m a -> m a
mask_ forall a b. (a -> b) -> a -> b
$ do
let maxCap :: Int
maxCap = Int
4000000000;
Ptr SIMDParser
ptr <- CSize -> IO (Ptr SIMDParser)
parserInit forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Enum a => Int -> a
toEnum forall a b. (a -> b) -> a -> b
$ forall a. a -> Maybe a -> a
fromMaybe Int
maxCap Maybe Int
mCap
forall (m :: * -> *) a.
MonadIO m =>
FinalizerPtr a -> Ptr a -> m (ForeignPtr a)
newForeignPtr FunPtr (Ptr SIMDParser -> IO ())
parserDestroy Ptr SIMDParser
ptr
mkSIMDDocument :: IO (ForeignPtr SIMDDocument)
mkSIMDDocument :: IO (ForeignPtr SIMDDocument)
mkSIMDDocument = forall (m :: * -> *) a. MonadUnliftIO m => m a -> m a
mask_ forall a b. (a -> b) -> a -> b
$ do
Ptr SIMDDocument
ptr <- IO (Ptr SIMDDocument)
makeDocumentImpl
forall (m :: * -> *) a.
MonadIO m =>
FinalizerPtr a -> Ptr a -> m (ForeignPtr a)
newForeignPtr FunPtr (Ptr SIMDDocument -> IO ())
deleteDocumentImpl Ptr SIMDDocument
ptr
mkSIMDPaddedStr :: ByteString -> IO (ForeignPtr PaddedString)
mkSIMDPaddedStr :: ByteString -> IO (ForeignPtr PaddedString)
mkSIMDPaddedStr ByteString
input = forall (m :: * -> *) a. MonadUnliftIO m => m a -> m a
mask_ forall a b. (a -> b) -> a -> b
$
forall a. ByteString -> (CStringLen -> IO a) -> IO a
Unsafe.unsafeUseAsCStringLen ByteString
input forall a b. (a -> b) -> a -> b
$ \(CString
cstr, Int
len) -> do
Ptr PaddedString
ptr <- CString -> CSize -> IO (Ptr PaddedString)
makeInputImpl CString
cstr (forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len)
forall (m :: * -> *) a.
MonadIO m =>
FinalizerPtr a -> Ptr a -> m (ForeignPtr a)
newForeignPtr FunPtr (Ptr PaddedString -> IO ())
deleteInputImpl Ptr PaddedString
ptr
withInputBuffer :: ByteString -> (InputBuffer -> IO a) -> IO a
withInputBuffer :: forall a. ByteString -> (InputBuffer -> IO a) -> IO a
withInputBuffer ByteString
bs InputBuffer -> IO a
f =
forall (m :: * -> *) a b c.
MonadUnliftIO m =>
m a -> (a -> m b) -> (a -> m c) -> m c
bracket IO (ForeignPtr PaddedString)
acquire forall {a}. ForeignPtr a -> IO ()
release forall a b. (a -> b) -> a -> b
$ \ForeignPtr PaddedString
fPtr -> forall (m :: * -> *) a b.
MonadUnliftIO m =>
ForeignPtr a -> (Ptr a -> m b) -> m b
withForeignPtr ForeignPtr PaddedString
fPtr forall a b. (a -> b) -> a -> b
$ InputBuffer -> IO a
f forall b c a. (b -> c) -> (a -> b) -> a -> c
. Ptr PaddedString -> InputBuffer
InputBuffer
where
acquire :: IO (ForeignPtr PaddedString)
acquire = forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ ByteString -> IO (ForeignPtr PaddedString)
mkSIMDPaddedStr ByteString
bs
release :: ForeignPtr a -> IO ()
release = forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (m :: * -> *) a. MonadIO m => ForeignPtr a -> m ()
finalizeForeignPtr
getDocumentInfo :: Document -> IO (Text, Text)
getDocumentInfo :: Document -> IO (Text, Text)
getDocumentInfo Document
docPtr = forall (m :: * -> *) a b.
(MonadUnliftIO m, Storable a) =>
(Ptr a -> m b) -> m b
alloca forall a b. (a -> b) -> a -> b
$ \Ptr CString
locStrPtr -> forall (m :: * -> *) a b.
(MonadUnliftIO m, Storable a) =>
(Ptr a -> m b) -> m b
alloca forall a b. (a -> b) -> a -> b
$ \Ptr CSize
lenPtr -> do
CInt
err <- forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ Document -> Ptr CString -> IO CInt
currentLocationImpl Document
docPtr Ptr CString
locStrPtr
let errCode :: SIMDErrorCode
errCode = forall a. Enum a => Int -> a
toEnum forall a b. (a -> b) -> a -> b
$ forall a b. (Integral a, Num b) => a -> b
fromIntegral CInt
err
if SIMDErrorCode
errCode forall a. Eq a => a -> a -> Bool
== SIMDErrorCode
OUT_OF_BOUNDS
then forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text
"out of bounds", Text
"")
else forall (m :: * -> *) a b.
MonadUnliftIO m =>
Int -> (Ptr a -> m b) -> m b
allocaBytes Int
128 forall a b. (a -> b) -> a -> b
$ \CString
dbStrPtr -> do
Text
locStr <- forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap String -> Text
T.pack forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *). MonadIO m => CString -> m String
peekCString forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall a. Storable a => Ptr a -> IO a
peek Ptr CString
locStrPtr
Document -> CString -> Ptr CSize -> IO ()
toDebugStringImpl Document
docPtr CString
dbStrPtr Ptr CSize
lenPtr
Int
len <- forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ forall a. Storable a => Ptr a -> IO a
peek Ptr CSize
lenPtr
Text
debugStr <- forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap String -> Text
T.pack forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *). MonadIO m => CStringLen -> m String
peekCStringLen (CString
dbStrPtr, Int
len)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text
locStr, Text
debugStr)