tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

delta_encoding.cc (32078B)


      1 /*
      2 *  Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
      3 *
      4 *  Use of this source code is governed by a BSD-style license
      5 *  that can be found in the LICENSE file in the root of the source
      6 *  tree. An additional intellectual property rights grant can be found
      7 *  in the file PATENTS.  All contributing project authors may
      8 *  be found in the AUTHORS file in the root of the source tree.
      9 */
     10 
     11 #include "logging/rtc_event_log/encoder/delta_encoding.h"
     12 
     13 #include <algorithm>
     14 #include <cstddef>
     15 #include <cstdint>
     16 #include <limits>
     17 #include <memory>
     18 #include <optional>
     19 #include <string>
     20 #include <vector>
     21 
     22 #include "absl/memory/memory.h"
     23 #include "absl/strings/string_view.h"
     24 #include "logging/rtc_event_log/encoder/bit_writer.h"
     25 #include "logging/rtc_event_log/encoder/var_int.h"
     26 #include "rtc_base/bitstream_reader.h"
     27 #include "rtc_base/checks.h"
     28 #include "rtc_base/logging.h"
     29 
     30 namespace webrtc {
     31 namespace {
     32 
     33 // TODO(eladalon): Only build the decoder in tools and unit tests.
     34 
     35 bool g_force_unsigned_for_testing = false;
     36 bool g_force_signed_for_testing = false;
     37 
     38 size_t BitsToBytes(size_t bits) {
     39  return (bits / 8) + (bits % 8 > 0 ? 1 : 0);
     40 }
     41 
     42 // TODO(eladalon): Replace by something more efficient.
     43 uint64_t UnsignedBitWidth(uint64_t input, bool zero_val_as_zero_width = false) {
     44  if (zero_val_as_zero_width && input == 0) {
     45    return 0;
     46  }
     47 
     48  uint64_t width = 0;
     49  do {  // input == 0 -> width == 1
     50    width += 1;
     51    input >>= 1;
     52  } while (input != 0);
     53  return width;
     54 }
     55 
     56 uint64_t SignedBitWidth(uint64_t max_pos_magnitude,
     57                        uint64_t max_neg_magnitude) {
     58  const uint64_t bitwidth_pos = UnsignedBitWidth(max_pos_magnitude, true);
     59  const uint64_t bitwidth_neg =
     60      (max_neg_magnitude > 0) ? UnsignedBitWidth(max_neg_magnitude - 1, true)
     61                              : 0;
     62  return 1 + std::max(bitwidth_pos, bitwidth_neg);
     63 }
     64 
     65 // Return the maximum integer of a given bit width.
     66 // Examples:
     67 // MaxUnsignedValueOfBitWidth(1) = 0x01
     68 // MaxUnsignedValueOfBitWidth(6) = 0x3f
     69 // MaxUnsignedValueOfBitWidth(8) = 0xff
     70 // MaxUnsignedValueOfBitWidth(32) = 0xffffffff
     71 uint64_t MaxUnsignedValueOfBitWidth(uint64_t bit_width) {
     72  RTC_DCHECK_GE(bit_width, 1);
     73  RTC_DCHECK_LE(bit_width, 64);
     74  return (bit_width == 64) ? std::numeric_limits<uint64_t>::max()
     75                           : ((static_cast<uint64_t>(1) << bit_width) - 1);
     76 }
     77 
     78 // Computes the delta between `previous` and `current`, under the assumption
     79 // that wrap-around occurs after `width` is exceeded.
     80 uint64_t UnsignedDelta(uint64_t previous, uint64_t current, uint64_t bit_mask) {
     81  return (current - previous) & bit_mask;
     82 }
     83 
     84 // Determines the encoding type (e.g. fixed-size encoding).
     85 // Given an encoding type, may also distinguish between some variants of it
     86 // (e.g. which fields of the fixed-size encoding are explicitly mentioned by
     87 // the header, and which are implicitly assumed to hold certain default values).
     88 enum class EncodingType {
     89  kFixedSizeUnsignedDeltasNoEarlyWrapNoOpt = 0,
     90  kFixedSizeSignedDeltasEarlyWrapAndOptSupported = 1,
     91  kReserved1 = 2,
     92  kReserved2 = 3,
     93  kNumberOfEncodingTypes  // Keep last
     94 };
     95 
     96 // The width of each field in the encoding header. Note that this is the
     97 // width in case the field exists; not all fields occur in all encoding types.
     98 constexpr size_t kBitsInHeaderForEncodingType = 2;
     99 constexpr size_t kBitsInHeaderForDeltaWidthBits = 6;
    100 constexpr size_t kBitsInHeaderForSignedDeltas = 1;
    101 constexpr size_t kBitsInHeaderForValuesOptional = 1;
    102 constexpr size_t kBitsInHeaderForValueWidthBits = 6;
    103 
    104 static_assert(static_cast<size_t>(EncodingType::kNumberOfEncodingTypes) <=
    105                  1 << kBitsInHeaderForEncodingType,
    106              "Not all encoding types fit.");
    107 
    108 // Default values for when the encoding header does not specify explicitly.
    109 constexpr bool kDefaultSignedDeltas = false;
    110 constexpr bool kDefaultValuesOptional = false;
    111 constexpr uint64_t kDefaultValueWidthBits = 64;
    112 
    113 // Parameters for fixed-size delta-encoding/decoding.
    114 // These are tailored for the sequence which will be encoded (e.g. widths).
    115 class FixedLengthEncodingParameters final {
    116 public:
    117  static bool ValidParameters(uint64_t delta_width_bits,
    118                              bool /* signed_deltas */,
    119                              uint64_t value_width_bits) {
    120    return (1 <= delta_width_bits && delta_width_bits <= 64 &&
    121            1 <= value_width_bits && value_width_bits <= 64 &&
    122            delta_width_bits <= value_width_bits);
    123  }
    124 
    125  FixedLengthEncodingParameters(uint64_t delta_width_bits,
    126                                bool signed_deltas,
    127                                bool values_optional,
    128                                uint64_t value_width_bits)
    129      : delta_width_bits_(delta_width_bits),
    130        signed_deltas_(signed_deltas),
    131        values_optional_(values_optional),
    132        value_width_bits_(value_width_bits),
    133        delta_mask_(MaxUnsignedValueOfBitWidth(delta_width_bits_)),
    134        value_mask_(MaxUnsignedValueOfBitWidth(value_width_bits_)) {
    135    RTC_DCHECK(
    136        ValidParameters(delta_width_bits, signed_deltas, value_width_bits));
    137  }
    138 
    139  // Number of bits necessary to hold the widest(*) of the deltas between the
    140  // values in the sequence.
    141  // (*) - Widest might not be the largest, if signed deltas are used.
    142  uint64_t delta_width_bits() const { return delta_width_bits_; }
    143 
    144  // Whether deltas are signed.
    145  bool signed_deltas() const { return signed_deltas_; }
    146 
    147  // Whether the values of the sequence are optional. That is, it may be
    148  // that some of them do not have a value (not even a sentinel value indicating
    149  // invalidity).
    150  bool values_optional() const { return values_optional_; }
    151 
    152  // Number of bits necessary to hold the largest value in the sequence.
    153  uint64_t value_width_bits() const { return value_width_bits_; }
    154 
    155  // Masks where only the bits relevant to the deltas/values are turned on.
    156  uint64_t delta_mask() const { return delta_mask_; }
    157  uint64_t value_mask() const { return value_mask_; }
    158 
    159  void SetSignedDeltas(bool signed_deltas) { signed_deltas_ = signed_deltas; }
    160  void SetDeltaWidthBits(uint64_t delta_width_bits) {
    161    delta_width_bits_ = delta_width_bits;
    162    delta_mask_ = MaxUnsignedValueOfBitWidth(delta_width_bits);
    163  }
    164 
    165 private:
    166  uint64_t delta_width_bits_;  // Normally const, but mutable in tests.
    167  bool signed_deltas_;         // Normally const, but mutable in tests.
    168  const bool values_optional_;
    169  const uint64_t value_width_bits_;
    170 
    171  uint64_t delta_mask_;  // Normally const, but mutable in tests.
    172  const uint64_t value_mask_;
    173 };
    174 
    175 // Performs delta-encoding of a single (non-empty) sequence of values, using
    176 // an encoding where all deltas are encoded using the same number of bits.
    177 // (With the exception of optional elements; those are encoded as a bit vector
    178 // with one bit per element, plus a fixed number of bits for every element that
    179 // has a value.)
    180 class FixedLengthDeltaEncoder final {
    181 public:
    182  // See webrtc::EncodeDeltas() for general details.
    183  // This function return a bit pattern that would allow the decoder to
    184  // determine whether it was produced by FixedLengthDeltaEncoder, and can
    185  // therefore be decoded by FixedLengthDeltaDecoder, or whether it was produced
    186  // by a different encoder.
    187  static std::string EncodeDeltas(
    188      std::optional<uint64_t> base,
    189      const std::vector<std::optional<uint64_t>>& values);
    190 
    191  FixedLengthDeltaEncoder(const FixedLengthDeltaEncoder&) = delete;
    192  FixedLengthDeltaEncoder& operator=(const FixedLengthDeltaEncoder&) = delete;
    193 
    194 private:
    195  // Calculate min/max values of unsigned/signed deltas, given the bit width
    196  // of all the values in the series.
    197  static void CalculateMinAndMaxDeltas(
    198      std::optional<uint64_t> base,
    199      const std::vector<std::optional<uint64_t>>& values,
    200      uint64_t bit_width,
    201      uint64_t* max_unsigned_delta,
    202      uint64_t* max_pos_signed_delta,
    203      uint64_t* min_neg_signed_delta);
    204 
    205  // No effect outside of unit tests.
    206  // In unit tests, may lead to forcing signed/unsigned deltas, etc.
    207  static void ConsiderTestOverrides(FixedLengthEncodingParameters* params,
    208                                    uint64_t delta_width_bits_signed,
    209                                    uint64_t delta_width_bits_unsigned);
    210 
    211  // FixedLengthDeltaEncoder objects are to be created by EncodeDeltas() and
    212  // released by it before it returns. They're mostly a convenient way to
    213  // avoid having to pass a lot of state between different functions.
    214  // Therefore, it was deemed acceptable to let them have a reference to
    215  // `values`, whose lifetime must exceed the lifetime of `this`.
    216  FixedLengthDeltaEncoder(const FixedLengthEncodingParameters& params,
    217                          std::optional<uint64_t> base,
    218                          const std::vector<std::optional<uint64_t>>& values,
    219                          size_t existent_values_count);
    220 
    221  // Perform delta-encoding using the parameters given to the ctor on the
    222  // sequence of values given to the ctor.
    223  std::string Encode();
    224 
    225  // Exact lengths.
    226  size_t OutputLengthBytes(size_t existent_values_count) const;
    227  size_t HeaderLengthBits() const;
    228  size_t EncodedDeltasLengthBits(size_t existent_values_count) const;
    229 
    230  // Encode the compression parameters into the stream.
    231  void EncodeHeader();
    232 
    233  // Encode a given delta into the stream.
    234  void EncodeDelta(uint64_t previous, uint64_t current);
    235  void EncodeUnsignedDelta(uint64_t previous, uint64_t current);
    236  void EncodeSignedDelta(uint64_t previous, uint64_t current);
    237 
    238  // The parameters according to which encoding will be done (width of
    239  // fields, whether signed deltas should be used, etc.)
    240  const FixedLengthEncodingParameters params_;
    241 
    242  // The encoding scheme assumes that at least one value is transmitted OOB,
    243  // so that the first value can be encoded as a delta from that OOB value,
    244  // which is `base_`.
    245  const std::optional<uint64_t> base_;
    246 
    247  // The values to be encoded.
    248  // Note: This is a non-owning reference. See comment above ctor for details.
    249  const std::vector<std::optional<uint64_t>>& values_;
    250 
    251  // Buffer into which encoded values will be written.
    252  // This is created dynmically as a way to enforce that the rest of the
    253  // ctor has finished running when this is constructed, so that the lower
    254  // bound on the buffer size would be guaranteed correct.
    255  std::unique_ptr<BitWriter> writer_;
    256 };
    257 
    258 // TODO(eladalon): Reduce the number of passes.
    259 std::string FixedLengthDeltaEncoder::EncodeDeltas(
    260    std::optional<uint64_t> base,
    261    const std::vector<std::optional<uint64_t>>& values) {
    262  RTC_DCHECK(!values.empty());
    263 
    264  // As a special case, if all of the elements are identical to the base,
    265  // (including, for optional fields, about their existence/non-existence),
    266  // the empty string is used to signal that.
    267  if (std::all_of(
    268          values.cbegin(), values.cend(),
    269          [base](std::optional<uint64_t> val) { return val == base; })) {
    270    return std::string();
    271  }
    272 
    273  bool non_decreasing = true;
    274  uint64_t max_value_including_base = base.value_or(0u);
    275  size_t existent_values_count = 0;
    276  {
    277    uint64_t previous = base.value_or(0u);
    278    for (size_t i = 0; i < values.size(); ++i) {
    279      if (!values[i].has_value()) {
    280        continue;
    281      }
    282      ++existent_values_count;
    283      non_decreasing &= (previous <= values[i].value());
    284      max_value_including_base =
    285          std::max(max_value_including_base, values[i].value());
    286      previous = values[i].value();
    287    }
    288  }
    289 
    290  // If the sequence is non-decreasing, it may be assumed to have width = 64;
    291  // there's no reason to encode the actual max width in the encoding header.
    292  const uint64_t value_width_bits =
    293      non_decreasing ? 64 : UnsignedBitWidth(max_value_including_base);
    294 
    295  uint64_t max_unsigned_delta;
    296  uint64_t max_pos_signed_delta;
    297  uint64_t min_neg_signed_delta;
    298  CalculateMinAndMaxDeltas(base, values, value_width_bits, &max_unsigned_delta,
    299                           &max_pos_signed_delta, &min_neg_signed_delta);
    300 
    301  const uint64_t delta_width_bits_unsigned =
    302      UnsignedBitWidth(max_unsigned_delta);
    303  const uint64_t delta_width_bits_signed =
    304      SignedBitWidth(max_pos_signed_delta, min_neg_signed_delta);
    305 
    306  // Note: Preference for unsigned if the two have the same width (efficiency).
    307  const bool signed_deltas =
    308      delta_width_bits_signed < delta_width_bits_unsigned;
    309  const uint64_t delta_width_bits =
    310      signed_deltas ? delta_width_bits_signed : delta_width_bits_unsigned;
    311 
    312  const bool values_optional =
    313      !base.has_value() || (existent_values_count < values.size());
    314 
    315  FixedLengthEncodingParameters params(delta_width_bits, signed_deltas,
    316                                       values_optional, value_width_bits);
    317 
    318  // No effect in production.
    319  ConsiderTestOverrides(&params, delta_width_bits_signed,
    320                        delta_width_bits_unsigned);
    321 
    322  FixedLengthDeltaEncoder encoder(params, base, values, existent_values_count);
    323  return encoder.Encode();
    324 }
    325 
    326 void FixedLengthDeltaEncoder::CalculateMinAndMaxDeltas(
    327    std::optional<uint64_t> base,
    328    const std::vector<std::optional<uint64_t>>& values,
    329    uint64_t bit_width,
    330    uint64_t* max_unsigned_delta_out,
    331    uint64_t* max_pos_signed_delta_out,
    332    uint64_t* min_neg_signed_delta_out) {
    333  RTC_DCHECK(!values.empty());
    334  RTC_DCHECK(max_unsigned_delta_out);
    335  RTC_DCHECK(max_pos_signed_delta_out);
    336  RTC_DCHECK(min_neg_signed_delta_out);
    337 
    338  const uint64_t bit_mask = MaxUnsignedValueOfBitWidth(bit_width);
    339 
    340  uint64_t max_unsigned_delta = 0;
    341  uint64_t max_pos_signed_delta = 0;
    342  uint64_t min_neg_signed_delta = 0;
    343 
    344  std::optional<uint64_t> prev = base;
    345  for (size_t i = 0; i < values.size(); ++i) {
    346    if (!values[i].has_value()) {
    347      continue;
    348    }
    349 
    350    if (!prev.has_value()) {
    351      // If the base is non-existent, the first existent value is encoded as
    352      // a varint, rather than as a delta.
    353      RTC_DCHECK(!base.has_value());
    354      prev = values[i];
    355      continue;
    356    }
    357 
    358    const uint64_t current = values[i].value();
    359 
    360    const uint64_t forward_delta = UnsignedDelta(*prev, current, bit_mask);
    361    const uint64_t backward_delta = UnsignedDelta(current, *prev, bit_mask);
    362 
    363    max_unsigned_delta = std::max(max_unsigned_delta, forward_delta);
    364 
    365    if (forward_delta < backward_delta) {
    366      max_pos_signed_delta = std::max(max_pos_signed_delta, forward_delta);
    367    } else {
    368      min_neg_signed_delta = std::max(min_neg_signed_delta, backward_delta);
    369    }
    370 
    371    prev = current;
    372  }
    373 
    374  *max_unsigned_delta_out = max_unsigned_delta;
    375  *max_pos_signed_delta_out = max_pos_signed_delta;
    376  *min_neg_signed_delta_out = min_neg_signed_delta;
    377 }
    378 
    379 void FixedLengthDeltaEncoder::ConsiderTestOverrides(
    380    FixedLengthEncodingParameters* params,
    381    uint64_t delta_width_bits_signed,
    382    uint64_t delta_width_bits_unsigned) {
    383  if (g_force_unsigned_for_testing) {
    384    params->SetDeltaWidthBits(delta_width_bits_unsigned);
    385    params->SetSignedDeltas(false);
    386  } else if (g_force_signed_for_testing) {
    387    params->SetDeltaWidthBits(delta_width_bits_signed);
    388    params->SetSignedDeltas(true);
    389  } else {
    390    // Unchanged.
    391  }
    392 }
    393 
    394 FixedLengthDeltaEncoder::FixedLengthDeltaEncoder(
    395    const FixedLengthEncodingParameters& params,
    396    std::optional<uint64_t> base,
    397    const std::vector<std::optional<uint64_t>>& values,
    398    size_t existent_values_count)
    399    : params_(params), base_(base), values_(values) {
    400  RTC_DCHECK(!values_.empty());
    401  writer_ =
    402      std::make_unique<BitWriter>(OutputLengthBytes(existent_values_count));
    403 }
    404 
    405 std::string FixedLengthDeltaEncoder::Encode() {
    406  EncodeHeader();
    407 
    408  if (params_.values_optional()) {
    409    // Encode which values exist and which don't.
    410    for (std::optional<uint64_t> value : values_) {
    411      writer_->WriteBits(value.has_value() ? 1u : 0u, 1);
    412    }
    413  }
    414 
    415  std::optional<uint64_t> previous = base_;
    416  for (std::optional<uint64_t> value : values_) {
    417    if (!value.has_value()) {
    418      RTC_DCHECK(params_.values_optional());
    419      continue;
    420    }
    421 
    422    if (!previous.has_value()) {
    423      // If the base is non-existent, the first existent value is encoded as
    424      // a varint, rather than as a delta.
    425      RTC_DCHECK(!base_.has_value());
    426      writer_->WriteBits(EncodeVarInt(value.value()));
    427    } else {
    428      EncodeDelta(previous.value(), value.value());
    429    }
    430 
    431    previous = value;
    432  }
    433 
    434  return writer_->GetString();
    435 }
    436 
    437 size_t FixedLengthDeltaEncoder::OutputLengthBytes(
    438    size_t existent_values_count) const {
    439  return BitsToBytes(HeaderLengthBits() +
    440                     EncodedDeltasLengthBits(existent_values_count));
    441 }
    442 
    443 size_t FixedLengthDeltaEncoder::HeaderLengthBits() const {
    444  if (params_.signed_deltas() == kDefaultSignedDeltas &&
    445      params_.values_optional() == kDefaultValuesOptional &&
    446      params_.value_width_bits() == kDefaultValueWidthBits) {
    447    return kBitsInHeaderForEncodingType + kBitsInHeaderForDeltaWidthBits;
    448  } else {
    449    return kBitsInHeaderForEncodingType + kBitsInHeaderForDeltaWidthBits +
    450           kBitsInHeaderForSignedDeltas + kBitsInHeaderForValuesOptional +
    451           kBitsInHeaderForValueWidthBits;
    452  }
    453 }
    454 
    455 size_t FixedLengthDeltaEncoder::EncodedDeltasLengthBits(
    456    size_t existent_values_count) const {
    457  if (!params_.values_optional()) {
    458    return values_.size() * params_.delta_width_bits();
    459  } else {
    460    RTC_DCHECK_EQ(std::count_if(values_.begin(), values_.end(),
    461                                [](std::optional<uint64_t> val) {
    462                                  return val.has_value();
    463                                }),
    464                  existent_values_count);
    465    // One bit for each delta, to indicate if the value exists, and delta_width
    466    // for each existent value, to indicate the delta itself.
    467    // If base_ is non-existent, the first value (if any) is encoded as a varint
    468    // rather than as a delta.
    469    const size_t existence_bitmap_size_bits = 1 * values_.size();
    470    const bool first_value_is_varint =
    471        !base_.has_value() && existent_values_count >= 1;
    472    const size_t first_value_varint_size_bits = 8 * kMaxVarIntLengthBytes;
    473    const size_t deltas_count = existent_values_count - first_value_is_varint;
    474    const size_t deltas_size_bits = deltas_count * params_.delta_width_bits();
    475    return existence_bitmap_size_bits + first_value_varint_size_bits +
    476           deltas_size_bits;
    477  }
    478 }
    479 
    480 void FixedLengthDeltaEncoder::EncodeHeader() {
    481  RTC_DCHECK(writer_);
    482 
    483  const EncodingType encoding_type =
    484      (params_.value_width_bits() == kDefaultValueWidthBits &&
    485       params_.signed_deltas() == kDefaultSignedDeltas &&
    486       params_.values_optional() == kDefaultValuesOptional)
    487          ? EncodingType::kFixedSizeUnsignedDeltasNoEarlyWrapNoOpt
    488          : EncodingType::kFixedSizeSignedDeltasEarlyWrapAndOptSupported;
    489 
    490  writer_->WriteBits(static_cast<uint64_t>(encoding_type),
    491                     kBitsInHeaderForEncodingType);
    492 
    493  // Note: Since it's meaningless for a field to be of width 0, when it comes
    494  // to fields that relate widths, we encode  width 1 as 0, width 2 as 1,
    495 
    496  writer_->WriteBits(params_.delta_width_bits() - 1,
    497                     kBitsInHeaderForDeltaWidthBits);
    498 
    499  if (encoding_type == EncodingType::kFixedSizeUnsignedDeltasNoEarlyWrapNoOpt) {
    500    return;
    501  }
    502 
    503  writer_->WriteBits(static_cast<uint64_t>(params_.signed_deltas()),
    504                     kBitsInHeaderForSignedDeltas);
    505  writer_->WriteBits(static_cast<uint64_t>(params_.values_optional()),
    506                     kBitsInHeaderForValuesOptional);
    507  writer_->WriteBits(params_.value_width_bits() - 1,
    508                     kBitsInHeaderForValueWidthBits);
    509 }
    510 
    511 void FixedLengthDeltaEncoder::EncodeDelta(uint64_t previous, uint64_t current) {
    512  if (params_.signed_deltas()) {
    513    EncodeSignedDelta(previous, current);
    514  } else {
    515    EncodeUnsignedDelta(previous, current);
    516  }
    517 }
    518 
    519 void FixedLengthDeltaEncoder::EncodeUnsignedDelta(uint64_t previous,
    520                                                  uint64_t current) {
    521  RTC_DCHECK(writer_);
    522  const uint64_t delta = UnsignedDelta(previous, current, params_.value_mask());
    523  writer_->WriteBits(delta, params_.delta_width_bits());
    524 }
    525 
    526 void FixedLengthDeltaEncoder::EncodeSignedDelta(uint64_t previous,
    527                                                uint64_t current) {
    528  RTC_DCHECK(writer_);
    529 
    530  const uint64_t forward_delta =
    531      UnsignedDelta(previous, current, params_.value_mask());
    532  const uint64_t backward_delta =
    533      UnsignedDelta(current, previous, params_.value_mask());
    534 
    535  uint64_t delta;
    536  if (forward_delta <= backward_delta) {
    537    delta = forward_delta;
    538  } else {
    539    // Compute the unsigned representation of a negative delta.
    540    // This is the two's complement representation of this negative value,
    541    // when deltas are of width params_.delta_mask().
    542    RTC_DCHECK_GE(params_.delta_mask(), backward_delta);
    543    RTC_DCHECK_LT(params_.delta_mask() - backward_delta, params_.delta_mask());
    544    delta = params_.delta_mask() - backward_delta + 1;
    545    RTC_DCHECK_LE(delta, params_.delta_mask());
    546  }
    547 
    548  writer_->WriteBits(delta, params_.delta_width_bits());
    549 }
    550 
    551 // Perform decoding of a a delta-encoded stream, extracting the original
    552 // sequence of values.
    553 class FixedLengthDeltaDecoder final {
    554 public:
    555  // Checks whether FixedLengthDeltaDecoder is a suitable decoder for this
    556  // bitstream. Note that this does NOT imply that stream is valid, and will
    557  // be decoded successfully. It DOES imply that all other decoder classes
    558  // will fail to decode this input, though.
    559  static bool IsSuitableDecoderFor(absl::string_view input);
    560 
    561  // Assuming that `input` is the result of fixed-size delta-encoding
    562  // that took place with the same value to `base` and over `num_of_deltas`
    563  // original values, this will return the sequence of original values.
    564  // If an error occurs (can happen if `input` is corrupt), an empty
    565  // vector will be returned.
    566  static std::vector<std::optional<uint64_t>> DecodeDeltas(
    567      absl::string_view input,
    568      std::optional<uint64_t> base,
    569      size_t num_of_deltas);
    570 
    571  FixedLengthDeltaDecoder(const FixedLengthDeltaDecoder&) = delete;
    572  FixedLengthDeltaDecoder& operator=(const FixedLengthDeltaDecoder&) = delete;
    573 
    574 private:
    575  // Reads the encoding header in `input` and returns a FixedLengthDeltaDecoder
    576  // with the corresponding configuration, that can be used to decode the
    577  // values in `input`.
    578  // If the encoding header is corrupt (contains an illegal configuration),
    579  // nullptr will be returned.
    580  // When a valid FixedLengthDeltaDecoder is returned, this does not mean that
    581  // the entire stream is free of error. Rather, only the encoding header is
    582  // examined and guaranteed.
    583  static std::unique_ptr<FixedLengthDeltaDecoder> Create(
    584      absl::string_view input,
    585      std::optional<uint64_t> base,
    586      size_t num_of_deltas);
    587 
    588  // FixedLengthDeltaDecoder objects are to be created by DecodeDeltas() and
    589  // released by it before it returns. They're mostly a convenient way to
    590  // avoid having to pass a lot of state between different functions.
    591  // Therefore, it was deemed acceptable that `reader` does not own the buffer
    592  // it reads, meaning the lifetime of `this` must not exceed the lifetime
    593  // of `reader`'s underlying buffer.
    594  FixedLengthDeltaDecoder(BitstreamReader reader,
    595                          const FixedLengthEncodingParameters& params,
    596                          std::optional<uint64_t> base,
    597                          size_t num_of_deltas);
    598 
    599  // Perform the decoding using the parameters given to the ctor.
    600  std::vector<std::optional<uint64_t>> Decode();
    601 
    602  // Add `delta` to `base` to produce the next value in a sequence.
    603  // The delta is applied as signed/unsigned depending on the parameters
    604  // given to the ctor. Wrap-around is taken into account according to the
    605  // values' width, as specified by the aforementioned encoding parameters.
    606  uint64_t ApplyDelta(uint64_t base, uint64_t delta) const;
    607 
    608  // Helpers for ApplyDelta().
    609  uint64_t ApplyUnsignedDelta(uint64_t base, uint64_t delta) const;
    610  uint64_t ApplySignedDelta(uint64_t base, uint64_t delta) const;
    611 
    612  // Reader of the input stream to be decoded. Does not own that buffer.
    613  // See comment above ctor for details.
    614  BitstreamReader reader_;
    615 
    616  // The parameters according to which encoding will be done (width of
    617  // fields, whether signed deltas should be used, etc.)
    618  const FixedLengthEncodingParameters params_;
    619 
    620  // The encoding scheme assumes that at least one value is transmitted OOB,
    621  // so that the first value can be encoded as a delta from that OOB value,
    622  // which is `base_`.
    623  const std::optional<uint64_t> base_;
    624 
    625  // The number of values to be known to be decoded.
    626  const size_t num_of_deltas_;
    627 };
    628 
    629 bool FixedLengthDeltaDecoder::IsSuitableDecoderFor(absl::string_view input) {
    630  BitstreamReader reader(input);
    631  uint64_t encoding_type_bits = reader.ReadBits(kBitsInHeaderForEncodingType);
    632  if (!reader.Ok()) {
    633    return false;
    634  }
    635 
    636  const auto encoding_type = static_cast<EncodingType>(encoding_type_bits);
    637  return encoding_type ==
    638             EncodingType::kFixedSizeUnsignedDeltasNoEarlyWrapNoOpt ||
    639         encoding_type ==
    640             EncodingType::kFixedSizeSignedDeltasEarlyWrapAndOptSupported;
    641 }
    642 
    643 std::vector<std::optional<uint64_t>> FixedLengthDeltaDecoder::DecodeDeltas(
    644    absl::string_view input,
    645    std::optional<uint64_t> base,
    646    size_t num_of_deltas) {
    647  auto decoder = FixedLengthDeltaDecoder::Create(input, base, num_of_deltas);
    648  if (!decoder) {
    649    return std::vector<std::optional<uint64_t>>();
    650  }
    651 
    652  return decoder->Decode();
    653 }
    654 
    655 std::unique_ptr<FixedLengthDeltaDecoder> FixedLengthDeltaDecoder::Create(
    656    absl::string_view input,
    657    std::optional<uint64_t> base,
    658    size_t num_of_deltas) {
    659  BitstreamReader reader(input);
    660  // Encoding type
    661  uint32_t encoding_type_bits = reader.ReadBits(kBitsInHeaderForEncodingType);
    662  if (!reader.Ok()) {
    663    return nullptr;
    664  }
    665 
    666  const EncodingType encoding = static_cast<EncodingType>(encoding_type_bits);
    667  if (encoding != EncodingType::kFixedSizeUnsignedDeltasNoEarlyWrapNoOpt &&
    668      encoding !=
    669          EncodingType::kFixedSizeSignedDeltasEarlyWrapAndOptSupported) {
    670    RTC_LOG(LS_WARNING) << "Unrecognized encoding type.";
    671    return nullptr;
    672  }
    673 
    674  // See encoding for +1's rationale.
    675  const uint64_t delta_width_bits =
    676      reader.ReadBits(kBitsInHeaderForDeltaWidthBits) + 1;
    677  RTC_DCHECK_LE(delta_width_bits, 64);
    678 
    679  // signed_deltas, values_optional, value_width_bits
    680  bool signed_deltas;
    681  bool values_optional;
    682  uint64_t value_width_bits;
    683  if (encoding == EncodingType::kFixedSizeUnsignedDeltasNoEarlyWrapNoOpt) {
    684    signed_deltas = kDefaultSignedDeltas;
    685    values_optional = kDefaultValuesOptional;
    686    value_width_bits = kDefaultValueWidthBits;
    687  } else {
    688    signed_deltas = reader.Read<bool>();
    689    values_optional = reader.Read<bool>();
    690    // See encoding for +1's rationale.
    691    value_width_bits = reader.ReadBits(kBitsInHeaderForValueWidthBits) + 1;
    692    RTC_DCHECK_LE(value_width_bits, 64);
    693  }
    694 
    695  if (!reader.Ok()) {
    696    return nullptr;
    697  }
    698 
    699  // Note: Because of the way the parameters are read, it is not possible
    700  // for illegal values to be read. We check nevertheless, in case the code
    701  // changes in the future in a way that breaks this promise.
    702  if (!FixedLengthEncodingParameters::ValidParameters(
    703          delta_width_bits, signed_deltas, value_width_bits)) {
    704    RTC_LOG(LS_WARNING) << "Corrupt log; illegal encoding parameters.";
    705    return nullptr;
    706  }
    707 
    708  FixedLengthEncodingParameters params(delta_width_bits, signed_deltas,
    709                                       values_optional, value_width_bits);
    710  return absl::WrapUnique(
    711      new FixedLengthDeltaDecoder(reader, params, base, num_of_deltas));
    712 }
    713 
    714 FixedLengthDeltaDecoder::FixedLengthDeltaDecoder(
    715    BitstreamReader reader,
    716    const FixedLengthEncodingParameters& params,
    717    std::optional<uint64_t> base,
    718    size_t num_of_deltas)
    719    : reader_(reader),
    720      params_(params),
    721      base_(base),
    722      num_of_deltas_(num_of_deltas) {
    723  RTC_DCHECK(reader_.Ok());
    724 }
    725 
    726 std::vector<std::optional<uint64_t>> FixedLengthDeltaDecoder::Decode() {
    727  RTC_DCHECK(reader_.Ok());
    728  std::vector<bool> existing_values(num_of_deltas_);
    729  if (params_.values_optional()) {
    730    for (size_t i = 0; i < num_of_deltas_; ++i) {
    731      existing_values[i] = reader_.Read<bool>();
    732    }
    733  } else {
    734    std::fill(existing_values.begin(), existing_values.end(), true);
    735  }
    736 
    737  std::optional<uint64_t> previous = base_;
    738  std::vector<std::optional<uint64_t>> values(num_of_deltas_);
    739 
    740  for (size_t i = 0; i < num_of_deltas_; ++i) {
    741    if (!existing_values[i]) {
    742      RTC_DCHECK(params_.values_optional());
    743      continue;
    744    }
    745 
    746    if (!previous) {
    747      // If the base is non-existent, the first existent value is encoded as
    748      // a varint, rather than as a delta.
    749      RTC_DCHECK(!base_.has_value());
    750      values[i] = DecodeVarInt(reader_);
    751    } else {
    752      uint64_t delta = reader_.ReadBits(params_.delta_width_bits());
    753      values[i] = ApplyDelta(*previous, delta);
    754    }
    755 
    756    previous = values[i];
    757  }
    758 
    759  if (!reader_.Ok()) {
    760    values = {};
    761  }
    762 
    763  return values;
    764 }
    765 
    766 uint64_t FixedLengthDeltaDecoder::ApplyDelta(uint64_t base,
    767                                             uint64_t delta) const {
    768  RTC_DCHECK_LE(base, MaxUnsignedValueOfBitWidth(params_.value_width_bits()));
    769  RTC_DCHECK_LE(delta, MaxUnsignedValueOfBitWidth(params_.delta_width_bits()));
    770  return params_.signed_deltas() ? ApplySignedDelta(base, delta)
    771                                 : ApplyUnsignedDelta(base, delta);
    772 }
    773 
    774 uint64_t FixedLengthDeltaDecoder::ApplyUnsignedDelta(uint64_t base,
    775                                                     uint64_t delta) const {
    776  // Note: May still be used if signed deltas used.
    777  RTC_DCHECK_LE(base, MaxUnsignedValueOfBitWidth(params_.value_width_bits()));
    778  RTC_DCHECK_LE(delta, MaxUnsignedValueOfBitWidth(params_.delta_width_bits()));
    779  return (base + delta) & params_.value_mask();
    780 }
    781 
    782 uint64_t FixedLengthDeltaDecoder::ApplySignedDelta(uint64_t base,
    783                                                   uint64_t delta) const {
    784  RTC_DCHECK(params_.signed_deltas());
    785  RTC_DCHECK_LE(base, MaxUnsignedValueOfBitWidth(params_.value_width_bits()));
    786  RTC_DCHECK_LE(delta, MaxUnsignedValueOfBitWidth(params_.delta_width_bits()));
    787 
    788  const uint64_t top_bit = static_cast<uint64_t>(1)
    789                           << (params_.delta_width_bits() - 1);
    790 
    791  const bool positive_delta = ((delta & top_bit) == 0);
    792  if (positive_delta) {
    793    return ApplyUnsignedDelta(base, delta);
    794  }
    795 
    796  const uint64_t delta_abs = (~delta & params_.delta_mask()) + 1;
    797  return (base - delta_abs) & params_.value_mask();
    798 }
    799 
    800 }  // namespace
    801 
    802 std::string EncodeDeltas(std::optional<uint64_t> base,
    803                         const std::vector<std::optional<uint64_t>>& values) {
    804  // TODO(eladalon): Support additional encodings.
    805  return FixedLengthDeltaEncoder::EncodeDeltas(base, values);
    806 }
    807 
    808 std::vector<std::optional<uint64_t>> DecodeDeltas(absl::string_view input,
    809                                                  std::optional<uint64_t> base,
    810                                                  size_t num_of_deltas) {
    811  RTC_DCHECK_GT(num_of_deltas, 0);  // Allows empty vector to indicate error.
    812 
    813  // The empty string is a special case indicating that all values were equal
    814  // to the base.
    815  if (input.empty()) {
    816    std::vector<std::optional<uint64_t>> result(num_of_deltas);
    817    std::fill(result.begin(), result.end(), base);
    818    return result;
    819  }
    820 
    821  if (FixedLengthDeltaDecoder::IsSuitableDecoderFor(input)) {
    822    return FixedLengthDeltaDecoder::DecodeDeltas(input, base, num_of_deltas);
    823  }
    824 
    825  RTC_LOG(LS_WARNING) << "Could not decode delta-encoded stream.";
    826  return std::vector<std::optional<uint64_t>>();
    827 }
    828 
    829 void SetFixedLengthEncoderDeltaSignednessForTesting(bool signedness) {
    830  g_force_unsigned_for_testing = !signedness;
    831  g_force_signed_for_testing = signedness;
    832 }
    833 
    834 void UnsetFixedLengthEncoderDeltaSignednessForTesting() {
    835  g_force_unsigned_for_testing = false;
    836  g_force_signed_for_testing = false;
    837 }
    838 
    839 }  // namespace webrtc