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}