| 10 | } |
| 11 | |
| 12 | export class LRU<T> implements Cache<T> { |
| 13 | private cache: Record<string, Node<T>> = {} |
| 14 | private head: Node<T> |
| 15 | private tail: Node<T> |
| 16 | |
| 17 | constructor ( |
| 18 | public limit: number, |
| 19 | public size = 0 |
| 20 | ) { |
| 21 | this.head = new Node<T>('HEAD', null as any, null as any, null as any) |
| 22 | this.tail = new Node<T>('TAIL', null as any, null as any, null as any) |
| 23 | this.head.next = this.tail |
| 24 | this.tail.prev = this.head |
| 25 | } |
| 26 | |
| 27 | write (key: string, value: T) { |
| 28 | if (this.cache[key]) { |
| 29 | this.cache[key].value = value |
| 30 | } else { |
| 31 | const node = new Node(key, value, this.head.next, this.head) |
| 32 | this.head.next.prev = node |
| 33 | this.head.next = node |
| 34 | |
| 35 | this.cache[key] = node |
| 36 | this.size++ |
| 37 | this.ensureLimit() |
| 38 | } |
| 39 | } |
| 40 | |
| 41 | read (key: string): T | undefined { |
| 42 | if (!this.cache[key]) return |
| 43 | const { value } = this.cache[key] |
| 44 | this.remove(key) |
| 45 | this.write(key, value) |
| 46 | return value |
| 47 | } |
| 48 | |
| 49 | remove (key: string) { |
| 50 | const node = this.cache[key] |
| 51 | node.prev.next = node.next |
| 52 | node.next.prev = node.prev |
| 53 | delete this.cache[key] |
| 54 | this.size-- |
| 55 | } |
| 56 | |
| 57 | clear () { |
| 58 | this.head.next = this.tail |
| 59 | this.tail.prev = this.head |
| 60 | this.size = 0 |
| 61 | this.cache = {} |
| 62 | } |
| 63 | |
| 64 | private ensureLimit () { |
| 65 | if (this.size > this.limit) this.remove(this.tail.prev.key) |
| 66 | } |
| 67 | } |
nothing calls this directly
no outgoing calls
no test coverage detected