1pub use crate::{
5 Decode, Encode, constraints, permitted_alphabet_constraint, size_constraint, value_constraint,
6};
7
8#[macro_use]
9#[cfg(test)]
10pub mod test;
11
12#[macro_export]
27macro_rules! value_constraint {
28 ($($args:tt)*) => {
29 $crate::bounded_constraint!(Value, $($args)*)
30 };
31}
32
33#[macro_export]
48macro_rules! size_constraint {
49 ($($args:tt)*) => {
50 $crate::bounded_constraint!(Size, $($args)*)
51 };
52}
53
54#[macro_export]
63macro_rules! constraints {
64 ($($constraint:expr),+ $(,)?) => {
65 $crate::types::constraints::Constraints::new(&[$($constraint),+])
66 };
67}
68#[macro_export]
84macro_rules! permitted_alphabet_constraint {
85 ( $alphabet:expr) => {
86 $crate::types::constraints::Constraint::PermittedAlphabet(
87 $crate::types::constraints::Extensible::new(
88 $crate::types::constraints::PermittedAlphabet::new($alphabet),
89 ),
90 )
91 };
92}
93
94#[doc(hidden)]
95#[macro_export]
96macro_rules! bounded_constraint {
97 ($constraint_type:ident, $single:expr, extensible) => {
99 $crate::types::constraints::Constraint::$constraint_type(
100 $crate::types::constraints::Extensible::new(
101 $crate::types::constraints::$constraint_type::new(
102 $crate::types::constraints::Bounded::Single($single),
103 ),
104 )
105 .set_extensible(true),
106 )
107 };
108
109 ($constraint_type:ident, $start:expr, $end:expr, extensible) => {
111 $crate::types::constraints::Constraint::$constraint_type(
112 $crate::types::constraints::Extensible::new(
113 $crate::types::constraints::$constraint_type::new(
114 $crate::types::constraints::Bounded::const_new($start, $end),
115 ),
116 )
117 .set_extensible(true),
118 )
119 };
120
121 ($constraint_type:ident, start: $start:expr, extensible) => {
123 $crate::types::constraints::Constraint::$constraint_type(
124 $crate::types::constraints::Extensible::new(
125 $crate::types::constraints::$constraint_type::new(
126 $crate::types::constraints::Bounded::start_from($start),
127 ),
128 )
129 .set_extensible(true),
130 )
131 };
132
133 ($constraint_type:ident, end: $end:expr, extensible) => {
135 $crate::types::constraints::Constraint::$constraint_type(
136 $crate::types::constraints::Extensible::new(
137 $crate::types::constraints::$constraint_type::new(
138 $crate::types::constraints::Bounded::up_to($end),
139 ),
140 )
141 .set_extensible(true),
142 )
143 };
144
145 ($constraint_type:ident, $start:expr, $end:expr) => {
147 $crate::types::constraints::Constraint::$constraint_type(
148 $crate::types::constraints::Extensible::new(
149 $crate::types::constraints::$constraint_type::new(
150 $crate::types::constraints::Bounded::const_new($start, $end),
151 ),
152 ),
153 )
154 };
155
156 ($constraint_type:ident, start: $start:expr) => {
158 $crate::types::constraints::Constraint::$constraint_type(
159 $crate::types::constraints::Extensible::new(
160 $crate::types::constraints::$constraint_type::new(
161 $crate::types::constraints::Bounded::start_from($start),
162 ),
163 ),
164 )
165 };
166
167 ($constraint_type:ident, end: $end:expr) => {
169 $crate::types::constraints::Constraint::$constraint_type(
170 $crate::types::constraints::Extensible::new(
171 $crate::types::constraints::$constraint_type::new(
172 $crate::types::constraints::Bounded::up_to($end),
173 ),
174 ),
175 )
176 };
177
178 ($constraint_type:ident, $single:expr) => {
180 $crate::types::constraints::Constraint::$constraint_type(
181 $crate::types::constraints::Extensible::new(
182 $crate::types::constraints::$constraint_type::new(
183 $crate::types::constraints::Bounded::Single($single),
184 ),
185 ),
186 )
187 };
188}
189
190#[macro_export]
201macro_rules! oid {
202 ($s:literal) => {{
203 const OID: &'static $crate::types::Oid = const {
204 const BYTE_STRING: &'static [u8] = const {
205 let s: &'static str = $s;
206 let bytes = s.as_bytes();
207
208 core::assert!(!bytes.is_empty(), "OID string literals cannot be empty");
209 core::assert!(bytes.is_ascii(), "OID string literals must be ASCII");
210 core::assert!(
211 bytes[bytes.len() - 1] != b'.',
212 "OID string literals cannot end with a period"
213 );
214
215 match bytes {
216 [b'.', rest @ ..] => rest,
217 bytes => bytes,
218 }
219 };
220
221 const COMPONENT_LEN: usize = const {
222 let mut component_count = 1;
223 let mut index = 0;
224 while index < BYTE_STRING.len() {
225 let byte = BYTE_STRING[index];
226
227 core::assert!(
228 core::matches!(byte, b'0'..=b'9' | b'.'),
229 "OID string literals can only contain ASCII digits and periods"
230 );
231
232 if byte == b'.' {
233 if index + 1 < BYTE_STRING.len() {
234 core::assert!(
235 BYTE_STRING[index + 1] != b'.',
236 "OID string literals cannot contain two or more consecutive periods"
237 );
238 }
239 component_count += 1;
240 }
241
242 index += 1;
243 }
244
245 component_count
246 };
247
248 const COMPONENTS: [u32; COMPONENT_LEN] = const {
249 let mut bytes_index = 0;
250
251 let mut components = [0u32; COMPONENT_LEN];
252 let mut index = 0;
253 while bytes_index < BYTE_STRING.len() {
254 let byte = BYTE_STRING[bytes_index];
255 match byte {
256 b'0'..=b'9' => {
257 components[index] = components[index] * 10 + ((byte - b'0') as u32)
258 }
259 b'.' => index += 1,
260 _ => core::unreachable!(),
261 }
262
263 bytes_index += 1;
264 }
265
266 core::assert!(components[0] <= 2, "the first OID arc must be <= 2");
267
268 components
269 };
270
271 $crate::types::Oid::new(&COMPONENTS).unwrap()
272 };
273
274 OID
275 }};
276}