import { type RewriteWriteFn } from '../../cache/types.ts';
import { type PathSpec, type StatFn } from '../../types.ts';
import { ByteSpool } from '../../io/spool.ts';
import type { ByteSource } from '../../io/types.ts';
export type ReadFn = (path: PathSpec) => Promise<Uint8Array>;
export type WriteFn<Written = unknown> = RewriteWriteFn<Written>;
/**
 * Append by reading the file and writing it back whole.
 *
 * Not atomic against a concurrent writer. A zero-byte append is an open for
 * appending with nothing written after it (`cmd >> f` opens `f` before `cmd`
 * runs): it creates a missing file and leaves an existing one alone, so it
 * costs a stat rather than moving the whole object twice to add nothing, and
 * cannot put back bytes a concurrent writer had just replaced. The read takes
 * the caller's index, as every other read does: an id-addressed backend (Box,
 * Drive) turns a path into an id through it. Mirrors Python's
 * `append_by_rewrite`.
 */
export declare function appendByRewrite<Written>(read: ReadFn, write: RewriteWriteFn<Written>, stat: StatFn, path: PathSpec, data: Uint8Array): Promise<Written | undefined>;
/**
 * Stage a read-modify-write with bounded RAM and the read's version. The new
 * bytes are spooled before the file is read: a streamed write lets its path
 * go while its source is pulled, so a write landing meanwhile is in the file
 * the replacement is made from.
 */
export declare function appendByStreamedRewrite<Written>(read: (path: PathSpec, onVersion: (version: string | null) => void) => AsyncIterable<Uint8Array>, write: RewriteWriteFn<Written>, stat: StatFn, path: PathSpec, data: ByteSource): Promise<Written | undefined>;
/**
 * Write at an offset by spooling the file and writing it back whole, its
 * head, the new bytes and its tail streamed, so memory holds a chunk at a
 * time whatever the sizes. The new bytes are spooled before the file is
 * read: a streamed write lets its path go while its source is pulled, so a
 * write landing meanwhile is in the file the replacement is made from.
 *
 * A zero-length pwrite(2) on an existing file changes nothing and must not
 * read the file back: a concurrent writer's update between the stat and a
 * write would be clobbered by the stale contents. On a missing file it
 * creates an empty one. A key store answers a read of a directory's name as
 * a missing key, so a read that misses is checked against stat before
 * writing: writing there would put an object beside the directory. `read`
 * fills a spool with the whole file and answers the version the read
 * carried. Mirrors Python's `pwrite_by_streamed_rewrite`.
 */
export declare function pwriteByStreamedRewrite(read: (path: PathSpec, spool: ByteSpool) => Promise<string | null>, write: RewriteWriteFn<unknown>, stat: StatFn, path: PathSpec, data: ByteSource, offset: number): Promise<void>;
/**
 * Resize by reading the file and writing it back padded or cut.
 *
 * For a store with no partial write. It cannot hold `noCreate` atomically,
 * so it refuses that before writing anything, as it does a negative length
 * (EINVAL). Emptying reads nothing, so its
 * write carries the version the agent read. Mirrors Python's
 * `truncate_by_rewrite`.
 */
export declare function truncateByRewrite(read: ReadFn, write: RewriteWriteFn<unknown>, path: PathSpec, length: number, noCreate: boolean): Promise<void>;
/** A pwrite offset, refused with EINVAL when negative. Mirrors Python's `expect_offset`. */
export declare function expectOffset(offset: number, path: PathSpec): number;
/**
 * Refuse a mkdir of a name that is taken, as mkdir(2) does.
 *
 * mkdir(2) refuses a name that exists, file or directory, and `mkdir -p`
 * passes only a directory. Not every backend's create says so (a Graph 409
 * on a folder, Nextcloud's MKCOL 405, SFTP under `-p`), so both callers look
 * the name up before the create. A directory under `-p` still reaches the
 * create, which keeps it durable (an object store writes the marker of a
 * directory only a key implied), and a name that cannot be looked up is left
 * to it too, to answer ENOENT or ENOTDIR. Mirrors Python's `refuse_taken`.
 */
export declare function refuseTaken(stat: StatFn, path: PathSpec, parents: boolean): Promise<void>;
//# sourceMappingURL=rewrite.d.ts.map