sqlstate_inline/
sqlstate.rs1use core::fmt;
6use core::ops::Deref;
7use core::str::FromStr;
8#[cfg(feature = "std")]
9use std::io;
10
11use crate::category::Category;
12use crate::character::Char;
13use crate::class::Class;
14use crate::error::ParseError;
15
16#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
22pub struct SqlState {
23 code: [Char; 5],
24}
25
26impl SqlState {
27 #[inline]
45 pub const fn from_str(value: &str) -> Result<Self, ParseError> {
46 Self::from_bytes(value.as_bytes())
47 }
48
49 #[inline]
68 pub const fn from_str_lossy(value: &str) -> Self {
69 Self::from_bytes_lossy(value.as_bytes())
70 }
71
72 #[inline]
90 pub const fn from_bytes(value: &[u8]) -> Result<Self, ParseError> {
91 match Char::new_array(value) {
92 Ok(code) => Ok(Self { code }),
93 Err(e) => Err(e),
94 }
95 }
96
97 #[inline]
101 pub const fn from_bytes_lossy(value: &[u8]) -> Self {
102 if value.is_empty() {
103 Self::UNKNOWN
104 } else {
105 Self {
106 code: Char::new_array_lossy(value, Char::X),
107 }
108 }
109 }
110
111 pub const fn from_byte_array(value: [u8; 5]) -> Result<Self, ParseError> {
131 match Char::new_array(&value) {
132 Ok(code) => Ok(Self { code }),
133 Err(e) => Err(e),
134 }
135 }
136
137 #[inline]
146 pub const fn category(&self) -> Category {
147 match self {
148 sqlstate![0 0 ..] => Category::Success,
149 sqlstate![0 1 ..] => Category::Warning,
150 sqlstate![0 2 ..] => Category::NoData,
151 _ => Category::Exception,
152 }
153 }
154
155 #[inline]
165 pub const fn class(&self) -> Class {
166 match self.code {
167 [a, b, _, _, _] => Class { code: [a, b] },
168 }
169 }
170
171 #[inline]
189 pub const fn is_implementation_specific(&self) -> bool {
190 !matches!(
191 self.code[0],
192 Char::_0
193 | Char::_1 | Char::_2
194 | Char::_3 | Char::_4
195 | Char::A | Char::B
196 | Char::C | Char::D
197 | Char::E | Char::F
198 | Char::G | Char::H
199 ) || !matches!(
200 self.code[2],
201 Char::_0
202 | Char::_1 | Char::_2
203 | Char::_3 | Char::_4
204 | Char::A | Char::B
205 | Char::C | Char::D
206 | Char::E | Char::F
207 | Char::G | Char::H
208 )
209 }
210
211 #[inline]
215 pub const fn has_subclass(&self) -> bool {
216 !matches!(self.code, [_, _, Char::_0, Char::_0, Char::_0])
217 }
218
219 pub const UNKNOWN: Self = sqlstate![9 9 9 9 9];
224}
225
226impl fmt::Debug for SqlState {
227 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
228 f.debug_tuple("SqlState").field(&&**self).finish()
229 }
230}
231
232impl fmt::Display for SqlState {
233 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
234 f.write_str(self)
235 }
236}
237
238impl AsRef<str> for SqlState {
239 #[inline]
240 fn as_ref(&self) -> &str {
241 self
242 }
243}
244
245impl AsRef<[u8]> for SqlState {
246 #[inline]
247 fn as_ref(&self) -> &[u8] {
248 Char::array_as_bytes(&self.code)
249 }
250}
251
252impl AsRef<[u8; 5]> for SqlState {
253 #[inline]
254 fn as_ref(&self) -> &[u8; 5] {
255 Char::array_as_bytes(&self.code)
256 }
257}
258
259impl From<SqlState> for [u8; 5] {
260 #[inline]
261 fn from(sqlstate: SqlState) -> Self {
262 sqlstate.code.map(Char::as_byte)
263 }
264}
265
266impl Deref for SqlState {
267 type Target = str;
268 #[inline]
269 fn deref(&self) -> &Self::Target {
270 Char::array_as_str(&self.code)
271 }
272}
273
274impl PartialEq<str> for SqlState {
275 fn eq(&self, other: &str) -> bool {
276 &**self == other
277 }
278}
279
280impl PartialEq<[u8]> for SqlState {
281 fn eq(&self, other: &[u8]) -> bool {
282 AsRef::<[u8]>::as_ref(self) == other
283 }
284}
285
286#[cfg(feature = "std")]
287impl From<SqlState> for io::ErrorKind {
288 fn from(state: SqlState) -> Self {
296 match state {
297 sqlstate![0 8 0 0 1] | sqlstate![0 8 0 0 4] => Self::ConnectionRefused,
299 sqlstate![0 8 0 0 3] => Self::ConnectionAborted,
300 sqlstate![0 8 ..] => Self::ConnectionReset,
301
302 sqlstate![0 A ..] => Self::Unsupported,
304
305 sqlstate![2 1 ..] => Self::InvalidInput,
307
308 sqlstate![2 2 ..] => Self::InvalidData,
310
311 sqlstate![2 3 5 0 5] => Self::AlreadyExists,
313 sqlstate![2 3 ..] => Self::PermissionDenied,
314
315 sqlstate![2 5 P 0 3] => Self::TimedOut,
318
319 sqlstate![2 6 ..] => Self::InvalidData,
321
322 sqlstate![2 8 ..] => Self::PermissionDenied,
324
325 sqlstate![4 0 0 0 2] => Self::PermissionDenied,
328 sqlstate![4 2 5 ..] => Self::PermissionDenied,
332 sqlstate![4 2 S 0 1] => Self::AlreadyExists,
333 sqlstate![4 2 S 0 2] | sqlstate![4 2 S 1 2] => Self::NotFound,
334 sqlstate![4 2 ..] => Self::InvalidInput,
335
336 sqlstate![4 4 ..] => Self::PermissionDenied,
338
339 sqlstate![5 3 2 0 0] => Self::OutOfMemory,
342 sqlstate![5 3 3 0 0] => Self::ConnectionRefused,
343
344 sqlstate![5 4 ..] => Self::InvalidInput,
346
347 sqlstate![5 7 0 1 4] => Self::Interrupted,
349 sqlstate![5 7 P 0 1] => Self::ConnectionReset,
350 sqlstate![5 7 P 0 2] => Self::ConnectionReset,
351 sqlstate![5 7 P 0 3] => Self::ConnectionRefused,
352 sqlstate![5 7 P 0 5] => Self::ConnectionAborted,
354
355 sqlstate![7 0 1 0 0] => Self::Interrupted,
357
358 sqlstate![H V 0 0 1] => Self::OutOfMemory,
360 sqlstate![H V 0 0 N] => Self::BrokenPipe,
362
363 sqlstate![H Y 0 0 1] => Self::OutOfMemory,
365 sqlstate![H Y 0 0 8] => Self::TimedOut,
366
367 sqlstate![X X 0 0 1] | sqlstate![X X 0 0 2] => Self::UnexpectedEof,
369
370 _ => Self::Other,
371 }
372 }
373}
374
375impl FromStr for SqlState {
376 type Err = ParseError;
377
378 fn from_str(s: &str) -> Result<Self, Self::Err> {
379 Self::from_bytes(s.as_bytes())
380 }
381}
382
383impl TryFrom<&[u8]> for SqlState {
384 type Error = ParseError;
385
386 fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
387 Self::from_bytes(bytes)
388 }
389}
390
391impl TryFrom<[u8; 5]> for SqlState {
392 type Error = ParseError;
393
394 fn try_from(bytes: [u8; 5]) -> Result<Self, Self::Error> {
395 Self::from_byte_array(bytes)
396 }
397}
398
399impl TryFrom<&str> for SqlState {
400 type Error = ParseError;
401
402 fn try_from(string: &str) -> Result<Self, Self::Error> {
403 Self::from_str(string)
404 }
405}
406
407#[cfg(feature = "serde")]
408impl serde::Serialize for SqlState {
409 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
410 where
411 S: serde::Serializer,
412 {
413 serializer.serialize_str(self)
414 }
415}
416
417#[cfg(feature = "serde")]
418impl<'de> serde::Deserialize<'de> for SqlState {
419 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
420 where
421 D: serde::Deserializer<'de>,
422 {
423 deserializer
424 .deserialize_str(crate::character::de::ArrayVisitor::new())
425 .map(|arr| Self { code: arr })
426 }
427}
428
429const _: () = assert!(core::mem::size_of::<SqlState>() == 5);
431const _: () = assert!(core::mem::size_of::<Option<Option<SqlState>>>() == 5);