refactor: format code
[poolifier.git] / src / fixed-queue.ts
CommitLineData
9183b880
JB
1import {
2 defaultQueueSize,
3 type FixedQueueNode,
4 type IFixedQueue,
5} from './utility-types.js'
097dea68
JB
6
7/**
8 * Fixed queue.
9 * @typeParam T - Type of fixed queue data.
10 * @internal
11 */
12export class FixedQueue<T> implements IFixedQueue<T> {
13 private start!: number
14 /** @inheritdoc */
15 public readonly capacity: number
16 /** @inheritdoc */
17 public size!: number
18 /** @inheritdoc */
19 public nodeArray: FixedQueueNode<T>[]
20
21 /**
22 * Constructs a fixed queue.
23 * @param size - Fixed queue size. @defaultValue defaultQueueSize
24 * @returns FixedQueue.
25 */
26 constructor (size: number = defaultQueueSize) {
27 this.checkSize(size)
28 this.capacity = size
29 this.nodeArray = new Array<FixedQueueNode<T>>(this.capacity)
30 this.clear()
31 }
32
33 /** @inheritdoc */
34 public empty (): boolean {
35 return this.size === 0
36 }
37
38 /** @inheritdoc */
39 public full (): boolean {
40 return this.size === this.capacity
41 }
42
43 /** @inheritdoc */
44 public enqueue (data: T, priority?: number): number {
45 if (this.full()) {
46 throw new Error('Priority queue is full')
47 }
48 let index = this.start + this.size
49 if (index >= this.capacity) {
50 index -= this.capacity
51 }
52 this.nodeArray[index] = { data, priority: priority ?? 0 }
53 return ++this.size
54 }
55
56 /** @inheritdoc */
57 public get (index: number): T | undefined {
58 if (this.empty() || index >= this.size) {
59 return undefined
60 }
61 index += this.start
62 if (index >= this.capacity) {
63 index -= this.capacity
64 }
65 return this.nodeArray[index].data
66 }
67
68 /** @inheritdoc */
69 public dequeue (): T | undefined {
70 if (this.empty()) {
71 return undefined
72 }
73 const index = this.start
74 --this.size
75 ++this.start
76 if (this.start === this.capacity) {
77 this.start = 0
78 }
79 return this.nodeArray[index].data
80 }
81
82 /** @inheritdoc */
83 public clear (): void {
84 this.start = 0
85 this.size = 0
86 }
87
88 /** @inheritdoc */
89 public [Symbol.iterator] (): Iterator<T> {
90 let index = this.start
91 let i = 0
92 return {
93 next: () => {
94 if (i >= this.size) {
95 return {
96 value: undefined,
97 done: true,
98 }
99 }
100 const value = this.nodeArray[index].data
101 ++index
102 ++i
103 if (index === this.capacity) {
104 index = 0
105 }
106 return {
107 value,
108 done: false,
109 }
110 },
111 }
112 }
113
114 /**
115 * Checks the fixed queue size.
116 * @param size - Queue size.
117 */
118 private checkSize (size: number): void {
119 if (!Number.isSafeInteger(size)) {
120 throw new TypeError(
121 `Invalid fixed queue size: '${size.toString()}' is not an integer`
122 )
123 }
124 if (size < 0) {
9183b880 125 throw new RangeError(`Invalid fixed queue size: ${size.toString()} < 0`)
097dea68
JB
126 }
127 }
128}