1pub use crate::{
5 constraints, permitted_alphabet_constraint, size_constraint, value_constraint, Decode, Encode,
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!(bytes[bytes.len() - 1] != b'.', "OID string literals cannot end with a period");
211
212 match bytes {
213 [b'.', rest @ ..] => rest,
214 bytes => bytes,
215 }
216 };
217
218 const COMPONENT_LEN: usize = const {
219 let mut component_count = 1;
220 let mut index = 0;
221 while index < BYTE_STRING.len() {
222 let byte = BYTE_STRING[index];
223
224 core::assert!(core::matches!(byte, b'0'..=b'9' | b'.'), "OID string literals can only contain ASCII digits and periods");
225
226 if byte == b'.' {
227 if index + 1 < BYTE_STRING.len() {
228 core::assert!(BYTE_STRING[index + 1] != b'.', "OID string literals cannot contain two or more consecutive periods");
229 }
230 component_count += 1;
231 }
232
233 index += 1;
234 }
235
236 component_count
237 };
238
239 const COMPONENTS: [u32; COMPONENT_LEN] = const {
240 let mut bytes_index = 0;
241
242 let mut components = [0u32; COMPONENT_LEN];
243 let mut index = 0;
244 while bytes_index < BYTE_STRING.len() {
245 let byte = BYTE_STRING[bytes_index];
246 match byte {
247 b'0'..=b'9' => components[index] = components[index] * 10 + ((byte - b'0') as u32),
248 b'.' => index += 1,
249 _ => core::unreachable!(),
250 }
251
252 bytes_index += 1;
253 }
254
255 core::assert!(components[0] <= 2, "the first OID arc must be <= 2");
256
257 components
258 };
259
260 $crate::types::Oid::new(&COMPONENTS).unwrap()
261 };
262
263 OID
264 }}
265}