blob: 911c6af0a7c51ec23110f9c9f1f65014040e6914 [file] [log] [blame]
// Copyright 2024 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "patchmaker/compression_util.h"
#include <optional>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include "patchmaker/file_util.h"
// We do not want to perform the most aggressive compression here for
// performance reasons. This utility is used to perform a quick
// comparison to understand the effectiveness of compression, and for
// this purpose an intermediate compression level is effective.
#define ZSTD_COMPRESSION_LEVEL_TEST 5
namespace util {
bool Compress(const brillo::Blob& in, brillo::Blob* out) {
ScopedZstdCtx ctx(ZSTD_createCCtx());
size_t compressed_size;
if (ZSTD_isError(ZSTD_CCtx_setParameter(ctx.get(), ZSTD_c_compressionLevel,
ZSTD_COMPRESSION_LEVEL_TEST))) {
return false;
}
// Ensure our buffer has enough space to hold compressed contents, as in
// theory it could be larger than the input file.
out->resize(ZSTD_compressBound(in.size()));
// Compression step.
compressed_size = ZSTD_compress2(ctx.get(),
// Destination.
out->data(), out->size(),
// Source.
in.data(), in.size());
out->resize(compressed_size);
if (ZSTD_isError(compressed_size)) {
return false;
}
return true;
}
bool Decompress(const brillo::Blob& in, brillo::Blob* out) {
out->resize(ZSTD_getFrameContentSize(in.data(), in.size()));
// Compression step.
size_t decompressed_size = ZSTD_decompress(
// Destination.
out->data(), out->size(),
// Source.
in.data(), in.size());
out->resize(decompressed_size);
// Clean up
if (ZSTD_isError(decompressed_size)) {
return false;
}
return true;
}
std::optional<size_t> GetCompressedSize(const base::FilePath& path) {
std::optional<brillo::Blob> src;
src = ReadFileToBlob(path);
if (!src.has_value()) {
LOG(ERROR) << "Failed to load file into blob";
return std::nullopt;
}
brillo::Blob dst;
if (!Compress(*src, &dst)) {
LOG(ERROR) << "Compress call failed";
return std::nullopt;
}
return dst.size();
}
} // namespace util