Skip to main content

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