'use strict';
/**
* Record objects that pass by in a stream. If the same object is used more
* than once, it can be value-shared using shared values.
*
* @see {@link http://cbor.schmorp.de/value-sharing}
*/
class ObjectRecorder {
constructor() {
this.clear();
}
/**
* Clear all of the objects that have been seen. Revert to recording mode.
*/
clear() {
this.map = new WeakMap();
this.count = 0;
this.recording = true;
}
/**
* Stop recording.
*/
stop() {
this.recording = false;
}
/**
* Determine if wrapping a tag 28 or 29 around an object that has been
* reused is appropriate. This method stores state for which objects have
* been seen.
*
* @param {object} obj Any object about to be serialized.
* @returns {number} If recording: -1 for first use, index for second use.
* If not recording, -1 for never-duplicated, -2 for first use, index for
* subsequent uses.
* @throws {Error} Recording does not match playback.
*/
check(obj) {
const val = this.map.get(obj);
if (val) {
if (val.length > 1) {
if (val[0] || this.recording) {
return val[1];
}
val[0] = true;
return ObjectRecorder.FIRST;
}
if (!this.recording) {
return ObjectRecorder.NEVER;
}
val.push(this.count++);
// Second use while recording
return val[1];
}
if (!this.recording) {
throw new Error('New object detected when not recording');
}
this.map.set(obj, [false]);
// First use while recording
return ObjectRecorder.NEVER;
}
}
ObjectRecorder.NEVER = -1;
ObjectRecorder.FIRST = -2;
module.exports = ObjectRecorder;