content: // Copyright 2023 Google Inc. Use of this source code is governed by an
  // MIT-style license that can be found in the LICENSE file or at
  // https://opensource.org/licenses/MIT.
  
  import '../embedded_sass.pb.dart';
  import '../utils.dart';
  
  /// A class that builds up unsigned varints byte-by-byte.
  class VarintBuilder {
    /// The maximum length in bits of the varint being parsed.
    final int _maxLength;
  
    /// The name of the value being parsed, used for error reporting.
    final String? _name;
  
    /// The value of the varint so far.
    int _value = 0;
  
    /// The total number of bits parsed so far.
    int _bits = 0;
  
    /// Whether we've finished parsing the varint.
    var _done = false;
  
    /// Creates a builder with [maxLength] as the maximum number of bits allowed
    /// for the integer.
    ///
    /// If [name] is passed, it's used in error reporting.
    VarintBuilder(this._maxLength, [this._name]);
  
    /// Parses [byte] as a continuation of the varint.
    ///
    /// If this byte completes the varint, returns the parsed int. Otherwise,
    /// returns null.
    ///
    /// Throws a [ProtocolError] if [byte] causes the length of the varint to
    /// exceed [_maxLength]. Throws a [StateError] if called after [add] has
    /// already returned a value.
    int? add(int byte) {
      if (_done) {
        throw StateError("VarintBuilder.add() has already returned a value.");
      }
  
      // Varints encode data in the 7 lower bits of each byte, which we access by
      // masking with 0x7f = 0b01111111.
      _value += (byte & 0x7f) << _bits;
      _bits += 7;
  
      // If the byte is higher than 0x7f = 0b01111111, that means its high bit is
      // set which and so there are more bytes to consume before we know the full
      // value.
      if (byte > 0x7f) {
        if (_bits >= _maxLength) {
          _done = true;
          throw _tooLong();
        } else {
          return null;
        }
      } else {
        _done = true;
        if (_bits > _maxLength && _value >= 1 << _maxLength) {
          // [_maxLength] is probably not divisible by 7, so we need to check that
          // the highest bits of the final byte aren't set.
          throw _tooLong();
        } else {
          return _value;
        }
      }
    }
  
    /// Resets this to its initial state so it can build another varint.
    void reset() {
      _value = 0;
      _bits = 0;
      _done = false;
    }
  
    /// Returns a [ProtocolError] indicating that the varint exceeded [_maxLength].
    ProtocolError _tooLong() => parseError(
          "Varint ${_name == null ? '' : '$_name '}was longer than "
          "$_maxLength bits.",
        );
  }
  