4 #include "util/coding/sequence_array.h" 6 #define ZSTD_STATIC_LINKING_ONLY 9 #include "base/endian.h" 10 #include "base/flit.h" 11 #include "base/logging.h" 13 namespace flit = base::flit;
19 template<
typename C>
size_t byte_size(
const C& container) {
20 return container.size() *
sizeof(
typename C::value_type);
23 inline size_t GetContentSizeChecked(
const uint8_t* src, uint32_t size) {
24 size_t content_size = ZSTD_getFrameContentSize(src, size);
26 CHECK_NE(ZSTD_CONTENTSIZE_ERROR, content_size);
27 CHECK_NE(ZSTD_CONTENTSIZE_UNKNOWN, content_size);
33 size_t SequenceArray::GetMaxSerializedSize()
const {
34 size_t sz1 = len_.size() * flit::Traits<uint32_t>::max_size;
35 return ZSTD_compressBound(data_.size()) + ZSTD_compressBound(sz1) + 4;
38 size_t SequenceArray::SerializeTo(uint8* dest)
const {
39 base::PODArray<uint8_t> len_buf;
40 len_buf.reserve(len_.size() * flit::Traits<uint32_t>::max_size);
43 for (
const uint32_t val : len_) {
44 len_size += flit::EncodeT<uint32_t>(val, len_buf.data() + len_size);
46 CHECK_LE(len_size, len_buf.capacity());
48 uint8* next = dest + 4;
49 size_t res1 = ZSTD_compress(next, ZSTD_compressBound(len_size), len_buf.data(), len_size, 1);
50 CHECK(!ZSTD_isError(res1)) << ZSTD_getErrorName(res1);
53 LittleEndian::Store32(dest, res1);
55 size_t res2 = ZSTD_compress(next, ZSTD_compressBound(data_.size()), data_.data(),
57 CHECK(!ZSTD_isError(res2)) << ZSTD_getErrorName(res2);
59 VLOG(1) <<
"SequenceArray::SerializeTo: from " << byte_size(len_) <<
"/" << data_size()
60 <<
" to " << res1 <<
"/" << res2 <<
" bytes";
61 return res1 + res2 + 4;
64 void SequenceArray::SerializeFrom(
const uint8_t* src, uint32_t count) {
68 uint32_t len_sz = LittleEndian::Load32(src);
70 CHECK_LT(4 + len_sz, count);
73 size_t len_content_size = GetContentSizeChecked(src, len_sz);
76 std::unique_ptr<uint8_t[]> len_buf(
new uint8_t[len_content_size + 8]);
78 size_t res = ZSTD_decompress(len_buf.get(), len_content_size, src, len_sz);
79 CHECK(!ZSTD_isError(res)) << ZSTD_getErrorName(res);
80 CHECK_EQ(res, len_content_size);
82 const uint8_t* next = len_buf.get();
83 while (next < len_buf.get() + res) {
85 next += flit::ParseT(next, &val);
88 CHECK_EQ(next, len_buf.get() + res);
89 uint32_t buf_sz = count - 4 - len_sz;
91 size_t buf_content_size = GetContentSizeChecked(src, buf_sz);
92 data_.resize(buf_content_size);
94 res = ZSTD_decompress(data_.data(), buf_content_size, src, buf_sz);
95 CHECK(!ZSTD_isError(res)) << ZSTD_getErrorName(res);
96 CHECK_EQ(buf_content_size, res);