1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
//! [`GrpcClientError`] — the gRPC sibling of `crate::error::ClientError`
//! (REST) and `crate::rpc::RpcClientError` (RPC).
//!
//! REST and RPC both decode a *body* on a non-2xx response
//! (`CoolErrorResponse` / `RpcErrorBody`) to recover a stable error code —
//! the HTTP status line alone doesn't carry one. gRPC doesn't have this
//! problem: `tonic::Status` already **is** the structured error, with a
//! `tonic::Code` the server derived from the exact same `CoolError` via
//! `cratestack_grpc::error::cool_error_to_status` (server-side,
//! `cool_error_to_status` -> `rpc_code` -> `tonic::Code`, the identical
//! table `cratestack_grpc::error::rpc_code_to_tonic_code` documents). So
//! `GrpcClientError::Status` wraps the `tonic::Status` tonic itself hands
//! back from a failed `Grpc::unary` call, unparsed — there is nothing left
//! to decode, and re-deriving a code string from `status.code()` would
//! just be inverting a mapping the server already computed correctly.