Restructure NAR streaming to remove one pointer indirection (#2)
We can pass the two fields directly via the FFI instead of bundling them in a `String_` struct
This commit is contained in:
committed by
GitHub
parent
0242d8bebb
commit
4ac870a142
@@ -161,7 +161,7 @@ void signString
|
|||||||
|
|
||||||
bool dumpPath
|
bool dumpPath
|
||||||
( char const * const hashPart
|
( char const * const hashPart
|
||||||
, bool (* const callback)(struct string const * const)
|
, bool (* const callback)(char const * const data, size_t const size)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
ref<Store> store = getStore();
|
ref<Store> store = getStore();
|
||||||
@@ -171,9 +171,7 @@ bool dumpPath
|
|||||||
|
|
||||||
if (storePath.has_value()) {
|
if (storePath.has_value()) {
|
||||||
LambdaSink sink([=](std::string_view v) {
|
LambdaSink sink([=](std::string_view v) {
|
||||||
struct string s = { .data = v.data(), .size = v.size() };
|
bool succeeded = (*callback)(v.data(), v.size());
|
||||||
|
|
||||||
bool succeeded = (*callback)(&s);
|
|
||||||
|
|
||||||
if (!succeeded) {
|
if (!succeeded) {
|
||||||
// We don't really care about the error message. The only
|
// We don't really care about the error message. The only
|
||||||
|
|||||||
34
src/Nix.hsc
34
src/Nix.hsc
@@ -18,7 +18,7 @@ import Data.ByteString.Builder (Builder)
|
|||||||
import Data.Vector (Vector)
|
import Data.Vector (Vector)
|
||||||
import Data.Word (Word64)
|
import Data.Word (Word64)
|
||||||
import Foreign (FunPtr, Ptr, Storable(..))
|
import Foreign (FunPtr, Ptr, Storable(..))
|
||||||
import Foreign.C (CChar, CLong, CSize, CString)
|
import Foreign.C (CChar, CLong, CSize(..), CString)
|
||||||
|
|
||||||
import qualified Control.Exception as Exception
|
import qualified Control.Exception as Exception
|
||||||
import qualified Control.Monad as Monad
|
import qualified Control.Monad as Monad
|
||||||
@@ -271,25 +271,41 @@ signString secretKey fingerprint =
|
|||||||
fromString_ string_
|
fromString_ string_
|
||||||
|
|
||||||
foreign import ccall "dumpPath" dumpPath_
|
foreign import ccall "dumpPath" dumpPath_
|
||||||
:: CString -> FunPtr (Ptr String_ -> IO Bool) -> IO Bool
|
:: CString -> FunPtr (Ptr CChar -> CSize -> IO Bool) -> IO Bool
|
||||||
|
|
||||||
dumpPath :: ByteString -> (Builder -> IO ()) -> IO (Either SomeException ())
|
dumpPath :: ByteString -> (Builder -> IO ()) -> IO (Either SomeException ())
|
||||||
dumpPath hashPart builderCallback = do
|
dumpPath hashPart builderCallback = do
|
||||||
result <- IORef.newIORef (Right ())
|
result <- IORef.newIORef (Right ())
|
||||||
|
|
||||||
let cCallback :: Ptr String_ -> IO Bool
|
let cCallback :: Ptr CChar -> CSize -> IO Bool
|
||||||
cCallback pointer = do
|
cCallback pointer cSize = do
|
||||||
string_ <- Foreign.peek pointer
|
|
||||||
|
|
||||||
byteString <- fromString_ string_
|
|
||||||
|
|
||||||
let handler :: SomeException -> IO Bool
|
let handler :: SomeException -> IO Bool
|
||||||
handler exception = do
|
handler exception = do
|
||||||
IORef.writeIORef result (Left exception)
|
IORef.writeIORef result (Left exception)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
Exception.handle handler do
|
Exception.handle handler do
|
||||||
|
-- At the time of this writing Nix uses a maximum chunk size of
|
||||||
|
-- 64 kibibytes, which could potentially increase in the future.
|
||||||
|
-- However:
|
||||||
|
--
|
||||||
|
-- • Data.Int.Int guarantees `maxBound :: Int` supports at least
|
||||||
|
-- 128 mebibytes
|
||||||
|
-- • The latest version of GHC sets `maxBound :: Int` to
|
||||||
|
-- support at least 2 gibibytes
|
||||||
|
-- • On 64-bit systems (almost all systems nowadays)
|
||||||
|
-- `maxBound :: Int` supports 8 exbibytes
|
||||||
|
--
|
||||||
|
-- … so even though this conversion could potentially overflow,
|
||||||
|
-- it's unlikely to happen (and it's not even clear what we
|
||||||
|
-- would do to fix the overflow anyway since the `bytestring`
|
||||||
|
-- package requires an `Int` size).
|
||||||
|
let len = fromIntegral @CSize @Int cSize
|
||||||
|
|
||||||
|
byteString <- ByteString.packCStringLen (pointer, len)
|
||||||
|
|
||||||
builderCallback (Builder.byteString byteString)
|
builderCallback (Builder.byteString byteString)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
wrappedCCallback <- wrapCallback cCallback
|
wrappedCCallback <- wrapCallback cCallback
|
||||||
@@ -318,4 +334,4 @@ dumpLog baseName = do
|
|||||||
else fmap Just (fromString_ string_)
|
else fmap Just (fromString_ string_)
|
||||||
|
|
||||||
foreign import ccall "wrapper" wrapCallback
|
foreign import ccall "wrapper" wrapCallback
|
||||||
:: (Ptr String_ -> IO Bool) -> IO (FunPtr (Ptr String_ -> IO Bool))
|
:: (Ptr CChar -> CSize -> IO Bool) -> IO (FunPtr (Ptr CChar -> CSize -> IO Bool))
|
||||||
|
|||||||
Reference in New Issue
Block a user