use core::fmt;
use core::ops::Deref;
use core::str::FromStr;
use crate::category::Category;
use crate::character::Char;
use crate::error::ParseError;
use crate::sqlstate::SqlState;
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Class {
pub(crate) code: [Char; 2],
}
impl Class {
#[inline]
pub const fn from_str(value: &str) -> Result<Self, ParseError> {
Self::from_bytes(value.as_bytes())
}
#[inline]
pub const fn from_bytes(value: &[u8]) -> Result<Self, ParseError> {
match Char::new_array(value) {
Ok(code) => Ok(Self { code }),
Err(e) => Err(e),
}
}
#[inline]
pub const fn from_byte_array(value: [u8; 2]) -> Result<Self, ParseError> {
match Char::new_array(&value) {
Ok(code) => Ok(Self { code }),
Err(e) => Err(e),
}
}
#[inline]
pub const fn category(&self) -> Category {
match self {
sqlstate![0 0] => Category::Success,
sqlstate![0 1] => Category::Warning,
sqlstate![0 2] => Category::NoData,
_ => Category::Exception,
}
}
#[inline]
pub const fn contains(&self, sqlstate: SqlState) -> bool {
let class = sqlstate.class();
let self_arrayref = Char::array_as_bytes(&self.code);
let other_arrayref = Char::array_as_bytes(&class.code);
self_arrayref[0] == other_arrayref[0] && self_arrayref[1] == other_arrayref[1]
}
#[inline]
pub const fn is_implementation_specific(&self) -> bool {
!matches!(
self.code[0],
Char::_0
| Char::_1 | Char::_2
| Char::_3 | Char::_4
| Char::A | Char::B
| Char::C | Char::D
| Char::E | Char::F
| Char::G | Char::H
)
}
}
impl Class {
pub const SUCCESSFUL_COMPLETION: Self = sqlstate![0 0];
pub const WARNING: Self = sqlstate![0 1];
pub const NO_DATA: Self = sqlstate![0 2];
pub const DYNAMIC_SQL_ERROR: Self = sqlstate![0 7];
pub const CONNECTION_EXCEPTION: Self = sqlstate![0 8];
pub const TRIGGERED_ACTION_EXCEPTION: Self = sqlstate![0 9];
pub const FEATURE_NOT_SUPPORTED: Self = sqlstate![0 A];
pub const INVALID_TARGET_TYPE_SPEC: Self = sqlstate![0 D];
pub const INVALID_SCHEMA_NAME_LIST_SPEC: Self = sqlstate![0 E];
pub const LOCATOR_EXCEPTION: Self = sqlstate![0 F];
pub const RESIGNAL_WHEN_HANDLER_NOT_ACTIVE: Self = sqlstate![0 K];
pub const INVALID_GRANTOR: Self = sqlstate![0 L];
pub const INVALID_SQL_INVOKED_PROCEDURE_REF: Self = sqlstate![0 M];
pub const SQL_XML_MAPPING_ERROR: Self = sqlstate![0 N];
pub const INVALID_ROLE_SPEC: Self = sqlstate![0 P];
pub const INVALID_TRANSFORM_GROUP_NAME_SPEC: Self = sqlstate![0 S];
pub const TARGET_TABLE_DISAGREES_WITH_CURSOR_SPEC: Self = sqlstate![0 T];
pub const ATTEMPT_TO_ASSIGN_TO_NON_UPDATABLE_COLUMN: Self = sqlstate![0 U];
pub const ATTEMPT_TO_ASSSIGN_TO_ORDERING_COLUMN: Self = sqlstate![0 V];
pub const PROHIBITED_STATEMENT_DURING_TRIGGER_EXEC: Self = sqlstate![0 W];
pub const INVALID_FOREIGN_SERVER_SPEC: Self = sqlstate![0 X];
pub const PASSTHROUGH_SPECIFIC_CONDITION: Self = sqlstate![0 Y];
pub const DIAGNOSTICS_EXCEPTION: Self = sqlstate![0 Z];
pub const XQUERY_ERROR: Self = sqlstate![1 0];
pub const CASE_NOT_FOUND_FOR_CASE_STATEMENT: Self = sqlstate![2 0];
pub const CARDINALITY_VIOLATION: Self = sqlstate![2 1];
pub const DATA_EXCEPTION: Self = sqlstate![2 2];
pub const INTEGRITY_CONSTRAINT_VIOLATION: Self = sqlstate![2 3];
pub const INVALID_CURSOR_STATE: Self = sqlstate![2 4];
pub const INVALID_TRANSACTION_STATE: Self = sqlstate![2 5];
pub const INVALID_SQL_STATEMENT_NAME: Self = sqlstate![2 6];
pub const TRIGGERED_DATA_CHANGE_VIOLATION: Self = sqlstate![2 7];
pub const INVALID_AUTHORIZATION_SPEC: Self = sqlstate![2 8];
pub const DEPENDENT_PRIVILEGE_DESCRIPTORS_STILL_EXIST: Self = sqlstate![2 B];
pub const INVALID_CHARACTER_SET_NAME: Self = sqlstate![2 C];
pub const INVALID_TRANSACTION_TERMINATION: Self = sqlstate![2 D];
pub const INVALID_CONNECTION_NAME: Self = sqlstate![2 E];
pub const SQL_ROUTINE_EXCEPTION: Self = sqlstate![2 F];
pub const INVALID_COLLATION_NAME: Self = sqlstate![2 H];
pub const INVALID_SQL_STATEMENT_IDENTIFIER: Self = sqlstate![3 0];
pub const INVALID_SQL_DESCRIPTOR_NAME: Self = sqlstate![3 3];
pub const INVALID_CURSOR_NAME: Self = sqlstate![3 4];
pub const INVALID_CONNECTION_NUMBER: Self = sqlstate![3 5];
pub const CURSOR_SENSITIVITY_EXCEPTION: Self = sqlstate![3 6];
pub const EXTERNAL_ROUTINE_EXCEPTION: Self = sqlstate![3 8];
pub const EXTERNAL_ROUTINE_INVOCATION_EXCEPTION: Self = sqlstate![3 9];
pub const SAVEPOINT_EXCEPTION: Self = sqlstate![3 B];
pub const AMBIGUOUS_CURSOR_NAME: Self = sqlstate![3 C];
pub const INVALID_CATALOG_NAME: Self = sqlstate![3 D];
pub const INVALID_SCHEMA_NAME: Self = sqlstate![3 F];
pub const TRANSACTION_ROLLBACK: Self = sqlstate![4 0];
pub const SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION: Self = sqlstate![4 2];
pub const WITH_CHECK_OPTION_VIOLATION: Self = sqlstate![4 4];
pub const UNHANDLED_USER_DEFINED_EXCEPTION: Self = sqlstate![4 5];
pub const OLB_SPECIFIC_ERROR: Self = sqlstate![4 6];
pub const DATALINK_EXCEPTION: Self = sqlstate![H W];
pub const FDW_SPECIFIC_CONDITION: Self = sqlstate![H V];
pub const CLI_SPECIFIC_CONDITION: Self = sqlstate![H Y];
}
impl Class {
pub const DB2_INVALID_APPLICATION_STATE: Self = sqlstate![5 1];
pub const DB2_INVALID_OPERAND_OR_INCONSISTENT_SPEC: Self = sqlstate![5 3];
pub const DB2_SQL_OR_PRODUCT_LIMIT_EXCEEDED: Self = sqlstate![5 4];
pub const DB2_OBJECT_NOT_IN_PREREQUISITE_STATE: Self = sqlstate![5 5];
pub const DB2_MISCELLANEOUS_SQL_OR_PRODUCT_ERROR: Self = sqlstate![5 6];
pub const DB2_RESOURCE_NOT_AVAILABLE_OR_OPERATOR_INTERVENTION: Self = sqlstate![5 7];
pub const DB2_SYSTEM_ERROR: Self = sqlstate![5 8];
pub const DB2_COMMON_UTILITIES_AND_TOOLS: Self = sqlstate![5 U];
}
impl Class {
pub const PGSQL_INSUFFICIENT_RESOURCES: Self = sqlstate![5 3];
pub const PGSQL_PROGRAM_LIMIT_EXCEEDED: Self = sqlstate![5 4];
pub const PGSQL_OBJECT_NOT_IN_PREREQUISITE_STATE: Self = sqlstate![5 5];
pub const PGSQL_OPERATOR_INTERVENTION: Self = sqlstate![5 7];
pub const PGSQL_SYSTEM_ERROR: Self = sqlstate![5 8];
pub const PGSQL_SNAPSHOT_FAILURE: Self = sqlstate![7 2];
pub const PGSQL_CONFIGURATION_FILE_ERROR: Self = sqlstate![F 0];
pub const PGSQL_PL_PGSQL_ERROR: Self = sqlstate![P 0];
pub const PGSQL_INTERNAL_ERROR: Self = sqlstate![X X];
}
impl Class {
pub const MYSQL_INTERRUPTION: Self = sqlstate![7 0];
pub const MYSQL_XA_ERROR: Self = sqlstate![X A];
}
impl Class {
pub const ODBC_DRIVER_ERROR: Self = sqlstate![I M];
}
impl Class {
pub const ORACLE_SYSTEM_ERROR: Self = sqlstate![6 0];
pub const ORACLE_RESOURCE_ERROR: Self = sqlstate![6 1];
pub const ORACLE_PATH_NAME_SERVER_AND_DETACHED_PROCESS_ERROR: Self = sqlstate![6 2];
pub const ORACLE_CA_OR_TWO_TASK_INTERFACE_ERROR: Self = sqlstate![6 3];
pub const ORACLE_FILE_OR_MEDIA_RECOVERY_ERROR: Self = sqlstate![6 4];
pub const ORACLE_PL_SQL_ERROR: Self = sqlstate![6 5];
pub const ORACLE_SQL_NET_DRIVER_ERROR: Self = sqlstate![6 6];
pub const ORACLE_LICENSING_ERROR: Self = sqlstate![6 7];
pub const ORACLE_SQL_CONNECT_ERROR: Self = sqlstate![6 9];
pub const ORACLE_SQL_EXECUTE_PHASE_ERROR: Self = sqlstate![7 2];
pub const ORACLE_INTERNAL_ERROR: Self = sqlstate![8 2];
pub const ORACLE_DEBUG_EVENT: Self = sqlstate![9 0];
}
impl fmt::Debug for Class {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
f.debug_tuple("Class").field(&&**self).finish()
}
}
impl fmt::Display for Class {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
f.write_str(self)
}
}
impl AsRef<str> for Class {
#[inline]
fn as_ref(&self) -> &str {
self
}
}
impl AsRef<[u8]> for Class {
#[inline]
fn as_ref(&self) -> &[u8] {
Char::array_as_bytes(&self.code)
}
}
impl AsRef<[u8; 2]> for Class {
#[inline]
fn as_ref(&self) -> &[u8; 2] {
Char::array_as_bytes(&self.code)
}
}
impl From<Class> for [u8; 2] {
#[inline]
fn from(class: Class) -> Self {
class.code.map(Char::as_byte)
}
}
impl Deref for Class {
type Target = str;
#[inline]
fn deref(&self) -> &Self::Target {
Char::array_as_str(&self.code)
}
}
impl PartialEq<str> for Class {
fn eq(&self, other: &str) -> bool {
&**self == other
}
}
impl PartialEq<[u8]> for Class {
fn eq(&self, other: &[u8]) -> bool {
AsRef::<[u8]>::as_ref(self) == other
}
}
impl FromStr for Class {
type Err = ParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Self::from_bytes(s.as_bytes())
}
}
impl TryFrom<&[u8]> for Class {
type Error = ParseError;
fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
Self::from_bytes(bytes)
}
}
impl TryFrom<[u8; 2]> for Class {
type Error = ParseError;
fn try_from(bytes: [u8; 2]) -> Result<Self, Self::Error> {
Self::from_byte_array(bytes)
}
}
impl TryFrom<&str> for Class {
type Error = ParseError;
fn try_from(string: &str) -> Result<Self, Self::Error> {
Self::from_str(string)
}
}
#[cfg(feature = "serde")]
impl serde::Serialize for Class {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_str(self)
}
}
#[cfg(feature = "serde")]
impl<'de> serde::Deserialize<'de> for Class {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
deserializer
.deserialize_str(crate::character::de::ArrayVisitor::new())
.map(|code| Self { code })
}
}
const _: () = assert!(core::mem::size_of::<Class>() == 2);
const _: () = assert!(core::mem::size_of::<Option<Class>>() == 2);
const _: () = assert!(core::mem::size_of::<Option<Option<Class>>>() == 2);