in backend/encoding.js [667:737]
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}
}