sqlstate_inline/error.rs
1// © 2022 Christoph Grenz <https://grenz-bonn.de>
2//
3// SPDX-License-Identifier: MPL-2.0
4
5#[cfg(feature = "std")]
6use std::io;
7
8/// Error creating an [`SqlState`], [`Class`] or [`Category`].
9///
10/// [`SqlState`]: `struct@super::SqlState`
11/// [`SqlState`]: `struct@super::SqlState`
12/// [`Class`]: `struct@super::Class`
13/// [`Category`]: `super::Category`
14#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15#[cfg_attr(feature = "std", derive(thiserror::Error))]
16pub enum ParseError {
17 /// The byte at index `position` in the string was not a valid ASCII character in the range `A-Z`,`0-9`.
18 #[cfg_attr(
19 feature = "std",
20 error("invalid character {byte:?} at position {position}")
21 )]
22 InvalidChar { byte: u8, position: usize },
23 /// The source string didn't have the expected length.
24 #[cfg_attr(
25 feature = "std",
26 error("wrong string length (expected {expected}, got {got})")
27 )]
28 WrongLength { expected: u8, got: usize },
29}
30
31impl ParseError {
32 /// Returns the index of the first invalid byte, the position of the premature end or of the
33 /// first superfluous byte.
34 ///
35 /// ```
36 /// # use sqlstate_inline::SqlState;
37 /// if let Err(error) = SqlState::from_str("000!0") {
38 /// let index = error.valid_up_to();
39 /// assert_eq!(index, 3);
40 /// } else {
41 /// unreachable!("this is no valid SQLSTATE code");
42 /// }
43 /// ```
44 pub const fn valid_up_to(&self) -> usize {
45 match *self {
46 Self::InvalidChar { position, .. } => position,
47 Self::WrongLength { expected, got } if got > (expected as _) => expected as _,
48 Self::WrongLength { got, .. } => got,
49 }
50 }
51}
52
53#[cfg(feature = "std")]
54impl From<ParseError> for io::Error {
55 /// Converts a `ParseError` to an `std::io::Error` of kind `InvalidData` for convenience.
56 fn from(error: ParseError) -> Self {
57 Self::new(io::ErrorKind::InvalidData, error)
58 }
59}
60
61// Statically assert that an `Option<ParseError>` is at most as big as two pointers for
62// architectures with usual pointer sizes (>= 32 bit).
63//
64// We want e.g. `Result<[Char; 5], ParseError>` to be this small, but this optimization is only
65// supported since Rust 1.65
66#[cfg(any(
67 target_pointer_width = "32",
68 target_pointer_width = "64",
69 target_pointer_width = "128"
70))]
71const _: () =
72 assert!(core::mem::size_of::<Option<ParseError>>() <= core::mem::size_of::<usize>() * 2);