# Errors

> UCall for Rust

Every fallible call answers `ucall::Result`, whose `Error` carries the `Status` the library reported and a static message beside it, so nothing allocates on the failure path.
A mistake the binding catches before calling the library, like polling an event loop the server lacks, reports the status the library would have used.
`Status` prints its stable spelling, such as "connection-failed", and a status a newer library added reads as `Status::Internal`.

```rust
use ucall::*;

let mut client = Client::new(ClientOptions { connections: 1, ..Default::default() })?;
match client.get("http://127.0.0.1:1/") {
    Ok(response) => println!("answered {}", response.status_code().0),
    Err(error) if error.status == Status::ConnectionFailed => println!("nobody listens: {error}"),
    Err(error) => return Err(error.into()),
}
```

A submitted call that fails completes with `Err` in `Completed::response`: `Status::ConnectionFailed`, `Status::ConnectionClosed`, `Status::Timeout`, `Status::HandshakeFailed` or `Status::PeerRejected`.
A request lookup that finds nothing answers `None`, and HTTP error statuses are ordinary responses.
`Backend` and `CPUClass` print and parse their stable names, like "linux-uring618" and "intel-icelake", failing with `Status::InvalidArgument` on a name no value has, and `Status::from_name` reads a status back from its spelling.
`ucall::version()` spells the linked library's version, candidate suffix included.
`ucall::decode_percent` decodes a path or a query value, which requests lend still percent-encoded.

`use ucall::Error;`

`use ucall::Status;`

`use ucall::*;`

## Result

The result of every fallible call in this crate.

```rust
pub type Result<Value> = Result<Value, Error>;
```

## Error

A failure, whether the library reported it or the binding caught it before the call.

```rust
pub struct Error
```

Messages are static storage, so nothing allocates on the failure path.

```
use ucall::{Client, ClientOptions, Status};

let refused = Client::new(ClientOptions::default()).err().expect("a client needs connections");
assert_eq!(refused.status, Status::InvalidArgument);
println!("{refused}"); // "invalid-argument: ..."
```

- `status` `Status`: What went wrong, to branch on.
- `message` `&'static str`: The detail the status alone cannot carry.

Implements: `Clone`, `Copy`, `StructuralPartialEq`, `PartialEq`, `Eq`, [`Debug`](https://www.unum.cloud/docs/ucall/rust/serving.md#Debug), `Display`, [`Error`](#Error)

## Status

Why a call failed, numbered as the library numbers it; success is the `Ok` of a [`Result`](#Result).

```rust
pub enum Status
```

- `Deferred` = `1`: A reply is still sending a file or path part, as [`Deferred::status`](https://www.unum.cloud/docs/ucall/rust/requests.md#status) reports it.
- `OutOfMemory` = `2`: An allocation or reservation could not be satisfied.
- `IO` = `7`: A socket or file could not be opened, read, written, or closed.
- `Malformed` = `9`: The peer supplied bytes that cannot be decoded as the expected protocol.
- `Internal` = `10`: The library violated its contract, which points at a defect.
- `Overflow` = `11`: The requested size exceeds the representable range.
- `Uninitialized` = `12`: The call needs a handle that was never initialized.
- `Contended` = `14`: The call was refused rather than waited for, like a submission to a full client.
- `Unsupported` = `16`: The build, backend, or machine does not implement the requested feature.
- `InvalidArgument` = `17`: An argument is missing, out of range, or contradicts another argument.
- `NotFound` = `18`: The requested endpoint, header, or parameter does not exist.
- `AlreadyExists` = `19`: An endpoint with the same template and verb is already registered.
- `ConnectionFailed` = `20`: DNS lookup or connection establishment failed.
- `ConnectionClosed` = `21`: The connection closed before the exchange completed.
- `Timeout` = `22`: The operation exceeded its time budget.
- `HandshakeFailed` = `23`: The Noise handshake failed to authenticate or agree on keys.
- `PeerRejected` = `24`: The peer authorizer declined the authenticated static key.
- `WouldBlock` = `25`: Nothing was ready: a nonblocking poll had no progress to report, a pull on the polling
thread found no body bytes yet, or a stream's peer lags behind its appended parts.

Implements: `Clone`, `Copy`, `StructuralPartialEq`, `PartialEq`, `Eq`, [`Debug`](https://www.unum.cloud/docs/ucall/rust/serving.md#Debug), `Hash`, `Display`

## from_name

Reads a status back from its stable spelling, like "out-of-memory", or [`None`](https://www.unum.cloud/docs/ucall/rust/noise-keys.md#None) for a name no failure has, "success" among them.

```rust
pub fn from_name(name: &str) -> Option<Self>
```

