blob: 3334f7477da2362f28eb9564e65ff838570708f2 [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ZIRCON_SYSTEM_ULIB_BLOBFS_COMPRESSION_ZSTD_SEEKABLE_H_
#define ZIRCON_SYSTEM_ULIB_BLOBFS_COMPRESSION_ZSTD_SEEKABLE_H_
#include <zircon/errors.h>
#include <zircon/types.h>
#include <memory>
#include <optional>
#include <blobfs/format.h>
#include <lib/zx/status.h>
#include <zstd/zstd.h>
#include <zstd/zstd_seekable.h>
#include "compressor.h"
#include "decompressor.h"
#include "seekable-decompressor.h"
namespace blobfs {
struct ZSTDSeekableHeader {
uint64_t archive_size;
};
constexpr size_t kZSTDSeekableHeaderSize = sizeof(ZSTDSeekableHeader);
constexpr unsigned kZSTDSeekableMaxFrameSize = 128 * kBlobfsBlockSize;
// Compressor implementation for the zstd seekable format library implemented in
// //third_party/zstd/contrib/seekable_format. The library provides a convenient API for
// random access in zstd archives.
class ZSTDSeekableCompressor : public Compressor {
public:
// TODO(markdittmer): This can include `kBlobFlagZSTDCompressed` if a unified envelope format is
// implemented across (minimally) all ZSTD compression strategies.
static uint32_t InodeHeaderCompressionFlags() { return kBlobFlagZSTDSeekableCompressed; }
// Returns an upper bound on the size of the buffer required to store the compressed
// representation of a blob of size `input_length`.
static size_t BufferMax(size_t input_length);
static zx_status_t Create(size_t input_size, void* compression_buffer,
size_t compression_buffer_length,
std::unique_ptr<ZSTDSeekableCompressor>* out);
~ZSTDSeekableCompressor();
////////////////////////////////////////
// Compressor interface
size_t Size() const final;
zx_status_t Update(const void* input_data, size_t input_length) final;
zx_status_t End() final;
private:
// Writes up to `kZSTDSeekableHeaderSize` bytes from the beginning of `buf` from `header`.
// @param buf Pointer to buffer that is to contain <header><zstd seekable archive>.
// @param buf_size Size of `buf` in bytes.
// @param header Header values to write.
// It is the responsibility of any code writing the zstd seekable archive to `buf` to skip the
// first `kZSTDSeekableHeaderSize` bytes before writing the archive contents. This is generally an
// implementation detail invoked by other public methods, but is public to enable test
// environments to write syntactically correct headers via the same code code path used by
// `ZSTDSeekableCompressor`.
static zx_status_t WriteHeader(void* buf, size_t buf_size, ZSTDSeekableHeader header);
ZSTDSeekableCompressor(ZSTD_seekable_CStream* stream, void* compression_buffer,
size_t compression_buffer_length);
ZSTD_seekable_CStream* stream_ = nullptr;
ZSTD_outBuffer output_ = {};
DISALLOW_COPY_ASSIGN_AND_MOVE(ZSTDSeekableCompressor);
};
class ZSTDSeekableDecompressor : public Decompressor, public SeekableDecompressor {
public:
ZSTDSeekableDecompressor() = default;
DISALLOW_COPY_ASSIGN_AND_MOVE(ZSTDSeekableDecompressor);
zx_status_t DecompressArchive(void* uncompressed_buf, size_t* uncompressed_size,
const void* compressed_buf, size_t compressed_size, size_t offset);
// Decompressor implementation.
zx_status_t Decompress(void* uncompressed_buf, size_t* uncompressed_size,
const void* compressed_buf, const size_t max_compressed_size) final;
// SeekableDecompressor implementation.
zx_status_t DecompressRange(void* uncompressed_buf, size_t* uncompressed_size,
const void* compressed_buf, size_t max_compressed_size,
size_t offset) final;
zx::status<CompressionMapping> MappingForDecompressedRange(size_t offset, size_t len) final {
// TODO(markdittmer): Implement.
ZX_ASSERT(false);
return zx::error(ZX_ERR_INTERNAL);
}
// Reads up to `kZSTDSeekableHeaderSize` bytes from the beginning of `buf` into `header`.
// @param buf Pointer to buffer that is to contain <header><zstd seekable archive>.
// @param buf_size Size of `buf` in bytes.
// @param header Header struct in which to store values.
static zx_status_t ReadHeader(const void* buf, size_t buf_size, ZSTDSeekableHeader* header);
};
} // namespace blobfs
#endif // ZIRCON_SYSTEM_ULIB_BLOBFS_COMPRESSION_ZSTD_SEEKABLE_H_