copyFrom(decoder, options = {}) {
    const { count, sumValues, sumShift } = options
    if (!(decoder instanceof RLEDecoder) || decoder.type !== this.type) {
      throw new TypeError("incompatible type of decoder")
    }
    let remaining = typeof count === "number" ? count : Number.MAX_SAFE_INTEGER
    let nonNullValues = 0,
      sum = 0
    if (count && remaining > 0 && decoder.done)
      throw new RangeError(`cannot copy ${count} values`)
    if (remaining === 0 || decoder.done)
      return sumValues ? { nonNullValues, sum } : { nonNullValues }

    // Copy a value so that we have a well-defined starting state. NB: when super.copyFrom() is
    // called by the DeltaEncoder subclass, the following calls to readValue() and appendValue()
    // refer to the overridden methods, while later readRecord(), readRawValue() and _appendValue()
    // calls refer to the non-overridden RLEDecoder/RLEEncoder methods.
    let firstValue = decoder.readValue()
    if (firstValue === null) {
      const numNulls = Math.min(decoder.count + 1, remaining)
      remaining -= numNulls
      decoder.count -= numNulls - 1
      this.appendValue(null, numNulls)
      if (count && remaining > 0 && decoder.done)
        throw new RangeError(`cannot copy ${count} values`)
      if (remaining === 0 || decoder.done)
        return sumValues ? { nonNullValues, sum } : { nonNullValues }
      firstValue = decoder.readValue()
      if (firstValue === null)
        throw new RangeError("null run must be followed by non-null value")
    }
    this.appendValue(firstValue)
    remaining--
    nonNullValues++
    if (sumValues) sum += sumShift ? firstValue >>> sumShift : firstValue
    if (count && remaining > 0 && decoder.done)
      throw new RangeError(`cannot copy ${count} values`)
    if (remaining === 0 || decoder.done)
      return sumValues ? { nonNullValues, sum } : { nonNullValues }

    // Copy data at the record level without expanding repetitions
    let firstRun = decoder.count > 0
    while (remaining > 0 && !decoder.done) {
      if (!firstRun) decoder.readRecord()
      const numValues = Math.min(decoder.count, remaining)
      decoder.count -= numValues

      if (decoder.state === "literal") {
        nonNullValues += numValues
        for (let i = 0; i < numValues; i++) {
          if (decoder.done) throw new RangeError("incomplete literal")
          const value = decoder.readRawValue()
          if (value === decoder.lastValue)
            throw new RangeError(
              "Repetition of values is not allowed in literal",
            )
          decoder.lastValue = value
          this._appendValue(value)
          if (sumValues) sum += sumShift ? value >>> sumShift : value
        }
      } else if (decoder.state === "repetition") {
        nonNullValues += numValues
        if (sumValues)
          sum +=
            numValues *
            (sumShift ? decoder.lastValue >>> sumShift : decoder.lastValue)
        const value = decoder.lastValue
        this._appendValue(value)
        if (numValues > 1) {
          this._appendValue(value)
          if (this.state !== "repetition")
            throw new RangeError(`Unexpected state ${this.state}`)
          this.count += numValues - 2
        }
      } else if (decoder.state === "nulls") {
        this._appendValue(null)
        if (this.state !== "nulls")
          throw new RangeError(`Unexpected state ${this.state}`)
        this.count += numValues - 1
      }

      firstRun = false
      remaining -= numValues
    }
    if (count && remaining > 0 && decoder.done)
      throw new RangeError(`cannot copy ${count} values`)
    return sumValues ? { nonNullValues, sum } : { nonNullValues }
  }
Copies values from the RLEDecoder `decoder` into this encoder. The `options` object may
contain the following keys:
 - `count`: The number of values to copy. If not specified, copies all remaining values.
 - `sumValues`: If true, the function computes the sum of all numeric values as they are
   copied (null values are counted as zero), and returns that number.
 - `sumShift`: If set, values are shifted right by `sumShift` bits before adding to the sum.

Returns an object of the form `{nonNullValues, sum}` where `nonNullValues` is the number of
non-null values copied, and `sum` is the sum (only if the `sumValues` option is set).