Skip to main content

proto_types/rpc/
http.rs

1use core::fmt::Display;
2
3use crate::{
4	HttpHeader,
5	rpc::{Code, HttpRequest, HttpResponse},
6};
7
8impl PartialOrd for HttpHeader {
9	#[inline]
10	fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
11		Some(self.cmp(other))
12	}
13}
14
15impl Ord for HttpHeader {
16	#[inline]
17	fn cmp(&self, other: &Self) -> core::cmp::Ordering {
18		self.key
19			.cmp(&other.key)
20			.then(self.value.cmp(&other.value))
21	}
22}
23
24impl HttpRequest {
25	has_impl!(method);
26	has_impl!(uri);
27
28	#[inline]
29	/// Returns true if the [`HttpRequest`] contains the given header.
30	pub fn has_header(&self, name: &str, value: &str) -> bool {
31		self.headers
32			.iter()
33			.any(|h| h.key == name && h.value == value)
34	}
35}
36
37impl HttpResponse {
38	#[inline]
39	/// Returns true if the `status` matches the argument.
40	pub const fn has_status(&self, status: i32) -> bool {
41		self.status == status
42	}
43
44	#[inline]
45	/// Returns true if the [`HttpResponse`] contains the given header.
46	pub fn has_header(&self, name: &str, value: &str) -> bool {
47		self.headers
48			.iter()
49			.any(|h| h.key == name && h.value == value)
50	}
51
52	has_impl!(reason);
53}
54
55impl Code {
56	/// Checks if the code is `Ok`.
57	#[must_use]
58	#[inline]
59	pub const fn is_200_ok(&self) -> bool {
60		matches!(self, Self::Ok)
61	}
62
63	/// Checks if the code is `Cancelled`.
64	#[must_use]
65	#[inline]
66	pub const fn is_cancelled(&self) -> bool {
67		matches!(self, Self::Cancelled)
68	}
69
70	/// Checks if the code is `Unknown`.
71	#[must_use]
72	#[inline]
73	pub const fn is_unknown(&self) -> bool {
74		matches!(self, Self::Unknown)
75	}
76
77	/// Checks if the code is `InvalidArgument`.
78	#[must_use]
79	#[inline]
80	pub const fn is_invalid_argument(&self) -> bool {
81		matches!(self, Self::InvalidArgument)
82	}
83
84	/// Checks if the code is `DeadlineExceeded`.
85	#[must_use]
86	#[inline]
87	pub const fn is_deadline_exceeded(&self) -> bool {
88		matches!(self, Self::DeadlineExceeded)
89	}
90
91	/// Checks if the code is `NotFound`.
92	#[must_use]
93	#[inline]
94	pub const fn is_not_found(&self) -> bool {
95		matches!(self, Self::NotFound)
96	}
97
98	/// Checks if the code is `AlreadyExists`.
99	#[must_use]
100	#[inline]
101	pub const fn is_already_exists(&self) -> bool {
102		matches!(self, Self::AlreadyExists)
103	}
104
105	/// Checks if the code is `PermissionDenied`.
106	#[must_use]
107	#[inline]
108	pub const fn is_permission_denied(&self) -> bool {
109		matches!(self, Self::PermissionDenied)
110	}
111
112	/// Checks if the code is `Unauthenticated`.
113	#[must_use]
114	#[inline]
115	pub const fn is_unauthenticated(&self) -> bool {
116		matches!(self, Self::Unauthenticated)
117	}
118
119	/// Checks if the code is `ResourceExhausted`.
120	#[must_use]
121	#[inline]
122	pub const fn is_resource_exhausted(&self) -> bool {
123		matches!(self, Self::ResourceExhausted)
124	}
125
126	/// Checks if the code is `FailedPrecondition`.
127	#[must_use]
128	#[inline]
129	pub const fn is_failed_precondition(&self) -> bool {
130		matches!(self, Self::FailedPrecondition)
131	}
132
133	/// Checks if the code is `Aborted`.
134	#[must_use]
135	#[inline]
136	pub const fn is_aborted(&self) -> bool {
137		matches!(self, Self::Aborted)
138	}
139
140	/// Checks if the code is `OutOfRange`.
141	#[must_use]
142	#[inline]
143	pub const fn is_out_of_range(&self) -> bool {
144		matches!(self, Self::OutOfRange)
145	}
146
147	/// Checks if the code is `Unimplemented`.
148	#[must_use]
149	#[inline]
150	pub const fn is_unimplemented(&self) -> bool {
151		matches!(self, Self::Unimplemented)
152	}
153
154	/// Checks if the code is `Internal`.
155	#[must_use]
156	#[inline]
157	pub const fn is_internal(&self) -> bool {
158		matches!(self, Self::Internal)
159	}
160
161	/// Checks if the code is `Unavailable`.
162	#[must_use]
163	#[inline]
164	pub const fn is_unavailable(&self) -> bool {
165		matches!(self, Self::Unavailable)
166	}
167
168	/// Checks if the code is `DataLoss`.
169	#[must_use]
170	#[inline]
171	pub const fn is_data_loss(&self) -> bool {
172		matches!(self, Self::DataLoss)
173	}
174
175	/// Returns the name of the code variant in title case.
176	#[must_use]
177	#[inline]
178	pub const fn as_title_case(&self) -> &'static str {
179		match self {
180			Self::Ok => "Ok",
181			Self::Cancelled => "Cancelled",
182			Self::Unknown => "Unknown",
183			Self::InvalidArgument => "Invalid Argument",
184			Self::DeadlineExceeded => "Deadline Exceeded",
185			Self::NotFound => "Not Found",
186			Self::AlreadyExists => "Already Exists",
187			Self::PermissionDenied => "Permission Denied",
188			Self::Unauthenticated => "Unauthenticated",
189			Self::ResourceExhausted => "Resource Exhausted",
190			Self::FailedPrecondition => "Failed Precondition",
191			Self::Aborted => "Aborted",
192			Self::OutOfRange => "Out Of Range",
193			Self::Unimplemented => "Unimplemented",
194			Self::Internal => "Internal",
195			Self::Unavailable => "Unavailable",
196			Self::DataLoss => "Data Loss",
197		}
198	}
199
200	/// Returns the corresponding HTTP status code mapping.
201	#[must_use]
202	#[inline]
203	pub const fn to_http_status(&self) -> u16 {
204		match self {
205			Self::Ok => 200,
206			Self::Cancelled => 499,
207			Self::Unknown | Self::Internal | Self::DataLoss => 500,
208			Self::InvalidArgument | Self::FailedPrecondition | Self::OutOfRange => 400,
209			Self::DeadlineExceeded => 504,
210			Self::NotFound => 404,
211			Self::AlreadyExists | Self::Aborted => 409,
212			Self::PermissionDenied => 403,
213			Self::Unauthenticated => 401,
214			Self::ResourceExhausted => 429,
215			Self::Unimplemented => 501,
216			Self::Unavailable => 503,
217		}
218	}
219}
220
221impl Display for Code {
222	fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
223		write!(f, "{}", self.as_title_case())
224	}
225}