UNPKG

@y/y

Version:

Shared Editing Library

420 lines • 15.1 kB
/** * @typedef {{ inserts: IdSet, deletes: IdSet }} ContentIds */ /** * @typedef {{ inserts: IdMap<any>, deletes: IdMap<any> }} ContentMap */ export class IdRange { /** * @param {number} clock * @param {number} len */ constructor(clock: number, len: number); /** * @type {number} */ clock: number; /** * @type {number} */ len: number; /** * @param {number} clock * @param {number} len */ copyWith(clock: number, len: number): IdRange; /** * Helper method making this compatible with IdMap. * * @return {Array<ContentAttribute<any>>} */ get attrs(): Array<ContentAttribute<any>>; } export class MaybeIdRange { /** * @param {number} clock * @param {number} len * @param {boolean} exists */ constructor(clock: number, len: number, exists: boolean); /** * @type {number} */ clock: number; /** * @type {number} */ len: number; /** * @type {boolean} */ exists: boolean; } export function createMaybeIdRange(clock: number, len: number, exists: boolean): MaybeIdRange; export class IdRanges { /** * @param {Array<IdRange>} ids */ constructor(ids: Array<IdRange>); sorted: boolean; /** * A typical use-case for IdSet is to append data. We heavily optimize this case by allowing the * last item to be mutated if it isn't used currently. * This flag is true if the last item was exposed to the outside. */ _lastIsUsed: boolean; /** * @private */ private _ids; copy(): IdRanges; /** * @param {number} clock * @param {number} length */ add(clock: number, length: number): void; /** * Return the list of immutable id ranges, sorted and merged. */ getIds(): IdRange[]; /** * Test a predicate against every attribute held by these ranges. Does not mutate - see * {@link AttrRanges#everyAttr}. * * This exists because an `IdMap` may hold `IdRanges`: {@link insertIntoIdMap}'s `src` may be an * `IdSet`, and `_insertIntoIdSet` picks the container class from whichever `src` reaches a client * first. For a pure `IdRanges` the loop is vacuous ({@link IdRange#attrs} is always `[]`), but it * must *not* shortcut to `true`: the append branch of `_insertIntoIdSet` copies elements without * checking their class, so an `IdRanges` reached by an `IdSet` first and an `IdMap` second holds * real `AttrRange`s - which {@link $idMap} must still validate. * * @param {(attr:ContentAttribute<any>) => boolean} f * @return {boolean} */ everyAttr(f: (attr: ContentAttribute<any>) => boolean): boolean; } /** * @implements {traits.EqualityTrait} */ export class IdSet implements traits.EqualityTrait { /** * @type {Map<number,IdRanges>} */ clients: Map<number, IdRanges>; isEmpty(): boolean; /** * @param {(idrange:IdRange, client:number) => void} f */ forEach(f: (idrange: IdRange, client: number) => void): void; /** * @param {ID} id * @return {boolean} */ hasId(id: ID): boolean; /** * @param {number} client * @param {number} clock */ has(client: number, clock: number): boolean; /** * Whether any id in the range `[clock, clock+len)` of `client` is contained in this set. * Allocation-free (binary search). * * @param {number} client * @param {number} clock * @param {number} len * @return {boolean} */ intersects(client: number, clock: number, len: number): boolean; /** * Whether the entire range `[clock, clock+len)` of `client` is contained in this set. * Allocation-free (binary search). Because `getIds()` returns maximal, merged ranges, full * coverage of a range implies it lies within a single range. * * @param {number} client * @param {number} clock * @param {number} len * @return {boolean} */ covers(client: number, clock: number, len: number): boolean; /** * Total number of ids in `[clock, clock+len)` of `client` contained in this set. * Allocation-free (binary search + linear scan of the overlapping ranges). Equivalent to * `slice(client, clock, len).reduce((s, r) => r.exists ? s + r.len : s, 0)` without allocating. * * @param {number} client * @param {number} clock * @param {number} len * @return {number} */ coveredLength(client: number, clock: number, len: number): number; /** * Return slices of ids that exist in this idset. * * @param {number} client * @param {number} clock * @param {number} len * @return {Array<MaybeIdRange>} */ slice(client: number, clock: number, len: number): Array<MaybeIdRange>; /** * @param {number} client * @param {number} clock * @param {number} len */ add(client: number, clock: number, len: number): void; /** * @param {number} client * @param {number} clock * @param {number} len */ delete(client: number, clock: number, len: number): void; $type: s.Schema<IdSet>; /** * @param {any} other */ [traits.EqualityTraitSymbol](other: any): boolean; } export function equalIdSets(ds1: IdSet, ds2: IdSet): boolean; export function _deleteRangeFromIdSet(set: IdSet | IdMap<any>, client: number, clock: number, len: number): void; export function iterateStructsByIdSet(transaction: Transaction, ds: IdSet, f: (arg0: GC | Item) => void): void; export function gcIdSet(doc: Doc, ids: IdSet, gcFilter?: (arg0: Item) => boolean): void; export function iterateStructsByIdSetWithoutSplits(store: StructStore, ds: IdSet, f: (struct: GC | Item | Skip, offset: number, len: number) => void): void; export function findIndexInIdRanges(dis: Array<IdRange>, clock: number): number | null; export function findRangeStartInIdRanges(dis: Array<IdRange>, clock: number): number | null; export function mergeIdSets(idSets: Array<IdSet>): IdSet; /** * @template {IdSet | IdMap<any>} S * @param {S} dest * @param {S} src */ export function insertIntoIdSet<S extends IdSet | IdMap<any>>(dest: S, src: S): void; /** * Note that `src` may be an `IdSet`, in which case `dest` ends up holding `IdRanges` - which carry * no attributes ({@link IdRange#attrs} is `[]`). This is by design; {@link $idMap} tolerates it. * * @type {(dest: IdMap<any>, src: IdMap<any>|IdSet) => void} */ export const insertIntoIdMap: (dest: IdMap<any>, src: IdMap<any> | IdSet) => void; export function _diffSet<Set extends IdSet | IdMap<any>>(set: Set, exclude: IdSet | IdMap<any>): Set; /** * Remove all ranges from `exclude` from `idSet`. The result is a fresh IdSet containing all ranges from `idSet` that are not * in `exclude`. * * @type {(idSet: IdSet, exclude: IdSet|IdMap<any>) => IdSet} */ export const diffIdSet: (idSet: IdSet, exclude: IdSet | IdMap<any>) => IdSet; export function _intersectSets<SetA extends IdSet | IdMap<any>, SetB extends IdSet | IdMap<any>>(setA: SetA, setB: SetB): SetA extends IdMap<infer A> ? (SetB extends IdMap<infer B> ? IdMap<A | B> : IdMap<A>) : IdSet; export function intersectSets<SetA extends IdSet | IdMap<any>, SetB extends IdSet | IdMap<any>>(setA: SetA, setB: SetB): SetA extends IdMap<infer A> ? (SetB extends IdMap<infer B> ? IdMap<A | B> : IdMap<A>) : IdSet; export function createIdSet(): IdSet; export function createDeleteSetFromStructStore(ss: StructStore): IdSet; export function _createInsertSliceFromStructs(structs: Array<GC | Item | Skip>, filterDeleted: boolean): IdRange[]; export function createInsertSetFromStructStore(ss: StructStore, filterDeleted: boolean): IdSet; export function writeIdSet(encoder: IdSetEncoderV1 | IdSetEncoderV2, idSet: IdSet): void; export function readIdSet(decoder: IdSetDecoderV1 | IdSetDecoderV2): IdSet; export function encodeIdSet(idSet: IdSet): Uint8Array<ArrayBuffer>; export function decodeIdSet(data: Uint8Array): IdSet; export function readAndApplyDeleteSet(decoder: IdSetDecoderV1 | IdSetDecoderV2, transaction: Transaction, store: StructStore): Uint8Array<ArrayBuffer> | null; /** * @template Attrs */ export class AttrRange<Attrs> { /** * @param {number} clock * @param {number} len * @param {Array<ContentAttribute<Attrs>>} attrs */ constructor(clock: number, len: number, attrs: Array<ContentAttribute<Attrs>>); /** * @readonly */ readonly clock: number; /** * @readonly */ readonly len: number; /** * @readonly */ readonly attrs: ContentAttribute<Attrs>[]; /** * @param {number} clock * @param {number} len */ copyWith(clock: number, len: number): AttrRange<Attrs>; } /** * @todo rename this to `Attribute` * @template V */ export class ContentAttribute<V> { /** * @param {string} name * @param {V} val */ constructor(name: string, val: V); name: string; val: V; hash(): string; } export function createContentAttribute<V>(name: string, val: V): ContentAttribute<V>; export function createMaybeAttrRange<Attrs>(clock: number, len: number, attrs: Array<ContentAttribute<Attrs>> | null): MaybeAttrRange<Attrs>; /** * Whenever this is instantiated, it must receive a fresh array of ops, not something copied. * * @template Attrs */ export class AttrRanges<Attrs> { /** * @param {Array<AttrRange<Attrs>>} ids */ constructor(ids: Array<AttrRange<Attrs>>); sorted: boolean; /** * @private */ private _ids; copy(): AttrRanges<Attrs>; /** * @param {number} clock * @param {number} length * @param {Array<ContentAttribute<Attrs>>} attrs */ add(clock: number, length: number, attrs: Array<ContentAttribute<Attrs>>): void; /** * Return the list of id ranges, sorted and merged. */ getIds(): AttrRange<Attrs>[]; /** * Test a predicate against every attribute held by these ranges. * * Unlike {@link AttrRanges#getIds} this does **not** sort/merge - i.e. it does not mutate its * receiver, which matters because it backs {@link $idMap}`.check`. The *set* of attributes is * invariant under sorting/merging (merging only ever concatenates existing attr arrays), so this * observes exactly the attributes that `getIds()` would expose. * * @param {(attr:ContentAttribute<Attrs>) => boolean} f * @return {boolean} */ everyAttr(f: (attr: ContentAttribute<Attrs>) => boolean): boolean; } /** * @template Attrs */ export class IdMap<Attrs> { /** * @type {Map<number,AttrRanges<Attrs>>} */ clients: Map<number, AttrRanges<Attrs>>; /** * @type {Map<string, ContentAttribute<Attrs>>} */ attrsH: Map<string, ContentAttribute<Attrs>>; /** * @type {Set<ContentAttribute<Attrs>>} */ attrs: Set<ContentAttribute<Attrs>>; /** * @param {(attrRange:AttrRange<Attrs>, client:number) => void} f */ forEach(f: (attrRange: AttrRange<Attrs>, client: number) => void): void; isEmpty(): boolean; /** * @param {ID} id * @return {boolean} */ hasId(id: ID): boolean; /** * @param {number} client * @param {number} clock * @return {boolean} */ has(client: number, clock: number): boolean; /** * Total number of ids in `[clock, clock+len)` of `client` contained in this map (i.e. carrying * an attribution, incl. an empty `[]`). Allocation-free (binary search + linear scan). * Equivalent to `slice(client, clock, len).reduce((s, r) => r.attrs != null ? s + r.len : s, 0)` * without allocating. * * @param {number} client * @param {number} clock * @param {number} len * @return {number} */ coveredLength(client: number, clock: number, len: number): number; /** * Return attributions for a slice of ids. * * @param {ID} id * @param {number} len * @return {Array<MaybeAttrRange<Attrs>>} */ sliceId(id: ID, len: number): Array<MaybeAttrRange<Attrs>>; /** * Return attributions for a slice of ids. * * @param {number} client * @param {number} clock * @param {number} len * @return {Array<MaybeAttrRange<Attrs>>} */ slice(client: number, clock: number, len: number): Array<MaybeAttrRange<Attrs>>; /** * @param {number} client * @param {number} clock * @param {number} len * @param {Array<ContentAttribute<Attrs>>} attrs */ add(client: number, clock: number, len: number, attrs: Array<ContentAttribute<Attrs>>): void; /** * @param {number} client * @param {number} clock * @param {number} len */ delete(client: number, clock: number, len: number): void; $type: s.Schema<IdMap<any>>; } export function idmapAttrsEqual<T>(a: Array<T>, b: Array<T>): boolean; export function mergeIdMaps<T>(ams: Array<IdMap<T>>): IdMap<T>; export function createIdMapFromIdSet(idset: IdSet, attrs: Array<ContentAttribute<any>>): IdMap<any>; export function createIdSetFromIdMap(idmap: IdMap<any>): IdSet; export function writeIdMap<Attr>(encoder: IdSetEncoderV1 | IdSetEncoderV2, idmap: IdMap<Attr>): void; export function encodeIdMap(idmap: IdMap<any>): Uint8Array<ArrayBuffer>; export function readIdMap(decoder: IdSetDecoderV1 | IdSetDecoderV2): IdMap<any>; export function decodeIdMap(data: Uint8Array): IdMap<any>; export function createIdMap(): IdMap<any>; export function diffIdMap<ISet extends IdMap<any>>(set: ISet, exclude: IdSet | IdMap<any>): ISet; export function intersectMaps<SetA extends IdSet | IdMap<any>, SetB extends IdSet | IdMap<any>>(setA: SetA, setB: SetB): SetA extends IdMap<infer A> ? (SetB extends IdMap<infer B> ? IdMap<A | B> : IdMap<A>) : IdSet; export function filterIdMap<Attrs>(idmap: IdMap<Attrs>, predicate: (attr: Array<ContentAttribute<Attrs>>) => boolean): IdMap<Attrs>; /** * Schema of an {@link IdSet}. * * Nominal: `check` is a single identity compare against the globally interned `y:idSet` tag, so it * stays sound across duplicate yjs installations (unlike `instanceof`) - the same reason * {@link $renderer} uses `$type`. */ export const $idSet: s.Schema<IdSet>; /** * Schema of an {@link IdMap} with any mapped-value type. This is where the nominal `y:idMap` tag * lives - {@link $idMap} builds on it. Mirrors lib0's `$deltaAny` / `$delta` split. */ export const $idMapAny: s.Schema<IdMap<any>>; export function $idMap<Attrs>($attrs: s.Schema<Attrs>): s.Schema<IdMap<Attrs>>; export type ContentIds = { inserts: IdSet; deletes: IdSet; }; export type ContentMap = { inserts: IdMap<any>; deletes: IdMap<any>; }; export type MaybeAttrRange<Attrs> = { clock: number; len: number; attrs: Array<ContentAttribute<Attrs>> | null; }; import * as traits from 'lib0/traits'; import * as s from 'lib0/schema'; import { IdSetEncoderV2 } from './UpdateEncoder.js'; import { IdSetDecoderV2 } from './UpdateDecoder.js'; //# sourceMappingURL=ids.d.ts.map