# Files and Streams

> UCall for Mojo

`request^.detach()` hands the request to a `DetachedRequest`, which reads the same way, moves to any thread, and answers 500 when dropped unreplied.
It alone offers the replies that may finish later:

```mojo
var detached = request^.detach()
var parts = [ReplyPart.bytes(header), ReplyPart.bytes(payload)]
if case .Some(deferred) = detached^.reply_parts(HTTPStatus.OK, no_headers, parts):
    deferred^.wait()  # off the polling thread, which is the one sending the file parts

var stream = other^.reply_stream(HTTPStatus.OK, no_headers)
stream.append(parts)
_ = stream^.end()  # Optional[Deferred] while file or path parts still send
```

`body_chunk` pulls a streamed body, waiting for the next bytes; on a buffered route the first pull is the whole body.
A `Deferred` reads `DEFERRED` from `status` until the reply is final, and `wait` blocks through `ucall_outcome_wait` and raises the reply's failure.
Dropping an unfinished `Deferred` waits for it.

`from ucall import FileRange, ReplyStream`

## FileRange

A byte range of a regular file the caller opened with `O_DIRECT`, `ucall_file_range_t` in C.

```mojo
struct FileRange
```

- `file_descriptor` `c_int`: The open file, borrowed and never closed by UCall, until the reply is final.
- `offset` `UInt64`: The range's first byte.
- `length` `UInt64`: The range's byte count; zero sends through the end of the file.

Conforms to: `Copyable`, `Deinitable`, `ImplicitlyCopyable`, `Movable`, `RegisterPassable`, `TrivialRegisterPassable`

## ReplyStream

A reply whose head left and whose body is appended part by part, from one thread at a time, until [`end`](#end); dropping it ends it, waiting for its file parts to send.

```mojo
struct ReplyStream
```

Conforms to: `Deinitable`, `Movable`

## __init__

```mojo
def __init__(out self, var shared: ArcPointer[_ServerCore], request: Int)
```

## __deinit__

Ends the body, waiting for its file parts. Calls `ucall_server_reply_end`.

```mojo
def __deinit__(deinit self)
```

## append

Queues `parts` on the body together, or none of them. Calls `ucall_server_reply_append`.

```mojo
def append[origin: ImmOrigin](self, parts: Span[ReplyPart[origin]])
```

Raises: [`Error`](https://www.unum.cloud/docs/ucall/mojo/errors.md#Error) with [`WOULD_BLOCK`](https://www.unum.cloud/docs/ucall/mojo/errors.md#WOULD_BLOCK), queueing nothing, while the peer lags behind the parts already queued; retry once it catches up.

## end

Ends the body, consuming the request whatever the outcome. Calls `ucall_server_reply_end`.

```mojo
def end(deinit self) -> Optional[Deferred]
```

Raises: [`Error`](https://www.unum.cloud/docs/ucall/mojo/errors.md#Error) with [`MALFORMED`](https://www.unum.cloud/docs/ucall/mojo/errors.md#MALFORMED) for a body short of its declared Content-Length.

