thorish
Version:
This is a library of useful JS concepts and data structures for Node and the browser. It it, unashamedly, a dumping ground for code needed by [@samthor](https://twitter.com/samthor)'s projects.
111 lines (110 loc) • 3.12 kB
TypeScript
/**
* @fileoverview Derived from @josephg's implementation here: https://github.com/josephg/jumprope
*
* MIT license etc etc
*/
/**
* Returns a value [1,31] inclusive, with 50% chance of 1, 25% chance of 2, 12.5% chance of 3, ...
*/
export declare const randomHeight: () => number;
export type RopeLookup<K, T> = {
data: T;
length: number;
id: K;
prevId: K;
nextId: K;
};
export type RopeRead<T> = {
out: T[];
len: number[];
};
/**
* Actually an 'immutable rope'.
*
* Parts cannot be modified, because they are objects with length that have some kind of rendering that this class won't understand.
*/
export declare class Rope<K, T> {
private _length;
private head;
private tail;
private readonly zeroId;
private byId;
private readonly _nodesBuffer;
private readonly _subBuffer;
private readonly _nodesPool;
/**
* Clones this {@link Rope} using {@link structuredClone}.
*/
clone(): Rope<K, T>;
constructor(zeroId: K, root: T);
length(): number;
last(): K;
count(): number;
/**
* Find the length between these two valid IDs.
*
* This isn't a substitute for {@link compare} as zero length entries are allowed, so this won't return which one is first.
*
* Currently just calls {@link find} twice.
*/
lengthBetween(low: K, high: K): number;
/**
* Prints out the rope for debugging.
*/
_debug(): void;
[Symbol.iterator](): Generator<T, void, unknown>;
/**
* Finds the position after the given ID.
*
* Perf: `O(logn)-ish`.
*/
find(ropeId: K): number;
has(ropeId: K): boolean;
lookup(ropeId: K): RopeLookup<K, T>;
/**
* Find the ID for the given position, and the offset from the end of that ID.
* Always returns a valid value, is clamped to edge.
*
* By default, this will be the left-most ID that contains the position (even 'at end').
* For example, looking up `offset=0` in an already-used rope will always yield `id=0`, as it has zero length.
*
* Specify the `biasEnd` parameter to flip this behavior.
*/
byPosition(position: number, biasAfter?: boolean): {
id: K;
offset: number;
};
/**
* Reduced version of `rseek` for various purposes...
*
* Result placed in `_nodesBuffer`.
*/
private rseekNodes;
/**
* Adjust the given entry's data/length.
*/
adjust(id: K, data: T, length: number): void;
/**
* Inserts a node after a previous node.
*/
insertAfter(afterId: K, newId: K, length: number, data: T): void;
/**
* Deletes the given ID from this rope.
*/
deleteById(id: K): T[];
/**
* Deletes after the given ID until the target ID.
*/
deleteTo(afterId: K, untilId: K): T[];
private insertIntoPool;
/**
* Is the ID in `a` before the ID in `b`?
*/
before(a: K, b: K): boolean;
compare(a: K, b: K): number;
iter(afterId: K): Iterable<{
id: K;
data: T;
}>;
read(from: K, to?: K): RopeRead<T> | undefined;
}