mirror of
https://github.com/NixOS/nix.git
synced 2025-11-09 12:06:01 +01:00
refactor(libutil): add CompressedSource
Introduce a `CompressedSource` class in libutil's `serialise.hh` that compresses a `RestartableSource` and owns the compressed data. This is a general-purpose utility that can be used anywhere compressed data needs to be treated as a source.
This commit is contained in:
parent
bffbdcfddc
commit
93fe3354b5
3 changed files with 61 additions and 9 deletions
|
|
@ -141,18 +141,12 @@ void HttpBinaryCacheStore::upsertFile(
|
|||
req.method = HttpMethod::PUT;
|
||||
auto compressionMethod = getCompressionMethod(path);
|
||||
|
||||
std::string data;
|
||||
std::optional<StringSource> stringSource{};
|
||||
std::optional<CompressedSource> compressed;
|
||||
|
||||
if (compressionMethod) {
|
||||
StringSink sink{};
|
||||
auto compressionSink = makeCompressionSink(*compressionMethod, sink);
|
||||
source.drainInto(*compressionSink);
|
||||
compressionSink->finish();
|
||||
data = std::move(sink.s);
|
||||
compressed = CompressedSource(source, *compressionMethod);
|
||||
req.headers.emplace_back("Content-Encoding", *compressionMethod);
|
||||
stringSource = StringSource{data};
|
||||
req.data = {*stringSource};
|
||||
req.data = {compressed->size(), *compressed};
|
||||
} else {
|
||||
req.data = {sizeHint, source};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -272,6 +272,50 @@ struct StringSource : RestartableSource
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Compresses a RestartableSource using the specified compression method.
|
||||
*
|
||||
* @note currently this buffers the entire compressed data stream in memory. In the future it may instead compress data
|
||||
* on demand, lazily pulling from the original `RestartableSource`. In that case, the `size()` method would go away
|
||||
* because we would not in fact know the compressed size in advance.
|
||||
*/
|
||||
struct CompressedSource : RestartableSource
|
||||
{
|
||||
private:
|
||||
std::string compressedData;
|
||||
std::string compressionMethod;
|
||||
StringSource stringSource;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Compress a RestartableSource using the specified compression method.
|
||||
*
|
||||
* @param source The source data to compress
|
||||
* @param compressionMethod The compression method to use (e.g., "xz", "br")
|
||||
*/
|
||||
CompressedSource(RestartableSource & source, const std::string & compressionMethod);
|
||||
|
||||
size_t read(char * data, size_t len) override
|
||||
{
|
||||
return stringSource.read(data, len);
|
||||
}
|
||||
|
||||
void restart() override
|
||||
{
|
||||
stringSource.restart();
|
||||
}
|
||||
|
||||
uint64_t size() const
|
||||
{
|
||||
return compressedData.size();
|
||||
}
|
||||
|
||||
std::string_view getCompressionMethod() const
|
||||
{
|
||||
return compressionMethod;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a restartable Source from a factory function.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#include "nix/util/serialise.hh"
|
||||
#include "nix/util/compression.hh"
|
||||
#include "nix/util/signals.hh"
|
||||
#include "nix/util/util.hh"
|
||||
|
||||
|
|
@ -252,6 +253,19 @@ void StringSource::skip(size_t len)
|
|||
pos += len;
|
||||
}
|
||||
|
||||
CompressedSource::CompressedSource(RestartableSource & source, const std::string & compressionMethod)
|
||||
: compressedData([&]() {
|
||||
StringSink sink;
|
||||
auto compressionSink = makeCompressionSink(compressionMethod, sink);
|
||||
source.drainInto(*compressionSink);
|
||||
compressionSink->finish();
|
||||
return std::move(sink.s);
|
||||
}())
|
||||
, compressionMethod(compressionMethod)
|
||||
, stringSource(compressedData)
|
||||
{
|
||||
}
|
||||
|
||||
std::unique_ptr<FinishSink> sourceToSink(std::function<void(Source &)> fun)
|
||||
{
|
||||
struct SourceToSink : FinishSink
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue