123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272 |
- // Copyright 2017 The Chromium 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 COMPONENTS_ZUCCHINI_PATCH_WRITER_H_
- #define COMPONENTS_ZUCCHINI_PATCH_WRITER_H_
- #include <stddef.h>
- #include <stdint.h>
- #include <map>
- #include <utility>
- #include <vector>
- #include "base/check.h"
- #include "components/zucchini/buffer_sink.h"
- #include "components/zucchini/buffer_view.h"
- #include "components/zucchini/image_utils.h"
- #include "components/zucchini/patch_utils.h"
- #include "third_party/abseil-cpp/absl/types/optional.h"
- namespace zucchini {
- namespace patch {
- // If sufficient space is available, serializes |element_match| into |sink| and
- // returns true. Otherwise returns false, and |sink| will be in an undefined
- // state.
- bool SerializeElementMatch(const ElementMatch& element_match, BufferSink* sink);
- // Returns the size in bytes required to serialize |element_match|.
- size_t SerializedElementMatchSize(const ElementMatch& element_match);
- // If sufficient space is available, serializes |buffer| into |sink| and returns
- // true. Otherwise returns false, and |sink| will be in an undefined state.
- bool SerializeBuffer(const std::vector<uint8_t>& buffer, BufferSink* sink);
- // Returns the size in bytes required to serialize |buffer|.
- size_t SerializedBufferSize(const std::vector<uint8_t>& buffer);
- } // namespace patch
- // Each of *Sink classes below has an associated "main type", and performs the
- // following:
- // - Receives multiple "main type" elements (hence "Sink" in the name).
- // - Encodes list of received data, and writes them to internal storage (e.g.,
- // applying delta encoding).
- // - Writes encoded data to BufferSink.
- //
- // Common "core functions" implemented for *Sink classes are:
- // - void PutNext(const MAIN_TYPE& inst): Encodes and writes an instance of
- // MAIN_TYPE to internal storage. Assumptions may be applied to successive
- // |inst| provided.
- // - size_t SerializedSize() const: Returns the serialized size in bytes of
- // internal storage.
- // - bool SerializeInto(BufferSink* sink) const: If |sink| has enough space,
- // serializes internal storage into |sink|, and returns true. Otherwise
- // returns false.
- //
- // Usage of *Sink instances don't mix, and PuttNext() have dissimilar
- // interfaces. Therefore we do not use inheritance to relate *Sink classes,
- // simply implement "core functions" with matching names.
- // Sink for equivalences.
- class EquivalenceSink {
- public:
- EquivalenceSink();
- EquivalenceSink(const std::vector<uint8_t>& src_skip,
- const std::vector<uint8_t>& dst_skip,
- const std::vector<uint8_t>& copy_count);
- EquivalenceSink(EquivalenceSink&&);
- ~EquivalenceSink();
- // Core functions.
- // Equivalences must be given by increasing |Equivalence::dst_offset|.
- void PutNext(const Equivalence& equivalence);
- size_t SerializedSize() const;
- bool SerializeInto(BufferSink* sink) const;
- private:
- // Offset in source, delta-encoded starting from end of last equivalence, and
- // stored as signed varint.
- std::vector<uint8_t> src_skip_;
- // Offset in destination, delta-encoded starting from end of last equivalence,
- // and stored as unsigned varint.
- std::vector<uint8_t> dst_skip_;
- // Length of equivalence stored as unsigned varint.
- // TODO(etiennep): Investigate on bias.
- std::vector<uint8_t> copy_count_;
- offset_t src_offset_ = 0; // Last offset in source.
- offset_t dst_offset_ = 0; // Last offset in destination.
- };
- // Sink for extra data.
- class ExtraDataSink {
- public:
- ExtraDataSink();
- explicit ExtraDataSink(const std::vector<uint8_t>& extra_data);
- ExtraDataSink(ExtraDataSink&&);
- ~ExtraDataSink();
- // Core functions.
- void PutNext(ConstBufferView region);
- size_t SerializedSize() const;
- bool SerializeInto(BufferSink* sink) const;
- private:
- std::vector<uint8_t> extra_data_;
- };
- // Sink for raw delta.
- class RawDeltaSink {
- public:
- RawDeltaSink();
- RawDeltaSink(const std::vector<uint8_t>& raw_delta_skip,
- const std::vector<uint8_t>& raw_delta_diff);
- RawDeltaSink(RawDeltaSink&&);
- ~RawDeltaSink();
- // Core functions.
- // Deltas must be given by increasing |RawDeltaUnit::copy_offset|.
- void PutNext(const RawDeltaUnit& delta);
- size_t SerializedSize() const;
- bool SerializeInto(BufferSink* sink) const;
- private:
- std::vector<uint8_t> raw_delta_skip_; // Copy offset stating from last delta.
- std::vector<uint8_t> raw_delta_diff_; // Bytewise difference.
- // We keep track of the compensation needed for next copy offset, taking into
- // accound delta encoding and bias of -1. Stored delta are biased by -1, so a
- // sequence of single byte deltas is represented as a string of 0's.
- offset_t copy_offset_compensation_ = 0;
- };
- // Sink for reference delta.
- class ReferenceDeltaSink {
- public:
- ReferenceDeltaSink();
- explicit ReferenceDeltaSink(const std::vector<uint8_t>& reference_delta);
- ReferenceDeltaSink(ReferenceDeltaSink&&);
- ~ReferenceDeltaSink();
- // Core functions.
- void PutNext(int32_t diff);
- size_t SerializedSize() const;
- bool SerializeInto(BufferSink* sink) const;
- private:
- std::vector<uint8_t> reference_delta_;
- };
- // Sink for additional targets.
- class TargetSink {
- public:
- TargetSink();
- explicit TargetSink(const std::vector<uint8_t>& extra_targets);
- TargetSink(TargetSink&&);
- ~TargetSink();
- // Core functions.
- // Targets must be given by increasing order.
- void PutNext(uint32_t target);
- size_t SerializedSize() const;
- bool SerializeInto(BufferSink* sink) const;
- private:
- // Targets are delta-encoded and biaised by 1, stored as unsigned varint.
- std::vector<uint8_t> extra_targets_;
- // We keep track of the compensation needed for next target, taking into
- // accound delta encoding and bias of -1.
- offset_t target_compensation_ = 0;
- };
- // Following are utility classes to write structured data forming a patch.
- // Utility to write a patch element. A patch element contains all the
- // information necessary to patch a single element. This class
- // provides an interface to individually set different building blocks of data
- // in the patch element.
- class PatchElementWriter {
- public:
- PatchElementWriter();
- explicit PatchElementWriter(ElementMatch element_match);
- PatchElementWriter(PatchElementWriter&&);
- ~PatchElementWriter();
- const ElementMatch& element_match() const { return element_match_; }
- const Element& old_element() const { return element_match_.old_element; }
- const Element& new_element() const { return element_match_.new_element; }
- // Following methods set individual blocks for this element. Previous
- // corresponding block is replaced. All streams must be set before call to
- // SerializedSize() of SerializeInto().
- void SetEquivalenceSink(EquivalenceSink&& equivalences) {
- equivalences_.emplace(std::move(equivalences));
- }
- void SetExtraDataSink(ExtraDataSink&& extra_data) {
- extra_data_.emplace(std::move(extra_data));
- }
- void SetRawDeltaSink(RawDeltaSink&& raw_delta) {
- raw_delta_.emplace(std::move(raw_delta));
- }
- void SetReferenceDeltaSink(ReferenceDeltaSink reference_delta) {
- reference_delta_.emplace(std::move(reference_delta));
- }
- // Set additional targets for pool identified with |pool_tag|.
- void SetTargetSink(PoolTag pool_tag, TargetSink&& extra_targets) {
- DCHECK(pool_tag != kNoPoolTag);
- extra_targets_.emplace(pool_tag, std::move(extra_targets));
- }
- // Returns the serialized size in bytes of the data this object is holding.
- size_t SerializedSize() const;
- // If sufficient space is available, serializes data into |sink|, which is at
- // least SerializedSize() bytes, and returns true. Otherwise returns false.
- bool SerializeInto(BufferSink* sink) const;
- private:
- ElementMatch element_match_;
- absl::optional<EquivalenceSink> equivalences_;
- absl::optional<ExtraDataSink> extra_data_;
- absl::optional<RawDeltaSink> raw_delta_;
- absl::optional<ReferenceDeltaSink> reference_delta_;
- std::map<PoolTag, TargetSink> extra_targets_;
- };
- // Utility to write a Zucchini ensemble patch. An ensemble patch is the
- // concatenation of a patch header with a vector of patch elements.
- class EnsemblePatchWriter {
- public:
- explicit EnsemblePatchWriter(const PatchHeader& header);
- EnsemblePatchWriter(ConstBufferView old_image, ConstBufferView new_image);
- EnsemblePatchWriter(const EnsemblePatchWriter&) = delete;
- const EnsemblePatchWriter& operator=(const EnsemblePatchWriter&) = delete;
- ~EnsemblePatchWriter();
- // Reserves space for |count| patch elements.
- void ReserveElements(size_t count) { elements_.reserve(count); }
- // Adds an patch element into the patch. Patch elements must be ordered by
- // their location in the new image file.
- void AddElement(PatchElementWriter&& patch_element);
- // Returns the serialized size in bytes of the data this object is holding.
- size_t SerializedSize() const;
- // If sufficient space is available, serializes data into |sink|, which is at
- // least SerializedSize() bytes, and returns true. Otherwise returns false.
- bool SerializeInto(BufferSink* sink) const;
- // If sufficient space is available, serializes data into |buffer|, which is
- // at least SerializedSize() bytes, and returns true. Otherwise returns false.
- bool SerializeInto(MutableBufferView buffer) const {
- BufferSink sink(buffer);
- return SerializeInto(&sink);
- }
- private:
- PatchHeader header_;
- std::vector<PatchElementWriter> elements_;
- offset_t current_dst_offset_ = 0;
- };
- } // namespace zucchini
- #endif // COMPONENTS_ZUCCHINI_PATCH_WRITER_H_
|