/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
import structuredClone from "@ungap/structured-clone";
/**
 * Subset of Map interface.
 */
export interface MapGetSet<K, V> {
    get(key: K): V | undefined;
    set(key: K, value: V): void;
}
/**
 * Make all transitive properties in T readonly
 */
export type RecursiveReadonly<T> = {
    readonly [P in keyof T]: RecursiveReadonly<T[P]>;
};
/**
 * Remove `readonly` from all fields.
 */
export type Mutable<T> = {
    -readonly [P in keyof T]: T[P];
};
/**
 * Make all field required and omits fields whose ony valid value would be `undefined`.
 * This is analogous to `Required<T>` except it tolerates 'optional undefined'.
 */
export type Populated<T> = {
    [P in keyof T as Exclude<P, T[P] extends undefined ? P : never>]-?: T[P];
};
/**
 * Casts a readonly object to a mutable one.
 * Better than casting to `Mutable<Foo>` because it doesn't risk casting a non-`Foo` to a `Mutable<Foo>`.
 * @param readonly - The object with readonly fields.
 * @returns The same object but with a type that makes all fields mutable.
 */
export declare function asMutable<T>(readonly: T): Mutable<T>;
export declare const clone: typeof structuredClone;
/**
 * @internal
 */
export declare function fail(message: string): never;
/**
 * Checks whether or not the given object is a `readonly` array.
 *
 * Note that this does NOT indicate if a given array should be treated as readonly.
 * This instead indicates if an object is an Array, and is typed to tolerate the readonly case.
 */
export declare function isReadonlyArray<T>(x: readonly T[] | unknown): x is readonly T[];
/**
 * Creates and populates a new array.
 * @param size - The size of the array to be created.
 * @param filler - Callback for populating the array with a value for a given index
 */
export declare function makeArray<T>(size: number, filler: (index: number) => T): T[];
/**
 * Compares two sets using callbacks.
 * Early returns on first false comparison.
 *
 * @param a - One Set.
 * @param b - The other Set.
 * @param aExtra - Called for items in `a` but not `b`.
 * @param bExtra - Called for items in `b` but not `a`.
 * @param same - Called for items in `a` and `b`.
 * @returns false iff any of the call backs returned false.
 */
export declare function compareSets<T>({ a, b, aExtra, bExtra, same, }: {
    a: ReadonlySet<T> | ReadonlyMap<T, unknown>;
    b: ReadonlySet<T> | ReadonlyMap<T, unknown>;
    aExtra?: (t: T) => boolean;
    bExtra?: (t: T) => boolean;
    same?: (t: T) => boolean;
}): boolean;
/**
 * Retrieve a value from a map with the given key, or create a new entry if the key is not in the map.
 * @param map - The map to query/update
 * @param key - The key to lookup in the map
 * @param defaultValue - a function which returns a default value. This is called and used to set an initial value for the given key in the map if none exists
 * @returns either the existing value for the given key, or the newly-created value (the result of `defaultValue`)
 */
export declare function getOrCreate<K, V>(map: MapGetSet<K, V>, key: K, defaultValue: (key: K) => V): V;
/**
 * Utility for dictionaries whose values are lists.
 * Gets the list associated with the provided key, if it exists.
 * Otherwise, creates an entry with an empty list, and returns that list.
 */
export declare function getOrAddEmptyToMap<K, V>(map: MapGetSet<K, V[]>, key: K): V[];
/**
 * Map one iterable to another by transforming each element one at a time
 * @param iterable - the iterable to transform
 * @param map - the transformation function to run on each element of the iterable
 * @returns a new iterable of elements which have been transformed by the `map` function
 */
export declare function mapIterable<T, U>(iterable: Iterable<T>, map: (t: T) => U): Iterable<U>;
/**
 * Returns an iterable of tuples containing pairs of elements from the given iterables
 * @param iterableA - an iterable to zip together with `iterableB`
 * @param iterableB - an iterable to zip together with `iterableA`
 * @returns in iterable of tuples of elements zipped together from `iterableA` and `iterableB`.
 * If the input iterables are of different lengths, then the extra elements in the longer will be ignored.
 */
export declare function zipIterables<T, U>(iterableA: Iterable<T>, iterableB: Iterable<U>): Iterable<[T, U]>;
/**
 * Use for Json compatible data.
 *
 * Note that this does not robustly forbid non json comparable data via type checking,
 * but instead mostly restricts access to it.
 * @internal
 */
export type JsonCompatible = string | number | boolean | null | JsonCompatible[] | JsonCompatibleObject;
/**
 * Use for Json object compatible data.
 *
 * Note that this does not robustly forbid non json comparable data via type checking,
 * but instead mostly restricts access to it.
 * @internal
 */
export type JsonCompatibleObject = {
    [P in string]?: JsonCompatible;
};
/**
 * Use for readonly view of Json compatible data.
 *
 * Note that this does not robustly forbid non json comparable data via type checking,
 * but instead mostly restricts access to it.
 * @internal
 */
export type JsonCompatibleReadOnly = string | number | boolean | null | readonly JsonCompatibleReadOnly[] | {
    readonly [P in string]?: JsonCompatibleReadOnly;
};
/**
 * @remarks TODO: Audit usage of this type in schemas, evaluating whether it is necessary and performance
 * of alternatives.
 *
 * True "arbitrary serializable data" is probably fine, but some persisted types declarations might be better
 * expressed using composition of schemas for runtime validation, even if we don't think making the types
 * generic is worth the maintenance cost.
 */
export declare const JsonCompatibleReadOnlySchema: import("@sinclair/typebox").TAny;
/**
 * Returns if a particular json compatible value is an object.
 * Does not include `null` or arrays.
 */
export declare function isJsonObject(value: JsonCompatibleReadOnly): value is {
    readonly [P in string]?: JsonCompatibleReadOnly;
};
/**
 * Verifies that the supplied indices are valid within the supplied array.
 * @param startIndex - The starting index in the range. Must be in [0, length).
 * @param endIndex - The ending index in the range. Must be within (start, length].
 * @param array - The array the indices refer to
 */
export declare function assertValidRangeIndices(startIndex: number, endIndex: number, array: {
    readonly length: number;
}): void;
export declare function assertValidIndex(index: number, array: {
    readonly length: number;
}, allowOnePastEnd?: boolean): void;
export declare function assertValidRange({ start, end }: {
    start: number;
    end: number;
}, array: {
    readonly length: number;
}): void;
export declare function assertNonNegativeSafeInteger(index: number): void;
/**
 * Convert an object into a Map.
 *
 * This function must only be used with objects specifically intended to encode map like information.
 * The only time such objects should be used is for encoding maps as object literals to allow for developer ergonomics or JSON compatibility.
 * Even those two use-cases need to be carefully considered as using objects as maps can have a lot of issues
 * (including but not limited to unintended access to __proto__ and other non-owned keys).
 * This function helps these few cases get into using an actual map in as safe of was as is practical.
 */
export declare function objectToMap<MapKey extends string | number | symbol, MapValue>(objectMap: Record<MapKey, MapValue>): Map<MapKey, MapValue>;
/**
 * Convert an object used as a map into a new object used like a map.
 *
 * @remarks
 * This function must only be used with objects specifically intended to encode map like information.
 * The only time such objects should be used is for encoding maps as object literals to allow for developer ergonomics or JSON compatibility.
 * Even those two use-cases need to be carefully considered as using objects as maps can have a lot of issues
 * (including but not limited to unintended access to __proto__ and other non-owned keys).
 * {@link objectToMap} helps these few cases get into using an actual map in as safe of a way as is practical.
 */
export declare function transformObjectMap<MapKey extends string | number | symbol, MapValue, NewMapValue>(objectMap: Record<MapKey, MapValue>, transformer: (value: MapValue, key: MapKey) => NewMapValue): Record<MapKey, MapValue>;
/**
 * Make an inverted copy of a map.
 *
 * @returns a map which can look up the keys from the values of the original map.
 */
export declare function invertMap<Key, Value>(input: Map<Key, Value>): Map<Value, Key>;
/**
 * Returns the value from `set` if it contains exactly one item, otherwise `undefined`.
 * @internal
 */
export declare function oneFromSet<T>(set: ReadonlySet<T> | undefined): T | undefined;
/**
 * Type with a name describing what it is.
 * Typically used with values (like schema) that can be stored in a map, but in some representations have their name/key as a field.
 * @internal
 */
export interface Named<TName> {
    readonly name: TName;
}
/**
 * Order {@link Named} objects by their name.
 * @internal
 */
export declare function compareNamed(a: Named<string>, b: Named<string>): -1 | 0 | 1;
/**
 * Placeholder for `Symbol.dispose`.
 * @privateRemarks
 * TODO: replace this with `Symbol.dispose` when it is available or make it a valid polyfill.
 * @public
 */
export declare const disposeSymbol: unique symbol;
/**
 * An object with an explicit lifetime that can be ended.
 * @privateRemarks
 * TODO: align this with core-utils/IDisposable and {@link https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html#using-declarations-and-explicit-resource-management| TypeScript's Disposable}.
 * @public
 */
export interface IDisposable {
    /**
     * Call to end the lifetime of this object.
     *
     * It is invalid to use this object after this,
     * except for operations which explicitly document they are valid after disposal.
     *
     * @remarks
     * May cleanup resources retained by this object.
     * Often includes un-registering from events and thus preventing other objects from retaining a reference to this indefinably.
     *
     * Usually the only operations allowed after disposal are querying if an object is already disposed,
     * but this can vary between implementations.
     */
    [disposeSymbol](): void;
}
/**
 * Capitalize a string.
 */
export declare function capitalize<S extends string>(s: S): Capitalize<S>;
/**
 * Compares strings lexically to form a strict partial ordering.
 */
export declare function compareStrings<T extends string>(a: T, b: T): number;
//# sourceMappingURL=utils.d.ts.map