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}