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