import type { ByteSource } from '../io/types.ts';
import { type CapacityResult, type PathSpec } from '../types.ts';
/** The bytes at a path, a directory's included; 0 for none. */
export type SizeOf = (path: PathSpec) => Promise<number>;
/** The bytes the whole store holds. */
export type CountAll = () => Promise<number>;
/**
 * One store's capacity and the bytes counted against it.
 *
 * `used` is null until the store is counted. `pending` holds bytes a stream
 * or an awaiting write admitted and has not landed yet. `active` holds the
 * writes in flight. Every method but `counted` is
 * synchronous, so a check and the change it guards run as one step on the
 * one thread, which is what makes parallel writers safe without a lock. Two
 * writes in flight on overlapping paths (a file and its folder) can both
 * measure the same bytes, so they lose the credit for the bytes they replace
 * and mark the count for a recount, which waits until no write is in flight. The count lives in this object: another
 * process, or another VFS on the same disk folder, Redis prefix or OPFS
 * directory, counts on its own, so together they can pass the limit.
 * Mirrors Python's `StorageUsage`.
 */
export declare class StorageUsage {
    readonly limit: number;
    used: number | null;
    pending: number;
    readonly active: Charge[];
    dirty: boolean;
    private counting;
    constructor(limit: number, used?: number | null);
    /** Count the store when it is uncounted, or marked for a recount and no
     * write is in flight; parallel callers wait on one count. */
    counted(count: CountAll): Promise<void>;
    private count;
    /** Count the store again once no write is in flight, as bytes written
     * past mirage (a native program on a disk folder) went uncounted. */
    stale(): void;
    /** Mark a write in flight; one overlapping another in flight takes both
     * off their credit and marks the count for a recount. */
    enter(held: Charge): void;
    /** Mark a write done. */
    leave(held: Charge): void;
    /** Throw `edquot(path)` when positive growth would pass the limit;
     * reaching it exactly passes. */
    admit(path: PathSpec, growth: number): void;
    /** Admit `size` and keep it in `pending` until it lands. */
    hold(path: PathSpec, size: number): void;
    /** Take `held` out of `pending` and add the measured `delta`. */
    land(held: number, delta: number): void;
    /** df's QUOTA row: total is the limit, available never below 0. */
    report(): CapacityResult;
}
/**
 * A backend's usage for its `capacity` setting; null for no cap. `used` is
 * the bytes it starts with when the backend knows them, as an empty RAM
 * store does. Mirrors Python's `storage_usage`.
 *
 * @throws VFSConfigError when the setting is not a size.
 */
export declare function storageUsage(name: string, capacity: number | string | null | undefined, used?: number | null): StorageUsage | null;
/**
 * What one write reserves against a counted store, and the bytes it held so
 * far; inert for an uncapped store. A replacement is credited with the bytes
 * it replaces until another write overlaps it (`contended`), as that write
 * may move those bytes elsewhere. Mirrors Python's `Charge`.
 */
export declare class Charge {
    readonly usage: StorageUsage | null;
    readonly path: PathSpec;
    before: number;
    held: number;
    written: number;
    contended: boolean;
    constructor(usage: StorageUsage | null, path: PathSpec, before?: number);
    /** Reserve `size` more bytes, or throw EDQUOT. */
    hold(size: number): void;
    /** The length the operand may reach within what this charge holds and is
     * credited with. */
    get reserved(): number;
    /** Reserve what growing the operand to `size` bytes adds past what this
     * charge already holds. */
    growTo(size: number): void;
    /** `data`, each chunk reserved as the writer takes it. With `append`
     * false, a replacement reserves only what passes the bytes it replaces. */
    stream(data: ByteSource, append?: boolean): ByteSource;
    private take;
    private held_;
}
/**
 * Reserve before a write's bytes go and land what it really changed. The
 * reservation is checked and taken in one synchronous step, so parallel
 * writers can never pass the store's capacity together. After the write,
 * however it ended, the operand is measured again and the change lands; one
 * that overlapped another in flight marks the count for a recount. An
 * uncapped store gets an inert charge and measures nothing. Mirrors Python's
 * `charge`.
 */
export declare function charge<T>(usage: StorageUsage | null, path: PathSpec, sizeOf: SizeOf, count: CountAll, write: (held: Charge) => Promise<T>): Promise<T>;
//# sourceMappingURL=capacity.d.ts.map