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);