mtcute/packages/core/src/utils/lru-set.ts
Alina Tumanova f5976a2d74
ESM + end-to-end tests (#11)
* feat: moved tl-runtime to esm and native ArrayBuffers

* feat: migration to esm

* fix(core): web-related fixes

* test: finally, some good fucking e2e

* chore: fixed linters etc

* ci: added e2e to ci

* build(tl): fixed gen-code on node 20

* fix: codegen Uint8Array, not Buffer

never `git reset --hard` kids

* build: only do type-aware linting for `packages/*`

* build: ignore no-unresolved in ci for e2e

* fix: node 16 doesn't have subtle crypto apparently?

* fix(tests): use Uint8Array

for gods sake please can i just merge this already

* ci: don't parallel tasks in ci

because machines are utter garbage and it may just randomly break

* ci: pass secrets to e2e tests

* ci: separate cli command for ci

apparently im retarded

* fix: run codegen in e2e

im actually retarded

* ci: more fixes for e2e

* ci: debugging stuff

* ci: still debugging

* ci: hopefully fix ci???
2023-10-16 19:23:53 +03:00

65 lines
1.7 KiB
TypeScript

/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/no-unsafe-argument */
// ^^ because of performance reasons
import Long from 'long'
import { LongSet } from './long-utils.js'
interface OneWayLinkedList<T> {
v: T
n?: OneWayLinkedList<T>
}
/**
* Simple class implementing LRU-like behaviour for a Set.
*
* Note: this is not exactly LRU, but rather "least recently added"
* and doesn't mark items as recently added if they are already in the set.
* This is enough for our use case, so we don't bother with more complex implementation.
*
* Used to store recently received message IDs in {@link SessionConnection}
*
* Uses one-way linked list internally to keep track of insertion order
*/
export class LruSet<T extends string | number | Long> {
private _capacity: number
private _first?: OneWayLinkedList<T>
private _last?: OneWayLinkedList<T>
private _set: Set<T> | LongSet
constructor(capacity: number, forLong = false) {
this._capacity = capacity
this._set = forLong ? new LongSet() : new Set()
}
clear() {
this._first = this._last = undefined
this._set.clear()
}
add(val: T) {
if (this._set.has(val as any)) return
if (!this._first) this._first = { v: val }
if (!this._last) this._last = this._first
else {
this._last.n = { v: val }
this._last = this._last.n
}
this._set.add(val as any)
if (this._set.size > this._capacity && this._first) {
// remove least recently used
this._set.delete(this._first.v as any)
this._first = this._first.n
}
}
has(val: T) {
return this._set.has(val as any)
}
}