diff --git a/src/libstore/binary-cache-store.cc b/src/libstore/binary-cache-store.cc index d33139092..f572b0a41 100644 --- a/src/libstore/binary-cache-store.cc +++ b/src/libstore/binary-cache-store.cc @@ -416,7 +416,7 @@ StorePath BinaryCacheStore::addToStore( if (method == FileIngestionMethod::Recursive) { sink << dumpPath(srcPath, filter); } else { - readFile(srcPath, sink); + sink << readFileSource(srcPath); } auto h = sink.finish().first; diff --git a/src/libstore/build/local-derivation-goal.cc b/src/libstore/build/local-derivation-goal.cc index 37c8a7708..be82fd028 100644 --- a/src/libstore/build/local-derivation-goal.cc +++ b/src/libstore/build/local-derivation-goal.cc @@ -2454,7 +2454,7 @@ SingleDrvOutputs LocalDerivationGoal::registerOutputs() HashModuloSink caSink { outputHash.hashType, oldHashPart }; std::visit(overloaded { [&](const TextIngestionMethod &) { - readFile(actualPath, caSink); + caSink << readFileSource(actualPath); }, [&](const FileIngestionMethod & m2) { switch (m2) { @@ -2462,7 +2462,7 @@ SingleDrvOutputs LocalDerivationGoal::registerOutputs() caSink << dumpPath(actualPath); break; case FileIngestionMethod::Flat: - readFile(actualPath, caSink); + caSink << readFileSource(actualPath); break; } }, diff --git a/src/libstore/local-binary-cache-store.cc b/src/libstore/local-binary-cache-store.cc index 5684dcd80..5ba5bd802 100644 --- a/src/libstore/local-binary-cache-store.cc +++ b/src/libstore/local-binary-cache-store.cc @@ -71,7 +71,7 @@ protected: void getFile(const std::string & path, Sink & sink) override { try { - readFile(binaryCacheDir + "/" + path, sink); + sink << readFileSource(binaryCacheDir + "/" + path); } catch (SysError & e) { if (e.errNo == ENOENT) throw NoSuchBinaryCacheFile("file '%s' does not exist in binary cache", path); diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index 9c86a6b88..9d170d581 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -1886,7 +1886,7 @@ ContentAddress LocalStore::hashCAPath( HashModuloSink caSink ( hashType, std::string(pathHash) ); std::visit(overloaded { [&](const TextIngestionMethod &) { - readFile(path, caSink); + caSink << readFileSource(path); }, [&](const FileIngestionMethod & m2) { switch (m2) { @@ -1894,7 +1894,7 @@ ContentAddress LocalStore::hashCAPath( caSink << dumpPath(path); break; case FileIngestionMethod::Flat: - readFile(path, caSink); + caSink << readFileSource(path); break; } }, diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc index e1575deb3..bb32b1534 100644 --- a/src/libstore/store-api.cc +++ b/src/libstore/store-api.cc @@ -271,13 +271,12 @@ StorePath Store::addToStore( const StorePathSet & references) { Path srcPath(absPath(_srcPath)); - auto source = sinkToSource([&](Sink & sink) { - if (method == FileIngestionMethod::Recursive) - sink << dumpPath(srcPath, filter); - else - readFile(srcPath, sink); - }); - return addToStoreFromDump(*source, name, method, hashAlgo, repair, references); + auto source = WireSource{ + method == FileIngestionMethod::Recursive + ? static_cast, void>>(dumpPath(srcPath, filter)) + : readFileSource(srcPath) + }; + return addToStoreFromDump(source, name, method, hashAlgo, repair, references); } void Store::addMultipleToStore( diff --git a/src/libutil/generator.hh b/src/libutil/generator.hh index ff524fe5d..d57de3fd3 100644 --- a/src/libutil/generator.hh +++ b/src/libutil/generator.hh @@ -10,29 +10,40 @@ namespace nix { template -struct Generator : private Generator +struct Generator { struct promise_type; using handle_type = std::coroutine_handle; - explicit Generator(handle_type h) : Generator{h, h.promise().state} {} + explicit Generator(handle_type h) : impl{h, h.promise().state} {} - using Generator::operator bool; - using Generator::operator(); + explicit operator bool() + { + return bool(impl); + } + T operator()() + { + return impl(); + } operator Generator &() & { - return *this; + return impl; } operator Generator() && { - return std::move(*this); + return std::move(impl); } + +private: + Generator impl; }; template struct Generator { + template + friend struct Generator; template friend struct Generator::promise_type; diff --git a/src/libutil/hash.cc b/src/libutil/hash.cc index 5dedbc221..5c268af20 100644 --- a/src/libutil/hash.cc +++ b/src/libutil/hash.cc @@ -325,7 +325,7 @@ Hash hashString(HashType ht, std::string_view s) Hash hashFile(HashType ht, const Path & path) { HashSink sink(ht); - readFile(path, sink); + sink << readFileSource(path); return sink.finish().first; } diff --git a/src/libutil/serialise.hh b/src/libutil/serialise.hh index 3116ca742..f175bc258 100644 --- a/src/libutil/serialise.hh +++ b/src/libutil/serialise.hh @@ -388,7 +388,8 @@ void drainGenerator(Generator, T> g, std::derived_from + explicit WireSource(Generator, F> g) : g(std::move(g)) {} virtual size_t read(char * data, size_t len) { @@ -406,7 +407,7 @@ struct WireSource : Source } private: - WireFormatGenerator g; + Generator, void> g; std::span buf{}; }; diff --git a/src/libutil/util.cc b/src/libutil/util.cc index b46716511..822bfe9dc 100644 --- a/src/libutil/util.cc +++ b/src/libutil/util.cc @@ -366,12 +366,12 @@ std::string readFile(const Path & path) } -void readFile(const Path & path, Sink & sink) +Generator> readFileSource(const Path & path) { AutoCloseFD fd{open(path.c_str(), O_RDONLY | O_CLOEXEC)}; if (!fd) throw SysError("opening file '%s'", path); - drainGenerator(drainFDSource(fd.get()), sink); + co_yield drainFDSource(fd.get()); } diff --git a/src/libutil/util.hh b/src/libutil/util.hh index a7db52421..351561cdf 100644 --- a/src/libutil/util.hh +++ b/src/libutil/util.hh @@ -163,7 +163,7 @@ unsigned char getFileType(const Path & path); */ std::string readFile(int fd); std::string readFile(const Path & path); -void readFile(const Path & path, Sink & sink); +Generator> readFileSource(const Path & path); /** * Write a string to a file. diff --git a/src/nix/add-to-store.cc b/src/nix/add-to-store.cc index c92e24fb8..7e16e12c3 100644 --- a/src/nix/add-to-store.cc +++ b/src/nix/add-to-store.cc @@ -37,7 +37,7 @@ struct CmdAddToStore : MixDryRun, StoreCommand Hash hash = narHash; if (ingestionMethod == FileIngestionMethod::Flat) { HashSink hsink(htSHA256); - readFile(path, hsink); + hsink << readFileSource(path); hash = hsink.finish().first; } diff --git a/src/nix/hash.cc b/src/nix/hash.cc index 6872dbd61..d9079d551 100644 --- a/src/nix/hash.cc +++ b/src/nix/hash.cc @@ -85,7 +85,7 @@ struct CmdHashBase : Command switch (mode) { case FileIngestionMethod::Flat: - readFile(path, *hashSink); + *hashSink << readFileSource(path); break; case FileIngestionMethod::Recursive: *hashSink << dumpPath(path);