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.cmp(&other))
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(|_| {
372                    crate::validate::Error::with_kind(crate::validate::ErrorKind::InvalidUtf8)
373                })?;
374                match $validate::<S>(s) {
375                    // SAFETY: just checked `s` is valid as `$ty`.
376                    Ok(()) => Ok(unsafe { $ty::new_always_unchecked(s) }),
377                    Err(e) => Err(e),
378                }
379            }
380        }
381
382        impl_cmp!(str, str, $ty<S>);
383        impl_cmp!(str, &str, $ty<S>);
384        impl_cmp!(str, str, &$ty<S>);
385        impl_cmp2!(str, &$ty<S>, $ty<T>);
386
387        impl<S: crate::spec::Spec> core::fmt::Display for $ty<S> {
388            #[inline]
389            fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
390                f.write_str(self.as_str())
391            }
392        }
393
394        /// Serde deserializer implementation.
395        #[cfg(feature = "serde")]
396        mod __serde_slice {
397            use super::$ty;
398
399            use core::{convert::TryFrom, fmt, marker::PhantomData};
400
401            use serde::{
402                de::{self, Visitor},
403                Deserialize, Deserializer,
404            };
405
406            /// Custom borrowed string visitor.
407            #[derive(Debug, Clone, Copy)]
408            struct CustomStrVisitor<S>(PhantomData<fn() -> S>);
409
410            impl<'de, S: 'de + crate::spec::Spec> Visitor<'de> for CustomStrVisitor<S> {
411                type Value = &'de $ty<S>;
412
413                #[inline]
414                fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
415                    f.write_str($expecting)
416                }
417
418                #[inline]
419                fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E>
420                where
421                    E: de::Error,
422                {
423                    <&'de $ty<S> as TryFrom<&'de str>>::try_from(v).map_err(E::custom)
424                }
425            }
426
427            // About `'de` and `'a`, see
428            // <https://serde.rs/lifetimes.html#the-deserializede-lifetime>.
429            impl<'de: 'a, 'a, S: 'de + crate::spec::Spec> Deserialize<'de> for &'a $ty<S> {
430                #[inline]
431                fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
432                where
433                    D: Deserializer<'de>,
434                {
435                    deserializer.deserialize_string(CustomStrVisitor::<S>(PhantomData))
436                }
437            }
438        }
439    };
440}
441
442/// Define the custom owned string type, and implements methods and traits.
443///
444/// Methods to be implemented:
445///
446/// * `pub fn new_unchecked()`
447/// * `pub(crate) fn new_maybe_unchecked()`
448/// * `pub(crate) fn new_always_unchecked()`
449/// * `pub fn shrink_to_fit()`
450///
451/// Traits to be implemented:
452///
453/// * fundamental
454///     + `Debug for $ty`
455///     + `Clone for $ty`
456///     + `Eq for $ty`
457///     + `Ord for $ty`
458///     + `Hash for $ty`
459/// * type conversion
460///     + `AsRef<str> for $ty`
461///     + `AsRef<$slice> for $ty`
462///     + `Borrow<str> for $ty`
463///     + `Borrow<$slice> for $ty`
464///     + `ToOwned<Owned = $ty> for $slice`
465///     + `From<&$slice> for $ty`
466///     + `From<$ty> for String`
467///     + `From<$ty> for Cow<'_, $slice>`
468///     + `From<$ty> for Box<$slice>`
469///     + `TryFrom<&str> for $ty`
470///     + `TryFrom<&[u8]> for $ty`
471///     + `TryFrom<String> for $ty`
472///     + `FromStr for $ty`
473///     + `Deref<Target = $slice> for $ty`
474/// * comparison (only `PartialEq` impls are listed, but `PartialOrd` is also implemented.
475///     + `PartialEq<$ty> for $ty`
476///     + `$slice` and `str`
477///         - `PartialEq<$slice> for Cow<'_, str>`
478///         - `PartialEq<Cow<'_, str>> for $slice`
479///         - `PartialEq<&$slice> for Cow<'_, str>`
480///         - `PartialEq<Cow<'_, str>> for &$slice`
481///     + `$slice` and `Cow<$slice>`
482///         - `PartialEq<$slice> for Cow<'_, $slice>`
483///         - `PartialEq<Cow<'_, $slice>> for $slice`
484///         - `PartialEq<&$slice> for Cow<'_, $slice>`
485///         - `PartialEq<Cow<'_, $slice>> for &$slice`
486///     + `str` and `$ty`
487///         - `PartialEq<str> for $ty`
488///         - `PartialEq<$ty> for str`
489///         - `PartialEq<&str> for $ty`
490///         - `PartialEq<$ty> for &str`
491///         - `PartialEq<Cow<'_, str>> for $ty`
492///         - `PartialEq<$ty> for Cow<'_, str>`
493///     + `String` and `$ty`
494///         - `PartialEq<String> for $ty`
495///         - `PartialEq<$ty> for String`
496///     + `$slice` and `$ty`
497///         - `PartialEq<$slice> for $ty`
498///         - `PartialEq<$ty> for $slice`
499///         - `PartialEq<&$slice> for $ty`
500///         - `PartialEq<$ty> for &$slice`
501///         - `PartialEq<Cow<'_, $slice>> for $ty`
502///         - `PartialEq<$ty> for Cow<'_, $slice>`
503/// * other
504///     + `Display for $ty`
505/// * serde
506///     + `serde::Serialize`
507///     + `serde::Deserialize`
508// Note that `From<$ty> for {Arc,Rc}<$slice>` is currently not implemented since
509// this won't reuse allocated memory and hides internal memory reallocation. See
510// <https://github.com/lo48576/iri-string/issues/20#issuecomment-1105207849>.
511// However, this is not decided with firm belief or opinion, so there would be
512// a chance that they are implemented in future.
513#[cfg(feature = "alloc")]
514macro_rules! define_custom_string_owned {
515    (
516        $(#[$meta:meta])*
517        struct $ty:ident {
518            validator = $validate:ident,
519            slice = $slice:ident,
520            expecting_msg = $expecting:expr,
521        }
522    ) => {
523        $(#[$meta])*
524        // `#[derive(..)]` cannot be used here, because it adds `S: DerivedTrait` bounds automatically.
525        #[cfg(feature = "alloc")]
526        #[cfg_attr(all(feature = "serde", feature = "alloc"), derive(serde::Serialize))]
527        #[cfg_attr(all(feature = "serde", feature = "alloc"), serde(bound = "S: crate::spec::Spec"))]
528        #[cfg_attr(all(feature = "serde", feature = "alloc"), serde(transparent))]
529        pub struct $ty<S> {
530            /// Spec.
531            #[cfg_attr(all(feature = "serde", feature = "alloc"), serde(skip))]
532            _spec: core::marker::PhantomData<fn() -> S>,
533            /// Inner data.
534            inner: alloc::string::String,
535        }
536
537        impl<S: crate::spec::Spec> $ty<S> {
538            /// Creates a new string without validation.
539            ///
540            /// This does not validate the given string, so it is caller's
541            /// responsibility to ensure the given string is valid.
542            ///
543            /// # Safety
544            ///
545            /// The given string must be syntactically valid as `Self` type.
546            /// If not, any use of the returned value or the call of this
547            /// function itself may result in undefined behavior.
548            #[inline]
549            #[must_use]
550            pub unsafe fn new_unchecked(s: alloc::string::String) -> Self {
551                // SAFETY: `new_always_unchecked` requires the same precondition
552                // as `new_always_unchecked`.
553                unsafe { Self::new_always_unchecked(s) }
554            }
555
556            /// Creates a new string maybe without validation.
557            ///
558            /// This does not validate the given string at any time.
559            ///
560            /// Intended for internal use.
561            ///
562            /// # Safety
563            ///
564            /// The given string must be syntactically valid as `Self` type.
565            #[inline]
566            #[must_use]
567            pub(crate) unsafe fn new_always_unchecked(s: alloc::string::String) -> Self {
568                // The construction itself can be written in safe Rust, but
569                // every other place including unsafe functions expects
570                // `self.inner` to be syntactically valid as `Self`. In order to
571                // make them safe, the construction should validate the value
572                // or at least should require users to validate the value by
573                // making the function `unsafe`.
574                Self {
575                    _spec: core::marker::PhantomData,
576                    inner: s,
577                }
578            }
579
580            /// Creates a new string maybe without validation.
581            ///
582            /// This does validation on debug build.
583            ///
584            /// # Safety
585            ///
586            /// The given string must be syntactically valid as `Self` type.
587            #[must_use]
588            pub(crate) unsafe fn new_maybe_unchecked(s: alloc::string::String) -> Self {
589                debug_assert_eq!(
590                    $validate::<S>(&s),
591                    Ok(()),
592                    "[precondition] the given string must be valid"
593                );
594                // SAFETY: `new_always_unchecked` requires the same precondition
595                // as `new_always_unchecked`. Additionally in debug build, just
596                // checked the content is actually valid by `$validate::<S>(s)`.
597                unsafe { Self::new_always_unchecked(s) }
598            }
599
600            /// Returns a mutable reference to the inner string buffer.
601            ///
602            /// This may be useful to implement inline modification algorithm,
603            /// but be careful as this method itself cannot validate the new
604            /// content.
605            ///
606            /// # Safety
607            ///
608            /// The content after modification must be syntactically valid as
609            /// `Self` type.
610            /// If not, any use of the returned value or the call of this
611            /// function itself may result in undefined behavior.
612            #[inline]
613            #[must_use]
614            // TODO: Use wrapper type to enforce validation on finish?
615            pub(crate) unsafe fn as_inner_mut(&mut self) -> &mut alloc::string::String {
616                &mut self.inner
617            }
618
619            /// Shrinks the capacity of the inner buffer to match its length.
620            #[inline]
621            pub fn shrink_to_fit(&mut self) {
622                self.inner.shrink_to_fit()
623            }
624
625            /// Returns the internal buffer capacity in bytes.
626            #[inline]
627            #[must_use]
628            pub fn capacity(&self) -> usize {
629                self.inner.capacity()
630            }
631
632            /// Returns the borrowed IRI string slice.
633            ///
634            /// This is equivalent to `&*self`.
635            #[inline]
636            #[must_use]
637            pub fn as_slice(&self) -> &$slice<S> {
638                self.as_ref()
639            }
640        }
641
642        impl<S: crate::spec::Spec> core::fmt::Debug for $ty<S> {
643            fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
644                f.debug_tuple(stringify!($ty)).field(&&self.inner).finish()
645            }
646        }
647
648        impl<S: crate::spec::Spec> Clone for $ty<S> {
649            #[inline]
650            fn clone(&self) -> Self {
651                // This is safe because `self` must be valid.
652                Self {
653                    _spec: core::marker::PhantomData,
654                    inner: self.inner.clone(),
655                }
656            }
657        }
658
659        impl<S: crate::spec::Spec, T: crate::spec::Spec> PartialEq<$ty<T>> for $ty<S> {
660            #[inline]
661            fn eq(&self, other: &$ty<T>) -> bool {
662                self.inner == other.inner
663            }
664        }
665
666        impl<S: crate::spec::Spec> Eq for $ty<S> {}
667
668        impl<S: crate::spec::Spec, T: crate::spec::Spec> PartialOrd<$ty<T>> for $ty<S> {
669            #[inline]
670            fn partial_cmp(&self, other: &$ty<T>) -> Option<core::cmp::Ordering> {
671                self.inner.partial_cmp(&other.inner)
672            }
673        }
674
675        impl<S: crate::spec::Spec> Ord for $ty<S> {
676            #[inline]
677            fn cmp(&self, other: &Self) -> core::cmp::Ordering {
678                self.inner.cmp(&other.inner)
679            }
680        }
681
682        impl<S: crate::spec::Spec> core::hash::Hash for $ty<S> {
683            #[inline]
684            fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
685                self.inner.hash(state);
686            }
687        }
688
689        impl<S: crate::spec::Spec> AsRef<str> for $ty<S> {
690            #[inline]
691            fn as_ref(&self) -> &str {
692                &self.inner
693            }
694        }
695
696        impl<S: crate::spec::Spec> AsRef<$slice<S>> for $ty<S> {
697            #[inline]
698            fn as_ref(&self) -> &$slice<S> {
699                // SAFETY: `$ty<S>` and `$slice<S>` requires same validation, so
700                // the content of `self: &$ty<S>` must be valid as `$slice<S>`.
701                unsafe { $slice::new_always_unchecked(AsRef::<str>::as_ref(self)) }
702            }
703        }
704
705        impl<S: crate::spec::Spec> core::borrow::Borrow<str> for $ty<S> {
706            #[inline]
707            fn borrow(&self) -> &str {
708                self.as_ref()
709            }
710        }
711
712        impl<S: crate::spec::Spec> core::borrow::Borrow<$slice<S>> for $ty<S> {
713            #[inline]
714            fn borrow(&self) -> &$slice<S> {
715                self.as_ref()
716            }
717        }
718
719        impl<S: crate::spec::Spec> alloc::borrow::ToOwned for $slice<S> {
720            type Owned = $ty<S>;
721
722            #[inline]
723            fn to_owned(&self) -> Self::Owned {
724                self.into()
725            }
726        }
727
728        impl<S: crate::spec::Spec> From<&'_ $slice<S>> for $ty<S> {
729            #[inline]
730            fn from(s: &$slice<S>) -> Self {
731                // This is safe because `s` must be valid.
732                $ty {
733                    _spec: core::marker::PhantomData,
734                    inner: alloc::string::String::from(s.as_str()),
735                }
736            }
737        }
738
739        impl<S: crate::spec::Spec> From<$ty<S>> for alloc::string::String {
740            #[inline]
741            fn from(s: $ty<S>) -> Self {
742                s.inner
743            }
744        }
745
746        impl<'a, S: crate::spec::Spec> From<$ty<S>> for alloc::borrow::Cow<'a, $slice<S>> {
747            #[inline]
748            fn from(s: $ty<S>) -> alloc::borrow::Cow<'a, $slice<S>> {
749                alloc::borrow::Cow::Owned(s)
750            }
751        }
752
753        impl<S: crate::spec::Spec> From<$ty<S>> for alloc::boxed::Box<$slice<S>> {
754            #[inline]
755            fn from(s: $ty<S>) -> alloc::boxed::Box<$slice<S>> {
756                let inner: alloc::string::String = s.into();
757                let buf = alloc::boxed::Box::<str>::from(inner);
758                // SAFETY: `$slice<S>` has `repr(transparent)` attribute, so
759                // the memory layouts of `Box<str>` and `Box<$slice<S>>` are
760                // compatible. Additionally, `$ty<S>` and `$slice<S>` require
761                // the same syntax (it is the macro user's responsibility to
762                // guarantee).
763                unsafe {
764                    let raw: *mut str = alloc::boxed::Box::into_raw(buf);
765                    alloc::boxed::Box::<$slice<S>>::from_raw(raw as *mut $slice<S>)
766                }
767            }
768        }
769
770        impl<S: crate::spec::Spec> core::convert::TryFrom<&'_ str> for $ty<S> {
771            type Error = crate::validate::Error;
772
773            #[inline]
774            fn try_from(s: &str) -> Result<Self, Self::Error> {
775                <&$slice<S>>::try_from(s).map(Into::into)
776            }
777        }
778
779        impl<S: crate::spec::Spec> core::convert::TryFrom<&'_ [u8]> for $ty<S> {
780            type Error = crate::validate::Error;
781
782            #[inline]
783            fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
784                let s = core::str::from_utf8(bytes).map_err(|_| {
785                    crate::validate::Error::with_kind(crate::validate::ErrorKind::InvalidUtf8)
786                })?;
787                <&$slice<S>>::try_from(s).map(Into::into)
788            }
789        }
790
791        impl<S: crate::spec::Spec> core::convert::TryFrom<alloc::string::String> for $ty<S> {
792            type Error = crate::types::CreationError<alloc::string::String>;
793
794            #[inline]
795            fn try_from(s: alloc::string::String) -> Result<Self, Self::Error> {
796                match <&$slice<S>>::try_from(s.as_str()) {
797                    Ok(_) => {
798                        // This is safe because `<&$slice<S>>::try_from(s)?` ensures
799                        // that the string `s` is valid.
800                        Ok(Self {
801                            _spec: core::marker::PhantomData,
802                            inner: s,
803                        })
804                    }
805                    Err(e) => Err(crate::types::CreationError::new(e, s)),
806                }
807            }
808        }
809
810        impl<S: crate::spec::Spec> alloc::str::FromStr for $ty<S> {
811            type Err = crate::validate::Error;
812
813            #[inline]
814            fn from_str(s: &str) -> Result<Self, Self::Err> {
815                core::convert::TryFrom::try_from(s)
816            }
817        }
818
819        impl<S: crate::spec::Spec> core::ops::Deref for $ty<S> {
820            type Target = $slice<S>;
821
822            #[inline]
823            fn deref(&self) -> &$slice<S> {
824                self.as_ref()
825            }
826        }
827
828        impl_cmp!(str, $slice<S>, alloc::borrow::Cow<'_, str>);
829        impl_cmp!(str, &$slice<S>, alloc::borrow::Cow<'_, str>);
830        impl_cmp2_as_str!(&$slice<S>, alloc::borrow::Cow<'_, $slice<T>>);
831
832        impl_cmp!(str, str, $ty<S>);
833        impl_cmp!(str, &str, $ty<S>);
834        impl_cmp!(str, alloc::borrow::Cow<'_, str>, $ty<S>);
835        impl_cmp!(str, alloc::string::String, $ty<S>);
836        impl_cmp2!(str, $slice<S>, $ty<T>);
837        impl_cmp2!(str, &$slice<S>, $ty<T>);
838        impl_cmp2_as_str!(alloc::borrow::Cow<'_, $slice<S>>, $ty<T>);
839
840        impl<S: crate::spec::Spec> core::fmt::Display for $ty<S> {
841            #[inline]
842            fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
843                f.write_str(self.as_str())
844            }
845        }
846
847        /// Serde deserializer implementation.
848        #[cfg(all(feature = "alloc", feature = "serde"))]
849        mod __serde_owned {
850            use super::$ty;
851
852            use core::{convert::TryFrom, fmt, marker::PhantomData};
853
854            #[cfg(all(feature = "serde", feature = "alloc"))]
855            use alloc::string::String;
856
857            use serde::{
858                de::{self, Visitor},
859                Deserialize, Deserializer,
860            };
861
862            /// Custom owned string visitor.
863            #[derive(Debug, Clone, Copy)]
864            struct CustomStringVisitor<S>(PhantomData<fn() -> S>);
865
866            impl<'de, S: crate::spec::Spec> Visitor<'de> for CustomStringVisitor<S> {
867                type Value = $ty<S>;
868
869                #[inline]
870                fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
871                    f.write_str($expecting)
872                }
873
874                #[inline]
875                fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
876                where
877                    E: de::Error,
878                {
879                    <$ty<S> as TryFrom<&str>>::try_from(v).map_err(E::custom)
880                }
881
882                #[cfg(all(feature = "serde", feature = "alloc"))]
883                #[inline]
884                fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
885                where
886                    E: de::Error,
887                {
888                    <$ty<S> as TryFrom<String>>::try_from(v).map_err(E::custom)
889                }
890            }
891
892            impl<'de, S: crate::spec::Spec> Deserialize<'de> for $ty<S> {
893                #[inline]
894                fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
895                where
896                    D: Deserializer<'de>,
897                {
898                    deserializer.deserialize_str(CustomStringVisitor::<S>(PhantomData))
899                }
900            }
901        }
902    };
903}
904
905/// Implements trivial conversions and other useful traits between two IRI types.
906///
907/// Implemented traits:
908///
909/// * type conversion
910///     + `AsRef<$to_slice> for $from_slice`
911///     + `AsRef<$to_slice> for $from_owned`
912///     + `From<$from_slice> for $to_slice`
913///     + `From<$from_owned> for $to_owned`
914///     + `TryFrom<&$to_slice> for &$from_slice`
915///     + `TryFrom<$to_owned> for $from_owned`
916/// * comparison (only `PartialEq` impls are listed, but `PartialOrd` is also implemented).
917///     + `$from_slice` and `$to_slice`
918///         - `PartialEq<$from_slice> for $to_slice`
919///         - `PartialEq<$to_slice> for $from_slice`
920///         - `PartialEq<&$from_slice> for $to_slice`
921///         - `PartialEq<$to_slice> for &$from_slice`
922///         - `PartialEq<$from_slice> for &$to_slice`
923///         - `PartialEq<&$to_slice> for $from_slice`
924///         - `PartialEq<$from_slice> for Cow<'_, $to_slice>`
925///         - `PartialEq<Cow<'_, $to_slice>> for $from_slice`
926///         - `PartialEq<&$from_slice> for Cow<'_, $to_slice>`
927///         - `PartialEq<Cow<'_, $to_slice>> for &$from_slice`
928///         - `PartialEq<Cow<'_, $from_slice>> for $to_slice`
929///         - `PartialEq<$to_slice> for Cow<'_, $from_slice>`
930///         - `PartialEq<Cow<'_, $from_slice>> for &$to_slice`
931///         - `PartialEq<&$to_slice> for Cow<'_, $from_slice>`
932///     + `$from_slice` and `$to_owned`
933///         - `PartialEq<$from_slice> for $to_owned`
934///         - `PartialEq<$to_owned> for $from_slice`
935///         - `PartialEq<&$from_slice> for $to_owned`
936///         - `PartialEq<$to_owned> for &$from_slice`
937///         - `PartialEq<Cow<'_, $from_slice>> for $to_owned`
938///         - `PartialEq<$to_owned> for Cow<'_, $from_slice>`
939///     + `$from_owned` and `$to_slice`
940///         - `PartialEq<$from_owned> for $to_slice`
941///         - `PartialEq<$to_slice> for $from_owned`
942///         - `PartialEq<$from_owned> for &$to_slice`
943///         - `PartialEq<&$to_slice> for $from_owned`
944///         - `PartialEq<$from_owned> for Cow<'_, $to_slice>`
945///         - `PartialEq<Cow<'_, $to_slice>> for $from_owned`
946///     + `$from_owned` and `$to_owned`
947///         - `PartialEq<$from_owned> for $to_owned`
948///         - `PartialEq<$to_owned> for $from_owned`
949macro_rules! impl_trivial_conv_between_iri {
950    (
951        from_slice: $from_slice:ident,
952        from_owned: $from_owned:ident,
953        to_slice: $to_slice:ident,
954        to_owned: $to_owned:ident,
955    ) => {
956        impl<S: crate::spec::Spec> AsRef<$to_slice<S>> for $from_slice<S> {
957            #[inline]
958            fn as_ref(&self) -> &$to_slice<S> {
959                // SAFETY: `$from_slice<S>` should be subset of `$to_slice<S>`.
960                // The caller of `impl_trivial_conv_between_iri!` macro is
961                // responsible for guaranteeing that.
962                unsafe { <$to_slice<S>>::new_maybe_unchecked(self.as_str()) }
963            }
964        }
965
966        #[cfg(feature = "alloc")]
967        impl<S: crate::spec::Spec> AsRef<$to_slice<S>> for $from_owned<S> {
968            #[inline]
969            fn as_ref(&self) -> &$to_slice<S> {
970                AsRef::<$from_slice<S>>::as_ref(self).as_ref()
971            }
972        }
973
974        impl<'a, S: crate::spec::Spec> From<&'a $from_slice<S>> for &'a $to_slice<S> {
975            #[inline]
976            fn from(s: &'a $from_slice<S>) -> &'a $to_slice<S> {
977                s.as_ref()
978            }
979        }
980
981        #[cfg(feature = "alloc")]
982        impl<S: crate::spec::Spec> From<$from_owned<S>> for $to_owned<S> {
983            #[inline]
984            fn from(s: $from_owned<S>) -> $to_owned<S> {
985                // SAFETY: `$from_slice<S>` should be subset of `$to_slice<S>`.
986                // The caller of `impl_trivial_conv_between_iri!` macro is
987                // responsible for guaranteeing that.
988                unsafe { <$to_owned<S>>::new_maybe_unchecked(s.into()) }
989            }
990        }
991
992        impl<'a, S: crate::spec::Spec> core::convert::TryFrom<&'a $to_slice<S>>
993            for &'a $from_slice<S>
994        {
995            type Error = crate::validate::Error;
996
997            #[inline]
998            fn try_from(s: &'a $to_slice<S>) -> Result<Self, Self::Error> {
999                Self::try_from(s.as_str())
1000            }
1001        }
1002
1003        #[cfg(feature = "alloc")]
1004        impl<S: crate::spec::Spec> core::convert::TryFrom<$to_owned<S>> for $from_owned<S> {
1005            type Error = crate::types::CreationError<$to_owned<S>>;
1006
1007            fn try_from(s: $to_owned<S>) -> Result<Self, Self::Error> {
1008                match <&$from_slice<S>>::try_from(s.as_str()) {
1009                    // SAFETY: just checked `s.as_str()` is valid as `$from_slice<S>`, and it
1010                    // requires the same syntax as `$from_owned<S>`.
1011                    Ok(_) => Ok(unsafe { <$from_owned<S>>::new_always_unchecked(s.into()) }),
1012                    Err(e) => Err(crate::types::CreationError::new(e, s)),
1013                }
1014            }
1015        }
1016
1017        impl_cmp2_as_str!($from_slice<S>, $to_slice<T>);
1018        impl_cmp2_as_str!(&$from_slice<S>, $to_slice<T>);
1019        impl_cmp2_as_str!($from_slice<S>, &$to_slice<T>);
1020        #[cfg(feature = "alloc")]
1021        impl_cmp2_as_str!($from_slice<S>, alloc::borrow::Cow<'_, $to_slice<T>>);
1022        #[cfg(feature = "alloc")]
1023        impl_cmp2_as_str!(&$from_slice<S>, alloc::borrow::Cow<'_, $to_slice<T>>);
1024        #[cfg(feature = "alloc")]
1025        impl_cmp2_as_str!(alloc::borrow::Cow<'_, $from_slice<S>>, $to_slice<T>);
1026        #[cfg(feature = "alloc")]
1027        impl_cmp2_as_str!(alloc::borrow::Cow<'_, $from_slice<S>>, &$to_slice<T>);
1028
1029        #[cfg(feature = "alloc")]
1030        impl_cmp2_as_str!($from_slice<S>, $to_owned<T>);
1031        #[cfg(feature = "alloc")]
1032        impl_cmp2_as_str!(&$from_slice<S>, $to_owned<T>);
1033        #[cfg(feature = "alloc")]
1034        impl_cmp2_as_str!(alloc::borrow::Cow<'_, $from_slice<S>>, $to_owned<T>);
1035
1036        #[cfg(feature = "alloc")]
1037        impl_cmp2_as_str!($from_owned<S>, $to_slice<T>);
1038        #[cfg(feature = "alloc")]
1039        impl_cmp2_as_str!($from_owned<S>, &$to_slice<T>);
1040        #[cfg(feature = "alloc")]
1041        impl_cmp2_as_str!($from_owned<S>, alloc::borrow::Cow<'_, $to_slice<T>>);
1042        #[cfg(feature = "alloc")]
1043        impl_cmp2_as_str!($from_owned<S>, $to_owned<T>);
1044    };
1045}