Tldraw/packages/editor/src/lib/editor/managers/Stack.ts

69 wiersze
1.3 KiB
TypeScript

import { EMPTY_ARRAY } from 'signia'
export type Stack<T> = StackItem<T> | EmptyStackItem<T>
export function stack<T>(items?: Array<T>): Stack<T> {
if (items) {
let result = EMPTY_STACK_ITEM as Stack<T>
while (items.length) {
result = result.push(items.pop()!)
}
return result
}
return EMPTY_STACK_ITEM as any
}
class EmptyStackItem<T> implements Iterable<T> {
readonly length = 0
readonly head = null
readonly tail: Stack<T> = this
push(head: T): Stack<T> {
return new StackItem<T>(head, this)
}
toArray() {
return EMPTY_ARRAY
}
[Symbol.iterator]() {
return {
next() {
return { value: undefined, done: true as const }
},
}
}
}
const EMPTY_STACK_ITEM = new EmptyStackItem()
class StackItem<T> implements Iterable<T> {
length: number
constructor(public readonly head: T, public readonly tail: Stack<T>) {
this.length = tail.length + 1
}
push(head: T): Stack<T> {
return new StackItem(head, this)
}
toArray() {
return Array.from(this)
}
[Symbol.iterator]() {
let stack = this as Stack<T>
return {
next() {
if (stack.length) {
const value = stack.head!
stack = stack.tail
return { value, done: false as const }
} else {
return { value: undefined, done: true as const }
}
},
}
}
}