evnty
Version:
Async-first, reactive event handling library for complex event flows in browser and Node.js
1 lines • 11.4 kB
Source Map (JSON)
{"version":3,"sources":["../src/ring-buffer.ts"],"sourcesContent":["const DEFAULT_CAPACITY = 8;\n\n/**\n * @internal Fixed-size circular buffer that grows in powers of two when full.\n * Provides O(1) push/pop/shift/unshift and supports wrap-around iteration.\n */\nexport class RingBuffer<T> {\n #buffer: Array<T | undefined>;\n #head = 0;\n #tail = 0;\n #mask: number;\n #length = 0;\n #shiftCount = 0;\n\n readonly [Symbol.toStringTag] = 'RingBuffer';\n\n /**\n * Creates a RingBuffer from an array of values.\n * @param values - The values to initialize the buffer with\n * @returns A new RingBuffer containing the values\n */\n static from<T>(values: T[]): RingBuffer<T> {\n const n = values.length;\n const ring = new RingBuffer<T>(n + 1);\n for (let i = 0; i < n; i++) {\n ring.#buffer[i] = values[i];\n }\n ring.#head = 0;\n ring.#tail = n;\n ring.#length = n;\n\n return ring;\n }\n\n /**\n * Creates a ring buffer with at least the requested capacity (rounded up to power of two).\n */\n constructor(capacity: number = DEFAULT_CAPACITY) {\n const size = Math.max(1 << (32 - Math.clz32(capacity - 1)), DEFAULT_CAPACITY);\n this.#buffer = new Array<T>(size);\n this.#mask = size - 1;\n }\n\n /**\n * The number of items currently in the buffer.\n */\n get length(): number {\n return this.#length;\n }\n\n /**\n * Logical position of the buffer's left edge (total items ever shifted).\n * Monotonically increasing - useful for cursor-based consumers.\n */\n get left(): number {\n return this.#shiftCount;\n }\n\n /**\n * Logical position of the buffer's right edge (left + length).\n * Represents the next logical index for push.\n */\n get right(): number {\n return this.#shiftCount + this.#length;\n }\n\n /**\n * Returns true if the buffer has wrapped around (head > tail).\n */\n isWrapped(): boolean {\n return this.#head > this.#tail;\n }\n\n /**\n * Returns true if the buffer contains no items.\n */\n isEmpty(): boolean {\n return this.#tail === this.#head;\n }\n\n /**\n * Ensures the underlying storage can hold at least `capacity` items.\n * Preserves existing order when the buffer is wrapped.\n */\n grow(capacity: number = this.#mask + 1): void {\n const buffer = this.#buffer;\n const bufferLength = buffer.length;\n if (bufferLength >= capacity + 1) {\n return;\n }\n const size = 1 << (32 - Math.clz32(capacity));\n this.#buffer.length = size;\n\n const oldTail = this.#tail;\n if (oldTail < this.#head) {\n for (let i = 0; i < oldTail; i++) {\n buffer[bufferLength + i] = buffer[i];\n buffer[i] = undefined;\n }\n this.#tail = bufferLength + oldTail;\n }\n\n this.#mask = size - 1;\n }\n\n /**\n * Appends a value at the tail, growing if full.\n */\n push(value: T) {\n const nextTail = (this.#tail + 1) & this.#mask;\n if (nextTail === this.#head) {\n this.grow(this.#mask + 2);\n this.#buffer[this.#tail] = value;\n this.#tail = (this.#tail + 1) & this.#mask;\n } else {\n this.#buffer[this.#tail] = value;\n this.#tail = nextTail;\n }\n this.#length++;\n return this;\n }\n\n /**\n * Inserts a value at the head, growing if full.\n */\n unshift(value: T): this {\n const newHead = (this.#head - 1) & this.#mask;\n if (newHead === this.#tail) {\n this.grow(this.#mask + 2);\n this.#head = (this.#head - 1) & this.#mask;\n } else {\n this.#head = newHead;\n }\n this.#buffer[this.#head] = value;\n this.#length++;\n return this;\n }\n\n /**\n * Returns the value at the given index without removing it.\n * Index 0 is the head, index length-1 is the tail.\n */\n peek(index: number): T | undefined {\n if (index < 0 || index >= this.#length) {\n return undefined;\n }\n return this.#buffer[(this.#head + index) & this.#mask];\n }\n\n /**\n * Returns the value at the given logical index without removing it.\n * Logical index is based on total push/shift history (cursor-friendly).\n */\n peekAt(logicalIndex: number): T | undefined {\n return this.peek(logicalIndex - this.#shiftCount);\n }\n\n /**\n * Removes and returns the value at the head, or undefined if empty.\n */\n shift(): T | undefined {\n if (this.#head === this.#tail) {\n return undefined;\n }\n const value = this.#buffer[this.#head];\n this.#buffer[this.#head] = undefined;\n this.#head = (this.#head + 1) & this.#mask;\n this.#length--;\n this.#shiftCount++;\n return value;\n }\n\n /**\n * Removes n values from the head.\n */\n shiftN(n: number): number {\n const count = Math.min(n, this.#length);\n for (let i = 0; i < count; i++) {\n this.#buffer[this.#head] = undefined;\n this.#head = (this.#head + 1) & this.#mask;\n }\n this.#length -= count;\n this.#shiftCount += count;\n return count;\n }\n\n /**\n * Removes and returns the value at the tail, or undefined if empty.\n */\n pop(): T | undefined {\n if (this.#head === this.#tail) {\n return undefined;\n }\n this.#tail = (this.#tail - 1) & this.#mask;\n const value = this.#buffer[this.#tail];\n this.#buffer[this.#tail] = undefined;\n this.#length--;\n return value;\n }\n\n /**\n * Clears all entries. Optionally keeps current capacity instead of resetting to default.\n */\n clear(preserveCapacity = false): this {\n const capacity = preserveCapacity ? this.#buffer.length : DEFAULT_CAPACITY;\n this.#buffer.length = 0;\n this.#buffer.length = capacity;\n this.#head = 0;\n this.#tail = 0;\n this.#length = 0;\n this.#shiftCount = 0;\n this.#mask = capacity - 1;\n return this;\n }\n\n [Symbol.iterator](): Iterator<T, void, unknown> {\n const buffer = this.#buffer;\n const mask = this.#mask;\n const length = this.#length;\n let count = 0;\n let idx = this.#head;\n return {\n next: (): IteratorResult<T> => {\n if (count >= length) {\n return { done: true, value: undefined };\n }\n const value = buffer[idx]!;\n idx = (idx + 1) & mask;\n count++;\n return { done: false, value };\n },\n };\n }\n}\n"],"names":["RingBuffer","DEFAULT_CAPACITY","Symbol","toStringTag","from","values","n","length","ring","i","capacity","size","Math","max","clz32","Array","left","right","isWrapped","isEmpty","grow","buffer","bufferLength","oldTail","undefined","push","value","nextTail","unshift","newHead","peek","index","peekAt","logicalIndex","shift","shiftN","count","min","pop","clear","preserveCapacity","iterator","mask","idx","next","done"],"mappings":"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"}