@rimbu/sorted
Version:
Immutable SortedMap and SortedSet implementations for TypeScript
403 lines (402 loc) • 19 kB
text/typescript
import { EmptyBase, NonEmptyBase } from '@rimbu/collection-types/map-custom';
import { IndexRange, OptLazy, TraverseState } from '@rimbu/common';
import { Stream } from '@rimbu/stream';
/**
* Base implementation used for empty sorted collections.<br/>
* <br/>
* Provides the index‑based operations used by `SortedMap` / `SortedSet`
* instances when they are empty and always returns the given fallback value.
*/
export declare class SortedEmpty extends EmptyBase {
min<O>(otherwise?: OptLazy<O>): O;
max<O>(otherwise?: OptLazy<O>): O;
getAtIndex<O>(index: number, otherwise?: OptLazy<O>): O;
take(): any;
drop(): any;
sliceIndex(): any;
}
/**
* Abstract base class for non‑empty sorted collections.<br/>
* <br/>
* It exposes the common index‑based operations and structural mutation
* helpers shared by the sorted map and set node implementations.
* @typeparam E - the stored entry type
* @typeparam TS - the concrete non‑empty node type
*/
export declare abstract class SortedNonEmptyBase<E, TS extends SortedNonEmptyBase<E, TS>> extends NonEmptyBase<E> {
abstract getAtIndex<O>(index: number, otherwise?: OptLazy<O>): E | O;
abstract get entries(): readonly E[];
abstract takeInternal(amount: number): TS;
abstract dropInternal(amount: number): TS;
abstract mutateSplitRight(index?: number): [E, TS];
abstract mutateGiveToLeft(left: TS, toLeft: E): [E, TS];
abstract mutateGiveToRight(right: TS, toRight: E): [E, TS];
abstract mutateGetFromLeft(left: TS, toMe: E): [E, TS];
abstract mutateGetFromRight(right: TS, toMe: E): [E, TS];
abstract mutateJoinLeft(left: TS, entry: E): void;
abstract mutateJoinRight(right: TS, entry: E): void;
abstract deleteMin(): [E, TS];
abstract deleteMax(): [E, TS];
get mutateEntries(): E[];
}
/**
* Describes the mutable surface of a leaf node used by the helper
* functions that transform B‑tree leaves.
* @typeparam TS - the concrete leaf type
* @typeparam E - the stored entry type
*/
export interface LeafMutateSource<TS extends LeafMutateSource<TS, E>, E> {
mutateEntries: E[];
entries: readonly E[];
copy(entries: readonly E[]): TS;
}
/**
* Removes and returns the minimum entry from the given leaf node while
* returning the updated leaf.
* @param source - the leaf node to operate on
*/
export declare function leafDeleteMin<S extends LeafMutateSource<S, E>, E>(source: S): [E, S];
/**
* Removes and returns the maximum entry from the given leaf node while
* returning the updated leaf.
* @param source - the leaf node to operate on
*/
export declare function leafDeleteMax<S extends LeafMutateSource<S, E>, E>(source: S): [E, S];
/**
* Splits the given leaf node into two nodes and returns the promoted
* separator entry together with the newly created right node.<br/>
* <br/>
* The split position can be customised through the optional `index`.
* @param source - the leaf node to split
* @param index - (optional) the split index, defaults to the middle entry
*/
export declare function leafMutateSplitRight<S extends LeafMutateSource<S, E>, E>(source: S, index?: number): [E, S];
/**
* Moves the given `toLeft` entry from `source` to the left sibling and
* returns the separator entry that should be stored in the parent node.
* @param source - the leaf that donates an entry to the left sibling
* @param left - the left sibling leaf to receive the entry
* @param toLeft - the entry that must end up in the left sibling
*/
export declare function leafMutateGiveToLeft<S extends LeafMutateSource<S, E>, E>(source: S, left: S, toLeft: E): [E, S];
/**
* Moves the given `toRight` entry from `source` to the right sibling and
* returns the separator entry that should be stored in the parent node.
* @param source - the leaf that donates an entry to the right sibling
* @param right - the right sibling leaf to receive the entry
* @param toRight - the entry that must end up in the right sibling
*/
export declare function leafMutateGiveToRight<S extends LeafMutateSource<S, E>, E>(source: S, right: S, toRight: E): [E, S];
/**
* Pulls an entry from the left sibling into `source` and returns the
* separator entry that should be stored in the parent node.
* @param source - the leaf receiving an entry
* @param left - the left sibling leaf to donate an entry
* @param toMe - the entry that must end up in `source`
*/
export declare function leafMutateGetFromLeft<S extends LeafMutateSource<S, E>, E>(source: S, left: S, toMe: E): [E, S];
/**
* Pulls an entry from the right sibling into `source` and returns the
* separator entry that should be stored in the parent node.
* @param source - the leaf receiving an entry
* @param right - the right sibling leaf to donate an entry
* @param toMe - the entry that must end up in `source`
*/
export declare function leafMutateGetFromRight<S extends LeafMutateSource<S, E>, E>(source: S, right: S, toMe: E): [E, S];
/**
* Joins the given left sibling leaf and `source` into a single leaf by
* inserting the given separator `entry` between them.
* @param source - the right leaf that will absorb the left sibling
* @param left - the left sibling leaf to merge
* @param entry - the separator entry from the parent
*/
export declare function leafMutateJoinLeft<S extends LeafMutateSource<S, E>, E>(source: S, left: S, entry: E): void;
/**
* Joins the given right sibling leaf and `source` into a single leaf by
* inserting the given separator `entry` between them.
* @param source - the left leaf that will absorb the right sibling
* @param right - the right sibling leaf to merge
* @param entry - the separator entry from the parent
*/
export declare function leafMutateJoinRight<S extends LeafMutateSource<S, E>, E>(source: S, right: S, entry: E): void;
/**
* Describes the minimal interface required from an inner B‑tree node
* used by the helper functions that transform inner nodes.
* @typeparam E - the stored entry type
*/
export interface InnerChild<E> {
readonly size: number;
getAtIndex<O>(index: number, otherwise?: OptLazy<O>): E | O;
stream(options?: {
reversed?: boolean;
}): Stream<E>;
streamSliceIndex(range: IndexRange, options?: {
reversed?: boolean;
}): Stream<E>;
readonly entries: readonly E[];
takeInternal(amount: number): InnerChild<E>;
dropInternal(amount: number): InnerChild<E>;
deleteMin(): [E, InnerChild<E>];
deleteMax(): [E, InnerChild<E>];
mutateGiveToLeft(left: InnerChild<E>, toLeft: E): [E, InnerChild<E>];
mutateGiveToRight(right: InnerChild<E>, toRight: E): [E, InnerChild<E>];
mutateSplitRight(index?: number): [E, InnerChild<E>];
mutateJoinLeft(left: InnerChild<E>, entry: E): void;
mutateJoinRight(right: InnerChild<E>, entry: E): void;
mutateGetFromLeft(left: InnerChild<E>, toMe: E): [E, InnerChild<E>];
mutateGetFromRight(right: InnerChild<E>, toMe: E): [E, InnerChild<E>];
}
/**
* Describes the mutable surface of an inner node used by the inner
* transformation helper functions.
* @typeparam TS - the concrete inner node type
* @typeparam E - the stored entry type
*/
export interface InnerMutateSource<TS extends InnerMutateSource<TS, E>, E> {
readonly context: {
readonly minEntries: number;
readonly maxEntries: number;
inner(entries: readonly E[], children: readonly InnerChild<E>[], size: number): TS;
};
size: number;
entries: readonly E[];
mutateEntries: E[];
children: readonly InnerChild<E>[];
mutateChildren: InnerChild<E>[];
stream(options?: {
reversed?: boolean;
}): Stream.NonEmpty<E>;
copy(entries?: readonly E[], children?: readonly InnerChild<E>[], size?: number): TS;
addInternal(entry: E): TS;
normalizeDownsizeChild(childIndex: number, newChild: InnerChild<E>, newSize: number): TS;
normalizeIncreaseChild(childIndex: number, newChild: InnerChild<E>, newSize: number): TS;
}
/**
* Removes and returns the minimum entry from the left‑most child of the
* given inner node and returns the updated node.
* @param source - the inner node to operate on
*/
export declare function innerDeleteMin<S extends InnerMutateSource<S, E>, E>(source: S): [E, S];
/**
* Removes and returns the maximum entry from the right‑most child of the
* given inner node and returns the updated node.
* @param source - the inner node to operate on
*/
export declare function innerDeleteMax<S extends InnerMutateSource<S, E>, E>(source: S): [E, S];
/**
* Splits the given inner node into two nodes and returns the promoted
* separator entry together with the new right node.<br/>
* <br/>
* The split position can be customised through the optional `index`.
* @param source - the inner node to split
* @param index - (optional) the split index, defaults to the middle entry
*/
export declare function innerMutateSplitRight<S extends InnerMutateSource<S, E>, E>(source: S, index?: number): [E, S];
/**
* Moves the given `toLeft` entry and its child from `source` to the left
* sibling and returns the separator entry that should be stored in the
* parent node.
* @param source - the inner node donating an entry to the left sibling
* @param left - the left sibling node to receive the entry and child
* @param toLeft - the entry that must end up in the left sibling
*/
export declare function innerMutateGiveToLeft<S extends InnerMutateSource<S, E>, E>(source: S, left: S, toLeft: E): [E, S];
/**
* Moves the given `toRight` entry and its child from `source` to the right
* sibling and returns the separator entry that should be stored in the
* parent node.
* @param source - the inner node donating an entry to the right sibling
* @param right - the right sibling node to receive the entry and child
* @param toRight - the entry that must end up in the right sibling
*/
export declare function innerMutateGiveToRight<S extends InnerMutateSource<S, E>, E>(source: S, right: S, toRight: E): [E, S];
/**
* Pulls an entry and child from the left sibling into `source` and returns
* the separator entry that should be stored in the parent node.
* @param source - the inner node receiving the entry and child
* @param left - the left sibling node to donate the entry and child
* @param toMe - the entry that must end up in `source`
*/
export declare function innerMutateGetFromLeft<S extends InnerMutateSource<S, E>, E>(source: S, left: S, toMe: E): [E, S];
/**
* Pulls an entry and child from the right sibling into `source` and returns
* the separator entry that should be stored in the parent node.
* @param source - the inner node receiving the entry and child
* @param right - the right sibling node to donate the entry and child
* @param toMe - the entry that must end up in `source`
*/
export declare function innerMutateGetFromRight<S extends InnerMutateSource<S, E>, E>(source: S, right: S, toMe: E): [E, S];
/**
* Joins the given left sibling inner node and `source` into a single node by
* inserting the given separator `entry` between them.
* @param source - the right inner node that will absorb the left sibling
* @param left - the left sibling node to merge
* @param entry - the separator entry from the parent
*/
export declare function innerMutateJoinLeft<S extends InnerMutateSource<S, E>, E>(source: S, left: S, entry: E): void;
/**
* Joins the given right sibling inner node and `source` into a single node by
* inserting the given separator `entry` between them.
* @param source - the left inner node that will absorb the right sibling
* @param right - the right sibling node to merge
* @param entry - the separator entry from the parent
*/
export declare function innerMutateJoinRight<S extends InnerMutateSource<S, E>, E>(source: S, right: S, entry: E): void;
/**
* Normalises the given child after it has decreased in size so that it
* satisfies the minimum entry constraint of the B‑tree.<br/>
* <br/>
* Depending on the neighbouring children this may rotate entries between
* nodes or perform a split.
* @param source - the inner node that contains the child
* @param childIndex - the index of the child within `source`
* @param newChild - the updated child node
* @param newSize - the new total size for `source`
*/
export declare function innerNormalizeDownsizeChild<S extends InnerMutateSource<S, E>, E>(source: S, childIndex: number, newChild: InnerChild<E>, newSize: number): S;
/**
* Normalises the given child after it has increased in size so that it
* satisfies the maximum entry constraint of the B‑tree.<br/>
* <br/>
* Depending on the neighbouring children this may rotate entries between
* nodes or merge nodes together.
* @param source - the inner node that contains the child
* @param childIndex - the index of the child within `source`
* @param newChild - the updated child node
* @param newSize - the new total size for `source`
*/
export declare function innerNormalizeIncreaseChild<S extends InnerMutateSource<S, E>, E>(source: S, childIndex: number, newChild: InnerChild<E>, newSize: number): S;
/**
* Returns the index of the element in the sources element array, or a tuple with the child index and the index within the child
* @param source the collection to operate on
* @param index the index to find
*/
export declare function innerGetSubIndex(source: InnerMutateSource<any, any>, index: number): number | [number, number];
/**
* Returns the entry at the given `index` from the B‑tree represented by the
* given inner node, or the provided fallback value if the index is out of
* bounds.<br/>
* <br/>
* Negative indices are interpreted from the end of the collection.
* @param source - the inner node to read from
* @param index - the (possibly negative) index to look up
* @param otherwise - (default: undefined) fallback value when out of bounds
*/
export declare function innerGetAtIndex<E, O>(source: InnerMutateSource<any, E>, index: number, otherwise?: OptLazy<O>): E | O;
/**
* Returns a new inner node containing only the first `amount` of entries
* and children of the given `source` node.<br/>
* <br/>
* The amount must be between `1` and `source.size - 1`.
* @param source - the inner node to operate on
* @param amount - the amount of entries to keep
*/
export declare function innerTakeInternal<S extends InnerMutateSource<S, E>, E>(source: S, amount: number): S;
/**
* Returns a new inner node containing all entries and children of the given
* `source` node except for the first `amount` entries.<br/>
* <br/>
* The amount must be between `1` and `source.size - 1`.
* @param source - the inner node to operate on
* @param amount - the amount of entries to drop
*/
export declare function innerDropInternal<S extends InnerMutateSource<S, E>, E>(source: S, amount: number): S;
/**
* Returns a `Stream` of entries of the given inner node limited to the
* provided index `range`.<br/>
* <br/>
* When `reversed` is true, the stream iterates the selected range in
* reverse order.
* @param source - the inner node to stream from
* @param range - the index range to include
* @param reversed - (default: false) when true reverses the stream order
*/
export declare function innerStreamSliceIndex<E>(source: InnerMutateSource<any, E>, range: IndexRange, reversed?: boolean): Stream<E>;
/**
* Abstract base class for mutable sorted builders used by the sorted map
* and set implementations.<br/>
* <br/>
* It encapsulates the shared tree‑based logic for computing `min`, `max`,
* index‑based access and traversal while allowing concrete builders to plug
* in their own entry and child representations.
* @typeparam E - the entry type stored in the builder
*/
export declare abstract class SortedBuilder<E> {
abstract get context(): {
minEntries: number;
maxEntries: number;
};
abstract source?: undefined | {
min<O>(otherwise?: OptLazy<O>): E | O;
max<O>(otherwise?: OptLazy<O>): E | O;
getAtIndex<O>(index: number, otherwise?: OptLazy<O>): E | O;
forEach(f: (entry: E, index: number, halt: () => void) => void, options?: {
state?: TraverseState;
}): void;
};
abstract _entries?: undefined | E[];
abstract _children?: undefined | SortedBuilder<E>[];
abstract get children(): SortedBuilder<E>[];
abstract set children(value: SortedBuilder<E>[]);
abstract size: number;
abstract prepareMutate(): void;
abstract createNew(source?: undefined | unknown, entries?: undefined | E[], children?: undefined | SortedBuilder<E>[], size?: undefined | number): SortedBuilder<E>;
_lock: number;
/**
* Throws an error when the builder is mutated while it is being iterated,
* for example from within {@link SortedBuilder.forEach}.
*/
checkLock(): void;
get entries(): E[];
set entries(value: E[]);
get hasChildren(): boolean;
get isEmpty(): boolean;
/**
* Returns the minimum entry of the builder, or the given fallback value
* if the builder is empty.
* @param otherwise - (default: undefined) fallback value when empty
*/
min<O>(otherwise?: OptLazy<O>): E | O;
/**
* Returns the maximum entry of the builder, or the given fallback value
* if the builder is empty.
* @param otherwise - (default: undefined) fallback value when empty
*/
max<O>(otherwise?: OptLazy<O>): E | O;
/**
* Returns the entry at the given `index`, or the provided fallback value
* when the index is out of bounds.<br/>
* <br/>
* Negative indices are interpreted from the end of the builder.
* @param index - the (possibly negative) index to look up
* @param otherwise - (default: undefined) fallback value when out of bounds
*/
getAtIndex<O>(index: number, otherwise?: OptLazy<O>): E | O;
/**
* Calls the given function `f` for every entry in the builder in key
* sort‑order, passing in the entry, its zero‑based index and a `halt`
* function that can be used to stop iteration early.
* @param f - the callback function to invoke for each entry
* @param options - (optional) traversal options including a custom state
*/
forEach(f: (entry: E, index: number, halt: () => void) => void, options?: {
state?: TraverseState;
}): void;
/**
* Restores the builder invariants after mutations by splitting the root
* node when it grows beyond the configured maximum block size.
*/
normalize(): void;
normalizeChildIncrease(childIndex: number): void;
normalizeChildDecrease(childIndex: number): void;
/**
* Removes and returns the minimum entry from the builder while keeping
* the internal B‑tree structure valid.
*/
deleteMin(): E;
/**
* Removes and returns the maximum entry from the builder while keeping
* the internal B‑tree structure valid.
*/
deleteMax(): E;
}