# objectstore.local

> A module of objectstore's API.

`objectstore.local` — the filesystem backend.

Range reads use `seek` + `read_bytes(n)`, which Mojo's `FileHandle` supports,
so reading a Parquet footer out of a 2 GB file costs 64 KiB rather than 2 GB.
Everything else is a thin wrapper whose value is uniformity: the same
`InputFile`/`OutputFile` shape as S3 and HTTP, so a caller never branches on
where a table happens to live.

## Structs

### `LocalInputFile`

```mojo
struct LocalInputFile
```

A readable file at an ordinary filesystem path.

Implements: `Copyable`, `Movable`

Fields:

- `path: String`

#### `location`

```mojo
def location(self) -> String
```

#### `exists`

```mojo
def exists(self) -> Bool
```

#### `length`

```mojo
def length(self) -> Int
```

#### `read_all`

```mojo
def read_all(self) -> List[UInt8]
```

#### `read_range`

```mojo
def read_range(self, offset: Int, length: Int) -> List[UInt8]
```

`length` bytes from `offset`; a short read at EOF is not an error.

A negative `offset` counts back from the end, the way an HTTP suffix
range does — which is how a Parquet reader asks for a footer.

### `LocalOutputFile`

```mojo
struct LocalOutputFile
```

A writable file at an ordinary filesystem path.

Parent directories are created on demand: Iceberg writes to deep,
partition-shaped paths that no one has made in advance.

Implements: `Copyable`, `Movable`

Fields:

- `path: String`

#### `location`

```mojo
def location(self) -> String
```

#### `exists`

```mojo
def exists(self) -> Bool
```

#### `create`

```mojo
def create(self, data: Span[UInt8])
```

#### `overwrite`

```mojo
def overwrite(self, data: Span[UInt8])
```

## Functions

### `local_delete`

```mojo
def local_delete(path: String)
```

Removes a file. A missing file is not an error — deletion is idempotent here for the same reason it is on S3.

### `local_list`

```mojo
def local_list(prefix: String) -> List[String]
```

Every file under `prefix`, recursively, as `file://` URIs.

A prefix that names a file lists just that file, which keeps the contract
the same as S3's: a prefix is a prefix, not necessarily a directory.

### `local_input`

```mojo
def local_input(location: String) -> LocalInputFile
```

Opens a `file://` URI or a bare path.

### `local_output`

```mojo
def local_output(location: String) -> LocalOutputFile
```
