iri_string/types/generic/macros.rs
1//! Macros to define resource identifier types.
2
3/// Implements type conversion from slice into smart pointer.
4macro_rules! impl_from_slice_into_smartptr {
5 (
6 // Generic slice type.
7 ty: $ty:ident,
8 // Smart pointer item path (without type parameter).
9 smartptr: $($smartptr:ident)::*,
10 // Pointer mutability for `into_raw` and `from_raw`.
11 // Use `mut` for `Box`, and `const` for `Arc` and `Rc`.
12 mutability: $mut:ident,
13 ) => {
14 #[cfg(feature = "alloc")]
15 impl<S: crate::spec::Spec> From<&$ty<S>> for $($smartptr)::* <$ty<S>> {
16 fn from(s: &$ty<S>) -> Self {
17 let inner: &str = s.as_str();
18 let buf = $($smartptr)::* ::<str>::from(inner);
19 // SAFETY: `$ty<S>` has `repr(transparent)` attribute, so the
20 // memory layouts of `$smartptr<str>` and `$smartptr<$ty<S>>`
21 // are compatible.
22 unsafe {
23 let raw: *$mut str = $($smartptr)::* ::into_raw(buf);
24 $($smartptr)::* ::<$ty<S>>::from_raw(raw as *$mut $ty<S>)
25 }
26 }
27 }
28 };
29}
30
31/// Implements `PartialEq` and `PartialOrd`.
32macro_rules! impl_cmp {
33 ($ty_common:ty, $ty_lhs:ty, $ty_rhs:ty) => {
34 impl<S: crate::spec::Spec> PartialEq<$ty_rhs> for $ty_lhs {
35 #[inline]
36 fn eq(&self, o: &$ty_rhs) -> bool {
37 <$ty_common as PartialEq<$ty_common>>::eq(self.as_ref(), o.as_ref())
38 }
39 }
40 impl<S: crate::spec::Spec> PartialEq<$ty_lhs> for $ty_rhs {
41 #[inline]
42 fn eq(&self, o: &$ty_lhs) -> bool {
43 <$ty_common as PartialEq<$ty_common>>::eq(self.as_ref(), o.as_ref())
44 }
45 }
46 impl<S: crate::spec::Spec> PartialOrd<$ty_rhs> for $ty_lhs {
47 #[inline]
48 fn partial_cmp(&self, o: &$ty_rhs) -> Option<core::cmp::Ordering> {
49 <$ty_common as PartialOrd<$ty_common>>::partial_cmp(self.as_ref(), o.as_ref())
50 }
51 }
52 impl<S: crate::spec::Spec> PartialOrd<$ty_lhs> for $ty_rhs {
53 #[inline]
54 fn partial_cmp(&self, o: &$ty_lhs) -> Option<core::cmp::Ordering> {
55 <$ty_common as PartialOrd<$ty_common>>::partial_cmp(self.as_ref(), o.as_ref())
56 }
57 }
58 };
59}
60
61/// Implements `PartialEq` and `PartialOrd` with two independent spec type parameter.
62macro_rules! impl_cmp2 {
63 ($ty_common:ty, $ty_lhs:ty, $ty_rhs:ty) => {
64 impl<S: crate::spec::Spec, T: crate::spec::Spec> PartialEq<$ty_rhs> for $ty_lhs {
65 #[inline]
66 fn eq(&self, o: &$ty_rhs) -> bool {
67 <$ty_common as PartialEq<$ty_common>>::eq(self.as_ref(), o.as_ref())
68 }
69 }
70 impl<S: crate::spec::Spec, T: crate::spec::Spec> PartialEq<$ty_lhs> for $ty_rhs {
71 #[inline]
72 fn eq(&self, o: &$ty_lhs) -> bool {
73 <$ty_common as PartialEq<$ty_common>>::eq(self.as_ref(), o.as_ref())
74 }
75 }
76 impl<S: crate::spec::Spec, T: crate::spec::Spec> PartialOrd<$ty_rhs> for $ty_lhs {
77 #[inline]
78 fn partial_cmp(&self, o: &$ty_rhs) -> Option<core::cmp::Ordering> {
79 <$ty_common as PartialOrd<$ty_common>>::partial_cmp(self.as_ref(), o.as_ref())
80 }
81 }
82 impl<S: crate::spec::Spec, T: crate::spec::Spec> PartialOrd<$ty_lhs> for $ty_rhs {
83 #[inline]
84 fn partial_cmp(&self, o: &$ty_lhs) -> Option<core::cmp::Ordering> {
85 <$ty_common as PartialOrd<$ty_common>>::partial_cmp(self.as_ref(), o.as_ref())
86 }
87 }
88 };
89}
90
91/// Implements `PartialEq` and `PartialOrd` with two independent spec type parameter.
92macro_rules! impl_cmp2_as_str {
93 ($ty_lhs:ty, $ty_rhs:ty) => {
94 impl<S: crate::spec::Spec, T: crate::spec::Spec> PartialEq<$ty_rhs> for $ty_lhs {
95 #[inline]
96 fn eq(&self, o: &$ty_rhs) -> bool {
97 PartialEq::eq(self.as_str(), o.as_str())
98 }
99 }
100 impl<S: crate::spec::Spec, T: crate::spec::Spec> PartialEq<$ty_lhs> for $ty_rhs {
101 #[inline]
102 fn eq(&self, o: &$ty_lhs) -> bool {
103 PartialEq::eq(self.as_str(), o.as_str())
104 }
105 }
106 impl<S: crate::spec::Spec, T: crate::spec::Spec> PartialOrd<$ty_rhs> for $ty_lhs {
107 #[inline]
108 fn partial_cmp(&self, o: &$ty_rhs) -> Option<core::cmp::Ordering> {
109 PartialOrd::partial_cmp(self.as_str(), o.as_str())
110 }
111 }
112 impl<S: crate::spec::Spec, T: crate::spec::Spec> PartialOrd<$ty_lhs> for $ty_rhs {
113 #[inline]
114 fn partial_cmp(&self, o: &$ty_lhs) -> Option<core::cmp::Ordering> {
115 PartialOrd::partial_cmp(self.as_str(), o.as_str())
116 }
117 }
118 };
119}
120
121/// Define the custom string slice type, and implements methods and traits.
122///
123/// Methods to be implemented:
124///
125/// * `pub fn new()`
126/// * `pub fn new_unchecked()`
127/// * `pub(crate) fn new_maybe_unchecked()`
128/// * `fn new_always_unchecked()`
129/// * `pub fn as_str()`
130/// * `pub fn len()`
131/// * `pub fn is_empty()`
132///
133/// Traits to be implemented:
134///
135/// * fundamental
136/// + `Debug for $ty`
137/// + `Eq for $ty`
138/// + `Ord for $ty`
139/// + `Hash for $ty`
140/// * type conversion
141/// + `AsRef<&str> for $ty`
142/// + `AsRef<&$ty> for $ty`
143/// + `From<&$ty>` for Cow<$ty>`
144/// + `From<&$ty>` for Arc<$ty>`
145/// + `From<&$ty>` for Box<$ty>`
146/// + `From<&$ty>` for Rc<$ty>`
147/// + `From<&$ty> for &str`
148/// + `TryFrom<&str> for &$ty`
149/// + `TryFrom<&[u8]> for &$ty`
150/// * comparison (only `PartialEq` impls are listed, but `PartialOrd` is also implemented).
151/// + `PartialEq<$ty> for $ty`
152/// + `str` and `$ty`
153/// - `PartialEq<str> for $ty`
154/// - `PartialEq<$ty> for str`
155/// - `PartialEq<&str> for $ty`
156/// - `PartialEq<$ty> for &str`
157/// - `PartialEq<str> for &$ty`
158/// - `PartialEq<&$ty> for str`
159/// + `$ty` and `$ty`
160/// - `PartialEq<&$ty> for $ty`
161/// - `PartialEq<$ty> for &$ty`
162/// * other
163/// + `Display for $ty`
164/// * serde
165/// + `serde::Serialize`
166/// + `serde::Deserialize`
167macro_rules! define_custom_string_slice {
168 (
169 $(#[$meta:meta])*
170 struct $ty:ident {
171 validator = $validate:ident,
172 expecting_msg = $expecting:expr,
173 }
174 ) => {
175 $(#[$meta])*
176 // `#[derive(..)]` cannot be used here, because it adds `S: DerivedTrait` bounds automatically.
177 #[repr(transparent)]
178 #[cfg_attr(feature = "serde", derive(serde::Serialize))]
179 #[cfg_attr(feature = "serde", serde(bound = "S: crate::spec::Spec"))]
180 #[cfg_attr(feature = "serde", serde(transparent))]
181 pub struct $ty<S> {
182 /// Spec.
183 #[cfg_attr(feature = "serde", serde(skip))]
184 _spec: core::marker::PhantomData<fn() -> S>,
185 /// Inner data.
186 inner: str,
187 }
188
189 impl<S: crate::spec::Spec> $ty<S> {
190 /// Creates a new string.
191 #[inline]
192 pub fn new(s: &str) -> Result<&Self, crate::validate::Error> {
193 core::convert::TryFrom::try_from(s)
194 }
195
196 /// Creates a new string without validation.
197 ///
198 /// This does not validate the given string, so it is caller's
199 /// responsibility to ensure the given string is valid.
200 ///
201 /// # Safety
202 ///
203 /// The given string must be syntactically valid as `Self` type.
204 /// If not, any use of the returned value or the call of this
205 /// function itself may result in undefined behavior.
206 #[inline]
207 #[must_use]
208 pub unsafe fn new_unchecked(s: &str) -> &Self {
209 // SAFETY: `new_always_unchecked` requires the same precondition
210 // as `new_always_unchecked`.
211 unsafe { Self::new_always_unchecked(s) }
212 }
213
214 /// Creates a new string maybe without validation.
215 ///
216 /// This does validation on debug build.
217 ///
218 /// # Safety
219 ///
220 /// The given string must be syntactically valid as `Self` type.
221 #[must_use]
222 pub(crate) unsafe fn new_maybe_unchecked(s: &str) -> &Self {
223 debug_assert_eq!($validate::<S>(s), Ok(()));
224 // SAFETY: `new_always_unchecked` requires the same precondition
225 // as `new_always_unchecked`. Additionally in debug build, just
226 // checked the content is actually valid by `$validate::<S>(s)`.
227 unsafe { Self::new_always_unchecked(s) }
228 }
229
230 /// Creates a new string without any validation.
231 ///
232 /// This does not validate the given string at any time.
233 ///
234 /// Intended for internal use.
235 ///
236 /// # Safety
237 ///
238 /// The given string must be syntactically valid as `Self` type.
239 #[inline]
240 #[must_use]
241 unsafe fn new_always_unchecked(s: &str) -> &Self {
242 // SAFETY: the cast is safe since `Self` type has `repr(transparent)`
243 // attribute and the content is guaranteed as valid by the
244 // precondition of the function.
245 unsafe { &*(s as *const str as *const Self) }
246 }
247
248 /// Returns `&str`.
249 #[inline]
250 #[must_use]
251 pub fn as_str(&self) -> &str {
252 self.as_ref()
253 }
254
255 /// Returns the string length.
256 #[inline]
257 #[must_use]
258 pub fn len(&self) -> usize {
259 self.as_str().len()
260 }
261
262 /// Returns whether the string is empty.
263 #[inline]
264 #[must_use]
265 pub fn is_empty(&self) -> bool {
266 self.as_str().is_empty()
267 }
268 }
269
270 impl<S: crate::spec::Spec> core::fmt::Debug for $ty<S> {
271 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
272 f.debug_tuple(stringify!($ty)).field(&&self.inner).finish()
273 }
274 }
275
276 impl<S: crate::spec::Spec> PartialEq for $ty<S> {
277 #[inline]
278 fn eq(&self, other: &Self) -> bool {
279 self.inner == other.inner
280 }
281 }
282
283 impl<S: crate::spec::Spec> Eq for $ty<S> {}
284
285 impl<S: crate::spec::Spec> PartialOrd for $ty<S> {
286 #[inline]
287 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
288 Some(self.inner.cmp(&other.inner))
289 }
290 }
291
292 impl<S: crate::spec::Spec> Ord for $ty<S> {
293 #[inline]
294 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
295 self.inner.cmp(&other.inner)
296 }
297 }
298
299 impl<S: crate::spec::Spec> core::hash::Hash for $ty<S> {
300 #[inline]
301 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
302 self.inner.hash(state);
303 }
304 }
305
306 impl<S: crate::spec::Spec> AsRef<str> for $ty<S> {
307 #[inline]
308 fn as_ref(&self) -> &str {
309 &self.inner
310 }
311 }
312
313 impl<S: crate::spec::Spec> AsRef<$ty<S>> for $ty<S> {
314 #[inline]
315 fn as_ref(&self) -> &$ty<S> {
316 self
317 }
318 }
319
320 #[cfg(feature = "alloc")]
321 impl<'a, S: crate::spec::Spec> From<&'a $ty<S>> for alloc::borrow::Cow<'a, $ty<S>> {
322 #[inline]
323 fn from(s: &'a $ty<S>) -> Self {
324 alloc::borrow::Cow::Borrowed(s)
325 }
326 }
327
328 impl_from_slice_into_smartptr! {
329 ty: $ty,
330 smartptr: alloc::sync::Arc,
331 mutability: const,
332 }
333
334 impl_from_slice_into_smartptr! {
335 ty: $ty,
336 smartptr: alloc::boxed::Box,
337 mutability: mut,
338 }
339
340 impl_from_slice_into_smartptr! {
341 ty: $ty,
342 smartptr: alloc::rc::Rc,
343 mutability: const,
344 }
345
346 impl<'a, S: crate::spec::Spec> From<&'a $ty<S>> for &'a str {
347 #[inline]
348 fn from(s: &'a $ty<S>) -> &'a str {
349 s.as_ref()
350 }
351 }
352
353 impl<'a, S: crate::spec::Spec> core::convert::TryFrom<&'a str> for &'a $ty<S> {
354 type Error = crate::validate::Error;
355
356 #[inline]
357 fn try_from(s: &'a str) -> Result<Self, Self::Error> {
358 match $validate::<S>(s) {
359 // SAFETY: just checked `s` is valid as `$ty`.
360 Ok(()) => Ok(unsafe { $ty::new_always_unchecked(s) }),
361 Err(e) => Err(e),
362 }
363 }
364 }
365
366 impl<'a, S: crate::spec::Spec> core::convert::TryFrom<&'a [u8]> for &'a $ty<S> {
367 type Error = crate::validate::Error;
368
369 #[inline]
370 fn try_from(bytes: &'a [u8]) -> Result<Self, Self::Error> {
371 let s = core::str::from_utf8(bytes).map_err(|_| crate::validate::Error::new())?;
372 match $validate::<S>(s) {
373 // SAFETY: just checked `s` is valid as `$ty`.
374 Ok(()) => Ok(unsafe { $ty::new_always_unchecked(s) }),
375 Err(e) => Err(e),
376 }
377 }
378 }
379
380 impl_cmp!(str, str, $ty<S>);
381 impl_cmp!(str, &str, $ty<S>);
382 impl_cmp!(str, str, &$ty<S>);
383 impl_cmp2!(str, &$ty<S>, $ty<T>);
384
385 impl<S: crate::spec::Spec> core::fmt::Display for $ty<S> {
386 #[inline]
387 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
388 f.write_str(self.as_str())
389 }
390 }
391
392 /// Serde deserializer implementation.
393 #[cfg(feature = "serde")]
394 mod __serde_slice {
395 use super::$ty;
396
397 use core::{convert::TryFrom, fmt, marker::PhantomData};
398
399 use serde::{
400 de::{self, Visitor},
401 Deserialize, Deserializer,
402 };
403
404 /// Custom borrowed string visitor.
405 #[derive(Debug, Clone, Copy)]
406 struct CustomStrVisitor<S>(PhantomData<fn() -> S>);
407
408 impl<'de, S: 'de + crate::spec::Spec> Visitor<'de> for CustomStrVisitor<S> {
409 type Value = &'de $ty<S>;
410
411 #[inline]
412 fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
413 f.write_str($expecting)
414 }
415
416 #[inline]
417 fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E>
418 where
419 E: de::Error,
420 {
421 <&'de $ty<S> as TryFrom<&'de str>>::try_from(v).map_err(E::custom)
422 }
423 }
424
425 // About `'de` and `'a`, see
426 // <https://serde.rs/lifetimes.html#the-deserializede-lifetime>.
427 impl<'de: 'a, 'a, S: 'de + crate::spec::Spec> Deserialize<'de> for &'a $ty<S> {
428 #[inline]
429 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
430 where
431 D: Deserializer<'de>,
432 {
433 deserializer.deserialize_string(CustomStrVisitor::<S>(PhantomData))
434 }
435 }
436 }
437 };
438}
439
440/// Define the custom owned string type, and implements methods and traits.
441///
442/// Methods to be implemented:
443///
444/// * `pub fn new_unchecked()`
445/// * `pub(crate) fn new_maybe_unchecked()`
446/// * `pub(crate) fn new_always_unchecked()`
447/// * `pub fn shrink_to_fit()`
448///
449/// Traits to be implemented:
450///
451/// * fundamental
452/// + `Debug for $ty`
453/// + `Clone for $ty`
454/// + `Eq for $ty`
455/// + `Ord for $ty`
456/// + `Hash for $ty`
457/// * type conversion
458/// + `AsRef<str> for $ty`
459/// + `AsRef<$slice> for $ty`
460/// + `Borrow<str> for $ty`
461/// + `Borrow<$slice> for $ty`
462/// + `ToOwned<Owned = $ty> for $slice`
463/// + `From<&$slice> for $ty`
464/// + `From<$ty> for String`
465/// + `From<$ty> for Cow<'_, $slice>`
466/// + `From<$ty> for Box<$slice>`
467/// + `TryFrom<&str> for $ty`
468/// + `TryFrom<&[u8]> for $ty`
469/// + `TryFrom<String> for $ty`
470/// + `FromStr for $ty`
471/// + `Deref<Target = $slice> for $ty`
472/// * comparison (only `PartialEq` impls are listed, but `PartialOrd` is also implemented.
473/// + `PartialEq<$ty> for $ty`
474/// + `$slice` and `str`
475/// - `PartialEq<$slice> for Cow<'_, str>`
476/// - `PartialEq<Cow<'_, str>> for $slice`
477/// - `PartialEq<&$slice> for Cow<'_, str>`
478/// - `PartialEq<Cow<'_, str>> for &$slice`
479/// + `$slice` and `Cow<$slice>`
480/// - `PartialEq<$slice> for Cow<'_, $slice>`
481/// - `PartialEq<Cow<'_, $slice>> for $slice`
482/// - `PartialEq<&$slice> for Cow<'_, $slice>`
483/// - `PartialEq<Cow<'_, $slice>> for &$slice`
484/// + `str` and `$ty`
485/// - `PartialEq<str> for $ty`
486/// - `PartialEq<$ty> for str`
487/// - `PartialEq<&str> for $ty`
488/// - `PartialEq<$ty> for &str`
489/// - `PartialEq<Cow<'_, str>> for $ty`
490/// - `PartialEq<$ty> for Cow<'_, str>`
491/// + `String` and `$ty`
492/// - `PartialEq<String> for $ty`
493/// - `PartialEq<$ty> for String`
494/// + `$slice` and `$ty`
495/// - `PartialEq<$slice> for $ty`
496/// - `PartialEq<$ty> for $slice`
497/// - `PartialEq<&$slice> for $ty`
498/// - `PartialEq<$ty> for &$slice`
499/// - `PartialEq<Cow<'_, $slice>> for $ty`
500/// - `PartialEq<$ty> for Cow<'_, $slice>`
501/// * other
502/// + `Display for $ty`
503/// * serde
504/// + `serde::Serialize`
505/// + `serde::Deserialize`
506// Note that `From<$ty> for {Arc,Rc}<$slice>` is currently not implemented since
507// this won't reuse allocated memory and hides internal memory reallocation. See
508// <https://github.com/lo48576/iri-string/issues/20#issuecomment-1105207849>.
509// However, this is not decided with firm belief or opinion, so there would be
510// a chance that they are implemented in future.
511#[cfg(feature = "alloc")]
512macro_rules! define_custom_string_owned {
513 (
514 $(#[$meta:meta])*
515 struct $ty:ident {
516 validator = $validate:ident,
517 slice = $slice:ident,
518 expecting_msg = $expecting:expr,
519 }
520 ) => {
521 $(#[$meta])*
522 // `#[derive(..)]` cannot be used here, because it adds `S: DerivedTrait` bounds automatically.
523 #[cfg(feature = "alloc")]
524 #[cfg_attr(all(feature = "serde", feature = "alloc"), derive(serde::Serialize))]
525 #[cfg_attr(all(feature = "serde", feature = "alloc"), serde(bound = "S: crate::spec::Spec"))]
526 #[cfg_attr(all(feature = "serde", feature = "alloc"), serde(transparent))]
527 pub struct $ty<S> {
528 /// Spec.
529 #[cfg_attr(all(feature = "serde", feature = "alloc"), serde(skip))]
530 _spec: core::marker::PhantomData<fn() -> S>,
531 /// Inner data.
532 inner: alloc::string::String,
533 }
534
535 impl<S: crate::spec::Spec> $ty<S> {
536 /// Creates a new string without validation.
537 ///
538 /// This does not validate the given string, so it is caller's
539 /// responsibility to ensure the given string is valid.
540 ///
541 /// # Safety
542 ///
543 /// The given string must be syntactically valid as `Self` type.
544 /// If not, any use of the returned value or the call of this
545 /// function itself may result in undefined behavior.
546 #[inline]
547 #[must_use]
548 pub unsafe fn new_unchecked(s: alloc::string::String) -> Self {
549 // SAFETY: `new_always_unchecked` requires the same precondition
550 // as `new_always_unchecked`.
551 unsafe { Self::new_always_unchecked(s) }
552 }
553
554 /// Creates a new string maybe without validation.
555 ///
556 /// This does not validate the given string at any time.
557 ///
558 /// Intended for internal use.
559 ///
560 /// # Safety
561 ///
562 /// The given string must be syntactically valid as `Self` type.
563 #[inline]
564 #[must_use]
565 pub(crate) unsafe fn new_always_unchecked(s: alloc::string::String) -> Self {
566 // The construction itself can be written in safe Rust, but
567 // every other place including unsafe functions expects
568 // `self.inner` to be syntactically valid as `Self`. In order to
569 // make them safe, the construction should validate the value
570 // or at least should require users to validate the value by
571 // making the function `unsafe`.
572 Self {
573 _spec: core::marker::PhantomData,
574 inner: s,
575 }
576 }
577
578 /// Creates a new string maybe without validation.
579 ///
580 /// This does validation on debug build.
581 ///
582 /// # Safety
583 ///
584 /// The given string must be syntactically valid as `Self` type.
585 #[must_use]
586 pub(crate) unsafe fn new_maybe_unchecked(s: alloc::string::String) -> Self {
587 debug_assert_eq!(
588 $validate::<S>(&s),
589 Ok(()),
590 "[precondition] the given string must be valid"
591 );
592 // SAFETY: `new_always_unchecked` requires the same precondition
593 // as `new_always_unchecked`. Additionally in debug build, just
594 // checked the content is actually valid by `$validate::<S>(s)`.
595 unsafe { Self::new_always_unchecked(s) }
596 }
597
598 /// Returns a mutable reference to the inner string buffer.
599 ///
600 /// This may be useful to implement inline modification algorithm,
601 /// but be careful as this method itself cannot validate the new
602 /// content.
603 ///
604 /// # Safety
605 ///
606 /// The content after modification must be syntactically valid as
607 /// `Self` type.
608 /// If not, any use of the returned value or the call of this
609 /// function itself may result in undefined behavior.
610 #[inline]
611 #[must_use]
612 // TODO: Use wrapper type to enforce validation on finish?
613 pub(crate) unsafe fn as_inner_mut(&mut self) -> &mut alloc::string::String {
614 &mut self.inner
615 }
616
617 /// Shrinks the capacity of the inner buffer to match its length.
618 #[inline]
619 pub fn shrink_to_fit(&mut self) {
620 self.inner.shrink_to_fit()
621 }
622
623 /// Returns the internal buffer capacity in bytes.
624 #[inline]
625 #[must_use]
626 pub fn capacity(&self) -> usize {
627 self.inner.capacity()
628 }
629
630 /// Returns the borrowed IRI string slice.
631 ///
632 /// This is equivalent to `&*self`.
633 #[inline]
634 #[must_use]
635 pub fn as_slice(&self) -> &$slice<S> {
636 self.as_ref()
637 }
638 }
639
640 impl<S: crate::spec::Spec> core::fmt::Debug for $ty<S> {
641 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
642 f.debug_tuple(stringify!($ty)).field(&&self.inner).finish()
643 }
644 }
645
646 impl<S: crate::spec::Spec> Clone for $ty<S> {
647 #[inline]
648 fn clone(&self) -> Self {
649 // This is safe because `self` must be valid.
650 Self {
651 _spec: core::marker::PhantomData,
652 inner: self.inner.clone(),
653 }
654 }
655 }
656
657 impl<S: crate::spec::Spec, T: crate::spec::Spec> PartialEq<$ty<T>> for $ty<S> {
658 #[inline]
659 fn eq(&self, other: &$ty<T>) -> bool {
660 self.inner == other.inner
661 }
662 }
663
664 impl<S: crate::spec::Spec> Eq for $ty<S> {}
665
666 impl<S: crate::spec::Spec, T: crate::spec::Spec> PartialOrd<$ty<T>> for $ty<S> {
667 #[inline]
668 fn partial_cmp(&self, other: &$ty<T>) -> Option<core::cmp::Ordering> {
669 self.inner.partial_cmp(&other.inner)
670 }
671 }
672
673 impl<S: crate::spec::Spec> Ord for $ty<S> {
674 #[inline]
675 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
676 self.inner.cmp(&other.inner)
677 }
678 }
679
680 impl<S: crate::spec::Spec> core::hash::Hash for $ty<S> {
681 #[inline]
682 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
683 self.inner.hash(state);
684 }
685 }
686
687 impl<S: crate::spec::Spec> AsRef<str> for $ty<S> {
688 #[inline]
689 fn as_ref(&self) -> &str {
690 &self.inner
691 }
692 }
693
694 impl<S: crate::spec::Spec> AsRef<$slice<S>> for $ty<S> {
695 #[inline]
696 fn as_ref(&self) -> &$slice<S> {
697 // SAFETY: `$ty<S>` and `$slice<S>` requires same validation, so
698 // the content of `self: &$ty<S>` must be valid as `$slice<S>`.
699 unsafe { $slice::new_always_unchecked(AsRef::<str>::as_ref(self)) }
700 }
701 }
702
703 impl<S: crate::spec::Spec> core::borrow::Borrow<str> for $ty<S> {
704 #[inline]
705 fn borrow(&self) -> &str {
706 self.as_ref()
707 }
708 }
709
710 impl<S: crate::spec::Spec> core::borrow::Borrow<$slice<S>> for $ty<S> {
711 #[inline]
712 fn borrow(&self) -> &$slice<S> {
713 self.as_ref()
714 }
715 }
716
717 impl<S: crate::spec::Spec> alloc::borrow::ToOwned for $slice<S> {
718 type Owned = $ty<S>;
719
720 #[inline]
721 fn to_owned(&self) -> Self::Owned {
722 self.into()
723 }
724 }
725
726 impl<S: crate::spec::Spec> From<&'_ $slice<S>> for $ty<S> {
727 #[inline]
728 fn from(s: &$slice<S>) -> Self {
729 // This is safe because `s` must be valid.
730 $ty {
731 _spec: core::marker::PhantomData,
732 inner: alloc::string::String::from(s.as_str()),
733 }
734 }
735 }
736
737 impl<S: crate::spec::Spec> From<$ty<S>> for alloc::string::String {
738 #[inline]
739 fn from(s: $ty<S>) -> Self {
740 s.inner
741 }
742 }
743
744 impl<'a, S: crate::spec::Spec> From<$ty<S>> for alloc::borrow::Cow<'a, $slice<S>> {
745 #[inline]
746 fn from(s: $ty<S>) -> alloc::borrow::Cow<'a, $slice<S>> {
747 alloc::borrow::Cow::Owned(s)
748 }
749 }
750
751 impl<S: crate::spec::Spec> From<$ty<S>> for alloc::boxed::Box<$slice<S>> {
752 #[inline]
753 fn from(s: $ty<S>) -> alloc::boxed::Box<$slice<S>> {
754 let inner: alloc::string::String = s.into();
755 let buf = alloc::boxed::Box::<str>::from(inner);
756 // SAFETY: `$slice<S>` has `repr(transparent)` attribute, so
757 // the memory layouts of `Box<str>` and `Box<$slice<S>>` are
758 // compatible. Additionally, `$ty<S>` and `$slice<S>` require
759 // the same syntax (it is the macro user's responsibility to
760 // guarantee).
761 unsafe {
762 let raw: *mut str = alloc::boxed::Box::into_raw(buf);
763 alloc::boxed::Box::<$slice<S>>::from_raw(raw as *mut $slice<S>)
764 }
765 }
766 }
767
768 impl<S: crate::spec::Spec> core::convert::TryFrom<&'_ str> for $ty<S> {
769 type Error = crate::validate::Error;
770
771 #[inline]
772 fn try_from(s: &str) -> Result<Self, Self::Error> {
773 <&$slice<S>>::try_from(s).map(Into::into)
774 }
775 }
776
777 impl<S: crate::spec::Spec> core::convert::TryFrom<&'_ [u8]> for $ty<S> {
778 type Error = crate::validate::Error;
779
780 #[inline]
781 fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
782 let s = core::str::from_utf8(bytes).map_err(|_| crate::validate::Error::new())?;
783 <&$slice<S>>::try_from(s).map(Into::into)
784 }
785 }
786
787 impl<S: crate::spec::Spec> core::convert::TryFrom<alloc::string::String> for $ty<S> {
788 type Error = crate::types::CreationError<alloc::string::String>;
789
790 #[inline]
791 fn try_from(s: alloc::string::String) -> Result<Self, Self::Error> {
792 match <&$slice<S>>::try_from(s.as_str()) {
793 Ok(_) => {
794 // This is safe because `<&$slice<S>>::try_from(s)?` ensures
795 // that the string `s` is valid.
796 Ok(Self {
797 _spec: core::marker::PhantomData,
798 inner: s,
799 })
800 }
801 Err(e) => Err(crate::types::CreationError::new(e, s)),
802 }
803 }
804 }
805
806 impl<S: crate::spec::Spec> alloc::str::FromStr for $ty<S> {
807 type Err = crate::validate::Error;
808
809 #[inline]
810 fn from_str(s: &str) -> Result<Self, Self::Err> {
811 core::convert::TryFrom::try_from(s)
812 }
813 }
814
815 impl<S: crate::spec::Spec> core::ops::Deref for $ty<S> {
816 type Target = $slice<S>;
817
818 #[inline]
819 fn deref(&self) -> &$slice<S> {
820 self.as_ref()
821 }
822 }
823
824 impl_cmp!(str, $slice<S>, alloc::borrow::Cow<'_, str>);
825 impl_cmp!(str, &$slice<S>, alloc::borrow::Cow<'_, str>);
826 impl_cmp2_as_str!(&$slice<S>, alloc::borrow::Cow<'_, $slice<T>>);
827
828 impl_cmp!(str, str, $ty<S>);
829 impl_cmp!(str, &str, $ty<S>);
830 impl_cmp!(str, alloc::borrow::Cow<'_, str>, $ty<S>);
831 impl_cmp!(str, alloc::string::String, $ty<S>);
832 impl_cmp2!(str, $slice<S>, $ty<T>);
833 impl_cmp2!(str, &$slice<S>, $ty<T>);
834 impl_cmp2_as_str!(alloc::borrow::Cow<'_, $slice<S>>, $ty<T>);
835
836 impl<S: crate::spec::Spec> core::fmt::Display for $ty<S> {
837 #[inline]
838 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
839 f.write_str(self.as_str())
840 }
841 }
842
843 /// Serde deserializer implementation.
844 #[cfg(all(feature = "alloc", feature = "serde"))]
845 mod __serde_owned {
846 use super::$ty;
847
848 use core::{convert::TryFrom, fmt, marker::PhantomData};
849
850 #[cfg(all(feature = "serde", feature = "alloc"))]
851 use alloc::string::String;
852
853 use serde::{
854 de::{self, Visitor},
855 Deserialize, Deserializer,
856 };
857
858 /// Custom owned string visitor.
859 #[derive(Debug, Clone, Copy)]
860 struct CustomStringVisitor<S>(PhantomData<fn() -> S>);
861
862 impl<'de, S: crate::spec::Spec> Visitor<'de> for CustomStringVisitor<S> {
863 type Value = $ty<S>;
864
865 #[inline]
866 fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
867 f.write_str($expecting)
868 }
869
870 #[inline]
871 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
872 where
873 E: de::Error,
874 {
875 <$ty<S> as TryFrom<&str>>::try_from(v).map_err(E::custom)
876 }
877
878 #[cfg(all(feature = "serde", feature = "alloc"))]
879 #[inline]
880 fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
881 where
882 E: de::Error,
883 {
884 <$ty<S> as TryFrom<String>>::try_from(v).map_err(E::custom)
885 }
886 }
887
888 impl<'de, S: crate::spec::Spec> Deserialize<'de> for $ty<S> {
889 #[inline]
890 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
891 where
892 D: Deserializer<'de>,
893 {
894 deserializer.deserialize_str(CustomStringVisitor::<S>(PhantomData))
895 }
896 }
897 }
898 };
899}
900
901/// Implements trivial conversions and other useful traits between two IRI types.
902///
903/// Implemented traits:
904///
905/// * type conversion
906/// + `AsRef<$to_slice> for $from_slice`
907/// + `AsRef<$to_slice> for $from_owned`
908/// + `From<$from_slice> for $to_slice`
909/// + `From<$from_owned> for $to_owned`
910/// + `TryFrom<&$to_slice> for &$from_slice`
911/// + `TryFrom<$to_owned> for $from_owned`
912/// * comparison (only `PartialEq` impls are listed, but `PartialOrd` is also implemented).
913/// + `$from_slice` and `$to_slice`
914/// - `PartialEq<$from_slice> for $to_slice`
915/// - `PartialEq<$to_slice> for $from_slice`
916/// - `PartialEq<&$from_slice> for $to_slice`
917/// - `PartialEq<$to_slice> for &$from_slice`
918/// - `PartialEq<$from_slice> for &$to_slice`
919/// - `PartialEq<&$to_slice> for $from_slice`
920/// - `PartialEq<$from_slice> for Cow<'_, $to_slice>`
921/// - `PartialEq<Cow<'_, $to_slice>> for $from_slice`
922/// - `PartialEq<&$from_slice> for Cow<'_, $to_slice>`
923/// - `PartialEq<Cow<'_, $to_slice>> for &$from_slice`
924/// - `PartialEq<Cow<'_, $from_slice>> for $to_slice`
925/// - `PartialEq<$to_slice> for Cow<'_, $from_slice>`
926/// - `PartialEq<Cow<'_, $from_slice>> for &$to_slice`
927/// - `PartialEq<&$to_slice> for Cow<'_, $from_slice>`
928/// + `$from_slice` and `$to_owned`
929/// - `PartialEq<$from_slice> for $to_owned`
930/// - `PartialEq<$to_owned> for $from_slice`
931/// - `PartialEq<&$from_slice> for $to_owned`
932/// - `PartialEq<$to_owned> for &$from_slice`
933/// - `PartialEq<Cow<'_, $from_slice>> for $to_owned`
934/// - `PartialEq<$to_owned> for Cow<'_, $from_slice>`
935/// + `$from_owned` and `$to_slice`
936/// - `PartialEq<$from_owned> for $to_slice`
937/// - `PartialEq<$to_slice> for $from_owned`
938/// - `PartialEq<$from_owned> for &$to_slice`
939/// - `PartialEq<&$to_slice> for $from_owned`
940/// - `PartialEq<$from_owned> for Cow<'_, $to_slice>`
941/// - `PartialEq<Cow<'_, $to_slice>> for $from_owned`
942/// + `$from_owned` and `$to_owned`
943/// - `PartialEq<$from_owned> for $to_owned`
944/// - `PartialEq<$to_owned> for $from_owned`
945macro_rules! impl_trivial_conv_between_iri {
946 (
947 from_slice: $from_slice:ident,
948 from_owned: $from_owned:ident,
949 to_slice: $to_slice:ident,
950 to_owned: $to_owned:ident,
951 ) => {
952 impl<S: crate::spec::Spec> AsRef<$to_slice<S>> for $from_slice<S> {
953 #[inline]
954 fn as_ref(&self) -> &$to_slice<S> {
955 // SAFETY: `$from_slice<S>` should be subset of `$to_slice<S>`.
956 // The caller of `impl_trivial_conv_between_iri!` macro is
957 // responsible for guaranteeing that.
958 unsafe { <$to_slice<S>>::new_maybe_unchecked(self.as_str()) }
959 }
960 }
961
962 #[cfg(feature = "alloc")]
963 impl<S: crate::spec::Spec> AsRef<$to_slice<S>> for $from_owned<S> {
964 #[inline]
965 fn as_ref(&self) -> &$to_slice<S> {
966 AsRef::<$from_slice<S>>::as_ref(self).as_ref()
967 }
968 }
969
970 impl<'a, S: crate::spec::Spec> From<&'a $from_slice<S>> for &'a $to_slice<S> {
971 #[inline]
972 fn from(s: &'a $from_slice<S>) -> &'a $to_slice<S> {
973 s.as_ref()
974 }
975 }
976
977 #[cfg(feature = "alloc")]
978 impl<S: crate::spec::Spec> From<$from_owned<S>> for $to_owned<S> {
979 #[inline]
980 fn from(s: $from_owned<S>) -> $to_owned<S> {
981 // SAFETY: `$from_slice<S>` should be subset of `$to_slice<S>`.
982 // The caller of `impl_trivial_conv_between_iri!` macro is
983 // responsible for guaranteeing that.
984 unsafe { <$to_owned<S>>::new_maybe_unchecked(s.into()) }
985 }
986 }
987
988 impl<'a, S: crate::spec::Spec> core::convert::TryFrom<&'a $to_slice<S>>
989 for &'a $from_slice<S>
990 {
991 type Error = crate::validate::Error;
992
993 #[inline]
994 fn try_from(s: &'a $to_slice<S>) -> Result<Self, Self::Error> {
995 Self::try_from(s.as_str())
996 }
997 }
998
999 #[cfg(feature = "alloc")]
1000 impl<S: crate::spec::Spec> core::convert::TryFrom<$to_owned<S>> for $from_owned<S> {
1001 type Error = crate::types::CreationError<$to_owned<S>>;
1002
1003 fn try_from(s: $to_owned<S>) -> Result<Self, Self::Error> {
1004 match <&$from_slice<S>>::try_from(s.as_str()) {
1005 // SAFETY: just checked `s.as_str()` is valid as `$from_slice<S>`, and it
1006 // requires the same syntax as `$from_owned<S>`.
1007 Ok(_) => Ok(unsafe { <$from_owned<S>>::new_always_unchecked(s.into()) }),
1008 Err(e) => Err(crate::types::CreationError::new(e, s)),
1009 }
1010 }
1011 }
1012
1013 impl_cmp2_as_str!($from_slice<S>, $to_slice<T>);
1014 impl_cmp2_as_str!(&$from_slice<S>, $to_slice<T>);
1015 impl_cmp2_as_str!($from_slice<S>, &$to_slice<T>);
1016 #[cfg(feature = "alloc")]
1017 impl_cmp2_as_str!($from_slice<S>, alloc::borrow::Cow<'_, $to_slice<T>>);
1018 #[cfg(feature = "alloc")]
1019 impl_cmp2_as_str!(&$from_slice<S>, alloc::borrow::Cow<'_, $to_slice<T>>);
1020 #[cfg(feature = "alloc")]
1021 impl_cmp2_as_str!(alloc::borrow::Cow<'_, $from_slice<S>>, $to_slice<T>);
1022 #[cfg(feature = "alloc")]
1023 impl_cmp2_as_str!(alloc::borrow::Cow<'_, $from_slice<S>>, &$to_slice<T>);
1024
1025 #[cfg(feature = "alloc")]
1026 impl_cmp2_as_str!($from_slice<S>, $to_owned<T>);
1027 #[cfg(feature = "alloc")]
1028 impl_cmp2_as_str!(&$from_slice<S>, $to_owned<T>);
1029 #[cfg(feature = "alloc")]
1030 impl_cmp2_as_str!(alloc::borrow::Cow<'_, $from_slice<S>>, $to_owned<T>);
1031
1032 #[cfg(feature = "alloc")]
1033 impl_cmp2_as_str!($from_owned<S>, $to_slice<T>);
1034 #[cfg(feature = "alloc")]
1035 impl_cmp2_as_str!($from_owned<S>, &$to_slice<T>);
1036 #[cfg(feature = "alloc")]
1037 impl_cmp2_as_str!($from_owned<S>, alloc::borrow::Cow<'_, $to_slice<T>>);
1038 #[cfg(feature = "alloc")]
1039 impl_cmp2_as_str!($from_owned<S>, $to_owned<T>);
1040 };
1041}