signalis/src/input_buffer.ts
2025-04-30 21:51:53 -05:00

92 lines
1.9 KiB
TypeScript

import { int32, int64, PackedVector2Array, Vector2 } from 'godot'
export class InputBufferError extends Error {
constructor(message: string) {
super(`InputBufferError: ${message}`)
}
static empty() {
return new InputBufferError('cannot perform operation, buffer is empty')
}
static outOfBounds(index: int64) {
return new InputBufferError(`cannot access ${index}: index out of bounds`)
}
}
export default class InputBuffer {
readonly capacity: int32
private _buffer: PackedVector2Array
private _head: int32 = 0
private _tail: int32 = 0
private _size: int32 = 0
constructor(capacity: int32) {
this.capacity = capacity
this._buffer = new PackedVector2Array()
this._buffer.resize(capacity)
this._buffer.fill(Vector2.ZERO)
}
is_empty() {
return this._size === 0
}
is_full() {
return this._size === this.capacity
}
push(value: Vector2) {
this._buffer.set_indexed(this._head, value)
this._head = (this._head + 1) % this.capacity
if (this.is_full()) {
this._tail = this._head
} else {
this._size += 1
}
}
pop(): Vector2 {
if (this.is_empty()) {
throw InputBufferError.empty()
}
const value = this.tail()
this._tail = (this._tail + 1) % this.capacity
this._size += 1
return value
}
at(index: int64) {
if (index >= this._size) {
throw InputBufferError.outOfBounds(index)
}
const n = index < 0 ? this._head - index : this._tail + index
const idx = n % this.capacity
return this._buffer.get_indexed(idx)
}
size() {
return this._size
}
head() {
return this._buffer.get_indexed(this._head)
}
tail() {
return this._buffer.get_indexed(this._tail)
}
slice(begin: int64, end?: int64) {
return this._buffer.slice(begin, end)
}
clear() {
this._size = 0
this._head = 0
this._tail = 0
}
}