The crate is a thin layer over UCall’s native library, and every rule below follows from that.
- Verbs share one name across languages.
take_call,take_calls,take_batch,take_batches,submitandtake_completedname the same calls in Python and Rust. - Blocking stays simple, deferring stays symmetric. A reply that is final on return looks as it did before files and streams existed, a deferred one is a
Deferredthatwaits,.awaits or waits as it drops, and nothing costs more until aDetachedRequestis used. - Ownership is a type, not a flag. A reply consumes its
Request, a dropped request answers 500, only aDetachedRequesthands back aDeferred, aResponsefrees itself, and aClientis neitherSendnorSync, so misuse does not compile. - Single owners are claimed, never assumed. Event loops and batch endpoints take
&self, and an atomic claim answersStatus::Contendedto a second poller instead of racing it. - Handlers are plain closures. A panic inside a handler or an authorizer is caught at the boundary, answering 500 or rejecting the peer, and never unwinds through C.
- Polling allocates nothing. A client sizes its tables by its call budget once, and a batch endpoint reuses the slots it lends requests in.
- No life of its own. The crate starts no threads, keeps no global state and needs no async runtime, so it drops into any threading model.