gestalt/rpc_support.rs
1// Code generated by sdkgen. DO NOT EDIT.
2
3//! Shared generated runtime for sdkgen clients: the canonical error model.
4
5/// Canonical SDK error codes, drawn from the standard gRPC status codes.
6pub mod gestalt_error_code {
7 /// The operation was cancelled.
8 pub const CANCELLED: i32 = 1;
9 /// The cause of the error is unknown.
10 pub const UNKNOWN: i32 = 2;
11 /// The client specified an invalid argument.
12 pub const INVALID_ARGUMENT: i32 = 3;
13 /// The deadline expired before the operation could complete.
14 pub const DEADLINE_EXCEEDED: i32 = 4;
15 /// The requested entity was not found.
16 pub const NOT_FOUND: i32 = 5;
17 /// The entity the client attempted to create already exists.
18 pub const ALREADY_EXISTS: i32 = 6;
19 /// The caller does not have permission to execute the operation.
20 pub const PERMISSION_DENIED: i32 = 7;
21 /// A resource has been exhausted.
22 pub const RESOURCE_EXHAUSTED: i32 = 8;
23 /// The system is not in a state required for the operation.
24 pub const FAILED_PRECONDITION: i32 = 9;
25 /// The operation was aborted.
26 pub const ABORTED: i32 = 10;
27 /// The operation was attempted past the valid range.
28 pub const OUT_OF_RANGE: i32 = 11;
29 /// The operation is not implemented or supported.
30 pub const UNIMPLEMENTED: i32 = 12;
31 /// An internal error occurred.
32 pub const INTERNAL: i32 = 13;
33 /// The service is currently unavailable.
34 pub const UNAVAILABLE: i32 = 14;
35 /// Unrecoverable data loss or corruption.
36 pub const DATA_LOSS: i32 = 15;
37 /// The request lacks valid authentication credentials.
38 pub const UNAUTHENTICATED: i32 = 16;
39}
40
41/// Canonical SDK error: one numeric status code and a human-readable message.
42/// Concrete transport adapters map their native errors into this type.
43#[derive(Debug, thiserror::Error)]
44#[error("{message}")]
45pub struct GestaltError {
46 /// Numeric status code, one of the gestalt_error_code constants.
47 pub code: i32,
48 /// Human-readable error message.
49 pub message: String,
50}
51
52impl GestaltError {
53 /// Creates an error with the given code and message.
54 pub fn new(code: i32, message: impl Into<String>) -> Self {
55 Self {
56 code,
57 message: message.into(),
58 }
59 }
60}
61
62/// Maps an HTTP status code to the canonical Gestalt gRPC error code.
63pub fn http_status_to_gestalt_code(status: i32) -> i32 {
64 match status {
65 400 => gestalt_error_code::INVALID_ARGUMENT,
66 401 => gestalt_error_code::UNAUTHENTICATED,
67 403 => gestalt_error_code::PERMISSION_DENIED,
68 404 => gestalt_error_code::NOT_FOUND,
69 409 => gestalt_error_code::ALREADY_EXISTS,
70 412 => gestalt_error_code::FAILED_PRECONDITION,
71 429 => gestalt_error_code::RESOURCE_EXHAUSTED,
72 499 => gestalt_error_code::CANCELLED,
73 500 => gestalt_error_code::INTERNAL,
74 501 => gestalt_error_code::UNIMPLEMENTED,
75 503 => gestalt_error_code::UNAVAILABLE,
76 504 => gestalt_error_code::DEADLINE_EXCEEDED,
77 _ => gestalt_error_code::UNKNOWN,
78 }
79}
80
81// Provider-only extensions to the shared generated error model.
82
83/// Native representation of google.rpc.Status carried in response payloads,
84/// mirroring the canonical error model.
85#[derive(Clone, Debug, Default, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
86pub struct RpcStatus {
87 /// Numeric gRPC status code, one of the gestalt_error_code constants.
88 pub code: i32,
89 /// Human-readable error message.
90 pub message: String,
91}
92
93impl From<tonic::Status> for GestaltError {
94 fn from(status: tonic::Status) -> Self {
95 // tonic reports an expired grpc-timeout as CANCELLED carrying the
96 // TimeoutExpired message; the gRPC spec assigns deadline expiry
97 // DEADLINE_EXCEEDED, so the canonical code is restored here.
98 let timeout_expired = tonic::TimeoutExpired(()).to_string();
99 let code = if status.code() == tonic::Code::Cancelled && status.message() == timeout_expired
100 {
101 gestalt_error_code::DEADLINE_EXCEEDED
102 } else {
103 status.code() as i32
104 };
105 Self {
106 code,
107 message: status.message().to_string(),
108 }
109 }
110}