sqlstate_inline/lib.rs
1// © 2022 Christoph Grenz <https://grenz-bonn.de>
2//
3// SPDX-License-Identifier: MPL-2.0
4
5#![cfg_attr(not(feature = "std"), no_std)]
6
7/// Helper macro: maps digits and identifiers to `Char` variants.
8macro_rules! _sqlstate {
9 (0) => {
10 $crate::character::Char::_0
11 };
12 (1) => {
13 $crate::character::Char::_1
14 };
15 (2) => {
16 $crate::character::Char::_2
17 };
18 (3) => {
19 $crate::character::Char::_3
20 };
21 (4) => {
22 $crate::character::Char::_4
23 };
24 (5) => {
25 $crate::character::Char::_5
26 };
27 (6) => {
28 $crate::character::Char::_6
29 };
30 (7) => {
31 $crate::character::Char::_7
32 };
33 (8) => {
34 $crate::character::Char::_8
35 };
36 (9) => {
37 $crate::character::Char::_9
38 };
39 ($x:ident) => {
40 $crate::character::Char::$x
41 };
42}
43
44/// Simplifies creation of `SqlState` and `Class` patterns inside this crate.
45///
46/// - `sqlstate![0 1 2 3 4]` produces a constant with the same value as `SqlState::from_str("01234")?`
47/// - `sqlstate![0 1 2 ..]` generates a pattern that matches `SqlState::from_str("012xx")?`
48/// - `sqlstate![0 1 ..]` generates a pattern that matches `SqlState::from_str("01xxx")?` etc.
49macro_rules! sqlstate {
50 ($a:tt $b:tt $c:tt $d:tt $e:tt) => {
51 $crate::SqlState {
52 code: [
53 _sqlstate!($a),
54 _sqlstate!($b),
55 _sqlstate!($c),
56 _sqlstate!($d),
57 _sqlstate!($e),
58 ],
59 }
60 };
61 ($a:tt $b:tt $c:tt $d:tt ..) => {
62 $crate::SqlState {
63 code: [
64 _sqlstate!($a),
65 _sqlstate!($b),
66 _sqlstate!($c),
67 _sqlstate!($d),
68 ..,
69 ],
70 }
71 };
72 ($a:tt $b:tt $c:tt ..) => {
73 $crate::SqlState {
74 code: [_sqlstate!($a), _sqlstate!($b), _sqlstate!($c), ..],
75 }
76 };
77 ($a:tt $b:tt ..) => {
78 $crate::SqlState {
79 code: [_sqlstate!($a), _sqlstate!($b), ..],
80 }
81 };
82 ($a:tt ..) => {
83 $crate::SqlState {
84 code: [_sqlstate!($a), ..],
85 }
86 };
87 ($a:tt $b:tt) => {
88 $crate::Class {
89 code: [_sqlstate!($a), _sqlstate!($b)],
90 }
91 };
92}
93
94mod category;
95mod character;
96mod class;
97mod error;
98mod sqlstate;
99
100pub use category::Category;
101pub use class::Class;
102pub use error::ParseError;
103pub use sqlstate::SqlState;
104
105/// Helper module for import trickery to overlay functions over structs
106#[allow(non_snake_case)]
107mod _fn {
108 /// SQLSTATE constant constructor
109 ///
110 /// Can be used to define constant values for [`SqlState`] from string literals.
111 ///
112 /// Use [`SqlState::from_str()`] for non-literals.
113 ///
114 /// # Panics
115 /// Panics if the passed string is not a valid SQLSTATE.
116 ///
117 /// # Examples
118 /// ```
119 /// # use sqlstate_inline::SqlState;
120 /// # fn some_db_query_function<T>(_:T) -> SqlState { SqlState("XRUST") }
121 /// const MY_ERROR: SqlState = SqlState("XRUST");
122 ///
123 /// let sqlstate = some_db_query_function(..);
124 ///
125 /// match sqlstate {
126 /// MY_ERROR => println!("got my expected error"),
127 /// _ => panic!("unexpected condition")
128 /// }
129 /// ```
130 ///
131 /// An invalid SQLSTATE code in a constant context will cause a compile time panic:
132 /// ```compile_fail
133 /// # use sqlstate_inline::{SqlState};
134 /// const MY_ERROR_CLASS: SqlState = SqlState("!RUST"); // error: evaluation of constant value failed
135 /// ```
136 /// but an invalid SQLSTATE code in a non-constant context may only panic at runtime:
137 /// ```should_panic
138 /// # use sqlstate_inline::{SqlState};
139 /// let some_class = SqlState("!RUST"); // panics
140 /// ```
141 /// [`SqlState`]: `struct@super::SqlState`
142 /// [`SqlState::from_str()`]: `super::SqlState::from_str()`
143 #[inline]
144 pub const fn SqlState(value: &'static str) -> super::SqlState {
145 match super::SqlState::from_str(value) {
146 Ok(result) => result,
147 Err(_) => panic!("{}", "invalid SQLSTATE string"),
148 }
149 }
150
151 /// Class code constant constructor
152 ///
153 /// Can be used to define constant values for [`Class`] from string literals.
154 ///
155 /// Use [`Class::from_str()`] for non-literals.
156 ///
157 /// # Panics
158 /// Panics if the passed string is not a valid class code.
159 ///
160 /// # Examples
161 /// ```
162 /// # use sqlstate_inline::{SqlState, Class};
163 /// # fn some_db_query_function<T>(_:T) -> SqlState { SqlState("XRUST") }
164 /// const MY_ERROR_CLASS: Class = Class("XR");
165 ///
166 /// let sqlstate = some_db_query_function(..);
167 ///
168 /// match sqlstate.class() {
169 /// MY_ERROR_CLASS => println!("got an error in my expected class"),
170 /// _ => panic!("unexpected condition")
171 /// }
172 /// ```
173 ///
174 /// An invalid class code in a constant context will cause a compile time panic:
175 /// ```compile_fail
176 /// # use sqlstate_inline::{Class};
177 /// const MY_ERROR_CLASS: Class = Class("!R"); // error: evaluation of constant value failed
178 /// ```
179 /// but an invalid class code in a non-constant context may only panic at runtime:
180 /// ```should_panic
181 /// # use sqlstate_inline::{Class};
182 /// let some_class = Class("!R"); // panics
183 /// ```
184 /// [`Class`]: `struct@super::Class`
185 /// [`Class::from_str()`]: `super::Class::from_str()`
186 #[inline]
187 pub const fn Class(value: &'static str) -> super::Class {
188 match super::Class::from_str(value) {
189 Ok(result) => result,
190 Err(_) => panic!("{}", "invalid SQLSTATE class string"),
191 }
192 }
193}
194pub use _fn::*;