validated_slice/macros/
borrowed.rs

1//! Macros for borrowed custom slice types.
2
3/// Implements some methods of [`SliceSpec`] trait automatically.
4///
5/// This macro can be safely used in nostd environment.
6///
7/// # Examples
8///
9/// ```
10/// #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
11/// struct AsciiError {
12///     valid_up_to: usize,
13/// }
14/// pub struct AsciiStr(str);
15///
16/// enum AsciiStrSpec {}
17///
18/// impl validated_slice::SliceSpec for AsciiStrSpec {
19///     type Custom = AsciiStr;
20///     type Inner = str;
21///     type Error = AsciiError;
22///
23///     #[inline]
24///     fn validate(s: &Self::Inner) -> Result<(), Self::Error> {
25///         match s.as_bytes().iter().position(|b| !b.is_ascii()) {
26///             Some(pos) => Err(AsciiError { valid_up_to: pos }),
27///             None => Ok(()),
28///         }
29///     }
30///
31///     validated_slice::impl_slice_spec_methods! {
32///         field=0;
33///         methods=[
34///             as_inner,
35///             as_inner_mut,
36///             from_inner_unchecked,
37///             from_inner_unchecked_mut,
38///         ];
39///     }
40/// }
41/// ```
42///
43/// ## Field
44///
45/// For tuple struct, `field` is the index of the inner slice field.
46/// For usual struct, `field` is the identifier of the field.
47///
48/// ## Methods
49///
50/// List methods to implement automatically.
51/// `validate` is not supported and should be manually implemented by the user.
52///
53/// [`SliceSpec`]: trait.SliceSpec.html
54#[macro_export]
55macro_rules! impl_slice_spec_methods {
56    (
57        field=$field:tt;
58        methods=[$($method:ident),* $(,)?];
59    ) => {
60        $(
61            $crate::impl_slice_spec_methods! {
62                @impl; ($field);
63                $method
64            }
65        )*
66    };
67    (@impl; ($field:tt); as_inner) => {
68        #[inline]
69        fn as_inner(s: &Self::Custom) -> &Self::Inner {
70            &s.$field
71        }
72    };
73    (@impl; ($field:tt); as_inner_mut) => {
74        #[inline]
75        fn as_inner_mut(s: &mut Self::Custom) -> &mut Self::Inner {
76            &mut s.$field
77        }
78    };
79    (@impl; ($field:tt); from_inner_unchecked) => {
80        #[inline]
81        unsafe fn from_inner_unchecked(s: &Self::Inner) -> &Self::Custom {
82            &*(s as *const Self::Inner as *const Self::Custom)
83        }
84    };
85    (@impl; ($field:tt); from_inner_unchecked_mut) => {
86        #[inline]
87        unsafe fn from_inner_unchecked_mut(s: &mut Self::Inner) -> &mut Self::Custom {
88            &mut *(s as *mut Self::Inner as *mut Self::Custom)
89        }
90    };
91}
92
93/// Implements std traits for the given custom slice type.
94///
95/// To implement `PartialEq` and `PartialOrd`, use [`impl_cmp_for_slice!`] macro.
96///
97/// # Usage
98///
99/// ## Examples
100///
101/// Assume you want to implement `str` type manually by yourself.
102/// Then you will have the type definitions below:
103///
104/// ```ignore
105/// /// My `str` type.
106/// #[repr(transparent)]
107/// #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
108/// pub struct MyStr([u8]);
109///
110/// /// Spec for `MyStr` type.
111/// enum MyStrSpec {}
112///
113/// impl validated_slice::SliceSpec for MyStrSpec {
114///     // My `str` type.
115///     type Custom = MyStr;
116///     // Backend type of `MyStr`.
117///     type Inner = [u8];
118///     // My `std::str::Utf8Error`.
119///     type Error = MyUtf8Error;
120///
121///     /* ... and methods. */
122/// }
123/// ```
124///
125/// Then you can implement std traits as below:
126///
127/// ```ignore
128/// validated_slice::impl_std_traits_for_slice! {
129///     // `Std` is omissible.
130///     Std {
131///         // Module identifier of `core` crate.
132///         // Default is `std`.
133///         core: core,
134///         // Module identifier of `alloc` crate.
135///         // Default is `std`.
136///         alloc: alloc,
137///     };
138///     Spec {
139///         spec: MyStrSpec,
140///         custom: MyStr,
141///         inner: [u8],
142///         error: MyUtf8Error,
143///     };
144///     { AsRef<[u8]> };
145///     { AsRef<str> };
146///     { AsRef<{Custom}> };
147///     { From<&{Custom}> for Arc<{Custom}> };
148///     /* ... and more traits you want! */
149/// }
150/// ```
151///
152/// ## Core and alloc
153///
154/// For `no_std` use, the macro uses custom `core` and `alloc` crate if given.
155/// You can support both nostd and non-nostd environment as below:
156///
157/// ```ignore
158/// // Use `std` when available.
159/// #[cfg(feature = "std")]
160/// use alloc as std;
161/// // Use external `alloc` crate when nostd.
162/// #[cfg(not(feature = "std"))]
163/// use alloc;
164///
165/// validated_slice::impl_std_traits_for_slice! {
166///     Std {
167///         core: core,
168///         alloc: alloc,
169///     };
170///     Spec { /* ... */ };
171///     /* ... */
172/// }
173/// ```
174///
175/// When you don't need `alloc` crate on nostd build, value of `alloc` field is not used.
176/// Simply specify `alloc: alloc,` or something.
177///
178/// ## Type names
179///
180/// As type name, you can use `{Custom}` and `{Inner}` instead of a real type name.
181/// They are replaced to the specified custom and inner types.
182///
183/// `Arc<ty>`, `Box<ty>`, `Cow<ty>`, and `Rc<ty>` will be also replaced to `std::sync::Arc<ty>`,
184/// `std::boxed::Box<ty>`, `std::borrow::Cow<'_, ty>`, and `std::rc::Rc<ty>`, respectively.
185/// They are checked symbolically, so they cannot be specified by type aliases, or
186/// path names such as `std::sync::Arc<ty>`.
187///
188/// ## Supported trait impls
189///
190/// **NOTE**: To implemente `PartialEq` and `PartialOrd`, use `impl_cmp_for_slice!` macro.
191///
192/// Each trait impl is specified by `{ TraitName<TyParams> for TyImplTarget };` format.
193/// `<TyParams>` part and `for TyImplTarget` part is optional.
194///
195/// Default impl target is `{Custom}`, and it should NOT be specified explicitly.
196/// Explicit `for {Custom}` is not supported and will cause compile error.
197///
198/// Supported trait impls are:
199///
200/// * `std::convert`
201///     + `{ AsMut<{Custom}> };`
202///     + `{ AsMut<any_ty> };`
203///     + `{ AsRef<{Custom}> };`
204///     + `{ AsRef<{Custom}> for Cow<{Custom}> };`
205///     + `{ AsRef<any_ty> };`
206///     + `{ AsRef<any_ty> for Cow<{Custom}> };`
207///     + `{ From<&{Inner}> for &{Custom} };
208///     + `{ From<&mut {Inner}> for &mut {Custom} };
209///     + `{ From<&{Custom}> for &{Inner} };
210///     + `{ From<&mut {Custom}> for &mut {Inner} };
211///     + `{ From<&{Custom}> for Arc<{Custom}> };
212///     + `{ From<&{Custom}> for Box<{Custom}> };
213///     + `{ From<&{Custom}> for Rc<{Custom}> };
214///     + `{ TryFrom<&{Inner}> for &{Custom} };
215///     + `{ TryFrom<&mut {Inner}> for &mut {Custom} };
216/// * `std::default`
217///     + `{ Default for &{Custom} };`
218///     + `{ Default for &mut {Custom} };`
219/// * `std::fmt`
220///     + `{ Debug };`
221///     + `{ Display };`
222/// * `std::ops`
223///     + `{ Deref<Target = {Inner}> };`
224///     + `{ DerefMut<Target = {Inner}> };`
225///
226/// [`impl_cmp_for_slice!`]: macro.impl_cmp_for_slice.html
227#[macro_export]
228macro_rules! impl_std_traits_for_slice {
229    (
230        Spec {
231            spec: $spec:ty,
232            custom: $custom:ty,
233            inner: $inner:ty,
234            error: $error:ty,
235        };
236        $({$($rest:tt)*});* $(;)?
237    ) => {
238        $(
239            $crate::impl_std_traits_for_slice! {
240                @impl; ({std, std}, $spec, $custom, $inner, $error);
241                rest=[$($rest)*];
242            }
243        )*
244    };
245
246    (
247        Std {
248            core: $core:ident,
249            alloc: $alloc:ident,
250        };
251        Spec {
252            spec: $spec:ty,
253            custom: $custom:ty,
254            inner: $inner:ty,
255            error: $error:ty,
256        };
257        $({$($rest:tt)*});* $(;)?
258    ) => {
259        $(
260            $crate::impl_std_traits_for_slice! {
261                @impl; ({$core, $alloc}, $spec, $custom, $inner, $error);
262                rest=[$($rest)*];
263            }
264        )*
265    };
266
267    // std::convert::AsMut
268    (
269        @impl; ({$core:ident, $alloc:ident}, $spec:ty, $custom:ty, $inner:ty, $error:ty);
270        rest=[ AsMut<{Custom}> ];
271    ) => {
272        impl $core::convert::AsMut<$custom> for $custom {
273            #[inline]
274            fn as_mut(&mut self) -> &mut $custom {
275                self
276            }
277        }
278    };
279    (
280        @impl; ({$core:ident, $alloc:ident}, $spec:ty, $custom:ty, $inner:ty, $error:ty);
281        rest=[ AsMut<$param:ty> ];
282    ) => {
283        impl $core::convert::AsMut<$param> for $custom
284        where
285            $inner: AsMut<$param>,
286        {
287            #[inline]
288            fn as_mut(&mut self) -> &mut $param {
289                <$spec as $crate::SliceSpec>::as_inner_mut(self).as_mut()
290            }
291        }
292    };
293
294    // std::convert::AsRef
295    (
296        @impl; ({$core:ident, $alloc:ident}, $spec:ty, $custom:ty, $inner:ty, $error:ty);
297        rest=[ AsRef<{Custom}> ];
298    ) => {
299        impl $core::convert::AsRef<$custom> for $custom {
300            #[inline]
301            fn as_ref(&self) -> &$custom {
302                self
303            }
304        }
305    };
306    (
307        @impl; ({$core:ident, $alloc:ident}, $spec:ty, $custom:ty, $inner:ty, $error:ty);
308        rest=[ AsRef<{Custom}> for Cow<{Custom}> ];
309    ) => {
310        impl<'a> $core::convert::AsRef<$custom> for $alloc::borrow::Cow<'a, $custom> {
311            #[inline]
312            fn as_ref(&self) -> &$custom {
313                &**self
314            }
315        }
316    };
317    (
318        @impl; ({$core:ident, $alloc:ident}, $spec:ty, $custom:ty, $inner:ty, $error:ty);
319        rest=[ AsRef<$param:ty> ];
320    ) => {
321        impl $core::convert::AsRef<$param> for $custom
322        where
323            $inner: AsRef<$param>,
324        {
325            #[inline]
326            fn as_ref(&self) -> &$param {
327                <$spec as $crate::SliceSpec>::as_inner(self).as_ref()
328            }
329        }
330    };
331    (
332        @impl; ({$core:ident, $alloc:ident}, $spec:ty, $custom:ty, $inner:ty, $error:ty);
333        rest=[ AsRef<$param:ty> for Cow<{Custom}> ];
334    ) => {
335        impl<'a> $core::convert::AsRef<$param> for $alloc::borrow::Cow<'a, $custom>
336        where
337            $inner: AsRef<$param>,
338        {
339            #[inline]
340            fn as_ref(&self) -> &$param {
341                <$spec as $crate::SliceSpec>::as_inner(&**self).as_ref()
342            }
343        }
344    };
345
346    // std::convert::From
347    (
348        @impl; ({$core:ident, $alloc:ident}, $spec:ty, $custom:ty, $inner:ty, $error:ty);
349        rest=[ From<&{Inner}> for &{Custom} ];
350    ) => {
351        impl<'a> $core::convert::From<&'a $inner> for &'a $custom {
352            fn from(s: &'a $inner) -> Self {
353                assert!(
354                    <$spec as $crate::SliceSpec>::validate(s).is_ok(),
355                    "Attempt to convert invalid data: `From<&{}> for &{}`",
356                    stringify!($inner), stringify!($custom)
357                );
358                unsafe {
359                    // This is safe only when all of the conditions below are met:
360                    //
361                    // * `$spec::validate(s)` returns `Ok(())`.
362                    //     + This is ensured by the leading assert.
363                    // * Safety condition for `<$spec as $crate::SliceSpec>` is satisfied.
364                    <$spec as $crate::SliceSpec>::from_inner_unchecked(s)
365                }
366            }
367        }
368    };
369    (
370        @impl; ({$core:ident, $alloc:ident}, $spec:ty, $custom:ty, $inner:ty, $error:ty);
371        rest=[ From<&mut {Inner}> for &mut {Custom} ];
372    ) => {
373        impl<'a> $core::convert::From<&'a mut $inner> for &'a mut $custom {
374            fn from(s: &'a mut $inner) -> Self {
375                assert!(
376                    <$spec as $crate::SliceSpec>::validate(s).is_ok(),
377                    "Attempt to convert invalid data: `From<&mut {}> for &mut {}`",
378                    stringify!($inner), stringify!($custom)
379                );
380                unsafe {
381                    // This is safe only when all of the conditions below are met:
382                    //
383                    // * `$spec::validate(s)` returns `Ok(())`.
384                    //     + This is ensured by the leading assert.
385                    // * Safety condition for `<$spec as $crate::SliceSpec>` is satisfied.
386                    <$spec as $crate::SliceSpec>::from_inner_unchecked_mut(s)
387                }
388            }
389        }
390    };
391    (
392        @impl; ({$core:ident, $alloc:ident}, $spec:ty, $custom:ty, $inner:ty, $error:ty);
393        rest=[ From<&{Custom}> for &{Inner} ];
394    ) => {
395        impl<'a> $core::convert::From<&'a $custom> for &'a $inner {
396            fn from(s: &'a $custom) -> Self {
397                <$spec as $crate::SliceSpec>::as_inner(s)
398            }
399        }
400    };
401    (
402        @impl; ({$core:ident, $alloc:ident}, $spec:ty, $custom:ty, $inner:ty, $error:ty);
403        rest=[ From<&mut {Custom}> for &mut {Inner} ];
404    ) => {
405        impl<'a> $core::convert::From<&'a mut $custom> for &'a mut $inner {
406            fn from(s: &'a mut $custom) -> Self {
407                <$spec as $crate::SliceSpec>::as_inner_mut(s)
408            }
409        }
410    };
411
412    // std::convert::From for smart pointers
413    (
414        @impl [smartptr]; ({$core:ident, $alloc:ident}, $spec:ty, $custom:ty, $inner:ty, $error:ty);
415        rest=[ From<&{Custom}> for $($smartptr:ident)::* <{Custom}> ];
416    ) => {
417        impl<'a> $core::convert::From<&'a $custom> for $($smartptr)::* <$custom>
418        where
419            $($smartptr)::* <$inner>: $core::convert::From<&'a $inner>,
420        {
421            fn from(s: &'a $custom) -> Self {
422                let inner = <$spec as $crate::SliceSpec>::as_inner(s);
423                let buf = $($smartptr)::* ::<$inner>::from(inner);
424                unsafe {
425                    // This is safe only when all of the conditions below are met:
426                    //
427                    // * `$spec::validate(s)` returns `Ok(())`.
428                    //     + This is ensured by the leading assert.
429                    // * Safety condition for `<$spec as $crate::SliceSpec>` is satisfied.
430                    //     + This ensures that the memory layout of `into_raw(buf)` is also valid
431                    //       as `$($smartptr)::* <$custom>`.
432                    $($smartptr)::* ::<$custom>::from_raw(
433                        $($smartptr)::* ::<$inner>::into_raw(buf) as *mut $custom
434                    )
435                }
436            }
437        }
438    };
439    (
440        @impl; ({$core:ident, $alloc:ident}, $spec:ty, $custom:ty, $inner:ty, $error:ty);
441        rest=[ From<&{Custom}> for Arc<{Custom}> ];
442    ) => {
443        $crate::impl_std_traits_for_slice! {
444            @impl [smartptr]; ({$core, $alloc}, $spec, $custom, $inner, $error);
445            rest=[ From<&{Custom}> for $alloc::sync::Arc <{Custom}> ];
446        }
447    };
448    (
449        @impl; ({$core:ident, $alloc:ident}, $spec:ty, $custom:ty, $inner:ty, $error:ty);
450        rest=[ From<&{Custom}> for Box<{Custom}> ];
451    ) => {
452        $crate::impl_std_traits_for_slice! {
453            @impl [smartptr]; ({$core, $alloc}, $spec, $custom, $inner, $error);
454            rest=[ From<&{Custom}> for $alloc::boxed::Box <{Custom}> ];
455        }
456    };
457    (
458        @impl; ({$core:ident, $alloc:ident}, $spec:ty, $custom:ty, $inner:ty, $error:ty);
459        rest=[ From<&{Custom}> for Rc<{Custom}> ];
460    ) => {
461        $crate::impl_std_traits_for_slice! {
462            @impl [smartptr]; ({$core, $alloc}, $spec, $custom, $inner, $error);
463            rest=[ From<&{Custom}> for $alloc::rc::Rc <{Custom}> ];
464        }
465    };
466
467    // std::convert::TryFrom
468    (
469        @impl; ({$core:ident, $alloc:ident}, $spec:ty, $custom:ty, $inner:ty, $error:ty);
470        rest=[ TryFrom<&{Inner}> for &{Custom} ];
471    ) => {
472        impl<'a> $core::convert::TryFrom<&'a $inner> for &'a $custom {
473            type Error = $error;
474
475            fn try_from(s: &'a $inner) -> $core::result::Result<Self, Self::Error> {
476                <$spec as $crate::SliceSpec>::validate(s)?;
477                Ok(unsafe {
478                    // This is safe only when all of the conditions below are met:
479                    //
480                    // * `$spec::validate(s)` returns `Ok(())`.
481                    //     + This is ensured by the leading `validate()?` call.
482                    // * Safety condition for `<$spec as $crate::SliceSpec>` is satisfied.
483                    <$spec as $crate::SliceSpec>::from_inner_unchecked(s)
484                })
485            }
486        }
487    };
488    (
489        @impl; ({$core:ident, $alloc:ident}, $spec:ty, $custom:ty, $inner:ty, $error:ty);
490        rest=[ TryFrom<&mut {Inner}> for &mut {Custom} ];
491    ) => {
492        impl<'a> $core::convert::TryFrom<&'a mut $inner> for &'a mut $custom {
493            type Error = $error;
494
495            fn try_from(s: &'a mut $inner) -> $core::result::Result<Self, Self::Error> {
496                <$spec as $crate::SliceSpec>::validate(s)?;
497                Ok(unsafe {
498                    // This is safe only when all of the conditions below are met:
499                    //
500                    // * `$spec::validate(s)` returns `Ok(())`.
501                    //     + This is ensured by the leading `validate()?` call.
502                    // * Safety condition for `<$spec as $crate::SliceSpec>` is satisfied.
503                    <$spec as $crate::SliceSpec>::from_inner_unchecked_mut(s)
504                })
505            }
506        }
507    };
508
509    // std::default::Default
510    (
511        @impl; ({$core:ident, $alloc:ident}, $spec:ty, $custom:ty, $inner:ty, $error:ty);
512        rest=[ Default for &{Custom} ];
513    ) => {
514        impl<'a> $core::default::Default for &'a $custom
515        where
516            &'a $inner: $core::default::Default,
517        {
518            fn default() -> Self {
519                let inner = <&'a $inner as $core::default::Default>::default();
520                assert!(
521                    <$spec as $crate::SliceSpec>::validate(inner).is_ok(),
522                    "Attempt to create invalid data: `Default for &{}`",
523                    stringify!($custom)
524                );
525                unsafe {
526                    // This is safe only when all of the conditions below are met:
527                    //
528                    // * `$spec::validate(s)` returns `Ok(())`.
529                    //     + This is ensured by the leading assert.
530                    // * Safety condition for `<$spec as $crate::SliceSpec>` is satisfied.
531                    <$spec as $crate::SliceSpec>::from_inner_unchecked(inner)
532                }
533            }
534        }
535    };
536    (
537        @impl; ({$core:ident, $alloc:ident}, $spec:ty, $custom:ty, $inner:ty, $error:ty);
538        rest=[ Default for &mut {Custom} ];
539    ) => {
540        impl<'a> $core::default::Default for &'a mut $custom
541        where
542            &'a mut $inner: $core::default::Default,
543        {
544            fn default() -> Self {
545                let inner = <&'a mut $inner as $core::default::Default>::default();
546                assert!(
547                    <$spec as $crate::SliceSpec>::validate(inner).is_ok(),
548                    "Attempt to create invalid data: `Default for &{}`",
549                    stringify!($custom)
550                );
551                unsafe {
552                    // This is safe only when all of the conditions below are met:
553                    //
554                    // * `$spec::validate(s)` returns `Ok(())`.
555                    //     + This is ensured by the leading assert.
556                    // * Safety condition for `<$spec as $crate::SliceSpec>` is satisfied.
557                    <$spec as $crate::SliceSpec>::from_inner_unchecked_mut(inner)
558                }
559            }
560        }
561    };
562
563    // std::fmt::Debug
564    (
565        @impl; ({$core:ident, $alloc:ident}, $spec:ty, $custom:ty, $inner:ty, $error:ty);
566        rest=[ Debug ];
567    ) => {
568        impl $core::fmt::Debug for $custom
569        where
570            $inner: $core::fmt::Debug,
571        {
572            fn fmt(&self, f: &mut $core::fmt::Formatter<'_>) -> $core::fmt::Result {
573                let inner = <$spec as $crate::SliceSpec>::as_inner(self);
574                <$inner as $core::fmt::Debug>::fmt(inner, f)
575            }
576        }
577    };
578
579    // std::fmt::Display
580    (
581        @impl; ({$core:ident, $alloc:ident}, $spec:ty, $custom:ty, $inner:ty, $error:ty);
582        rest=[ Display ];
583    ) => {
584        impl $core::fmt::Display for $custom
585        where
586            $inner: $core::fmt::Display,
587        {
588            fn fmt(&self, f: &mut $core::fmt::Formatter<'_>) -> $core::fmt::Result {
589                let inner = <$spec as $crate::SliceSpec>::as_inner(self);
590                <$inner as $core::fmt::Display>::fmt(inner, f)
591            }
592        }
593    };
594
595    // std::ops::Deref
596    (
597        @impl; ({$core:ident, $alloc:ident}, $spec:ty, $custom:ty, $inner:ty, $error:ty);
598        rest=[ Deref<Target = {Inner}> ];
599    ) => {
600        impl $core::ops::Deref for $custom {
601            type Target = $inner;
602
603            #[inline]
604            fn deref(&self) -> &Self::Target {
605                <$spec as $crate::SliceSpec>::as_inner(self)
606            }
607        }
608    };
609
610    // std::ops::DerefMut
611    (
612        @impl; ({$core:ident, $alloc:ident}, $spec:ty, $custom:ty, $inner:ty, $error:ty);
613        rest=[ DerefMut<Target = {Inner}> ];
614    ) => {
615        impl $core::ops::DerefMut for $custom {
616            #[inline]
617            fn deref_mut(&mut self) -> &mut Self::Target {
618                <$spec as $crate::SliceSpec>::as_inner_mut(self)
619            }
620        }
621    };
622
623    // Fallback.
624    (
625        @impl; ({$core:ident, $alloc:ident}, $spec:ty, $custom:ty, $inner:ty, $error:ty);
626        rest=[ $($rest:tt)* ];
627    ) => {
628        compile_error!(concat!("Unsupported target: ", stringify!($($rest)*)));
629    };
630}
631
632/// Implements `PartialEq` and `PartialOrd` for the given custom slice type.
633///
634/// # Usage
635///
636/// ## Examples
637///
638/// ```ignore
639/// validated_slice::impl_cmp_for_slice! {
640///     // `Std` is omissible.
641///     Std {
642///         // Module identifier of `core` crate.
643///         // Default is `std`.
644///         core: core,
645///         // Module identifier of `alloc` crate.
646///         // Default is `std`.
647///         alloc: alloc,
648///     };
649///     Spec {
650///         spec: AsciiStrSpec,
651///         custom: AsciiStr,
652///         inner: str,
653///         base: Inner,
654///     };
655///     Cmp { PartialEq, PartialOrd };
656///     // This is same as `#[derive(PartialEq, PartialOrd)]`.
657///     { ({Custom}), ({Custom}) };
658///     { ({Custom}), (&{Custom}), rev };
659///     // NOTE: `std::borrow::ToOwned for AsciiStr` is required by `Cow`.
660///     { ({Custom}), (Cow<{Custom}>), rev };
661///
662///     { ({Custom}), ({Inner}), rev };
663///     { ({Custom}), (&{Inner}), rev };
664///     /* ... and more pairs! */
665/// }
666/// ```
667///
668/// ## Core and alloc
669///
670/// For `no_std` use, the macro uses custom `core` and `alloc` crate if given.
671/// You can support both nostd and non-nostd environment as below:
672///
673/// ```ignore
674/// // Use `std` when available.
675/// #[cfg(feature = "std")]
676/// use alloc as std;
677/// // Use external `alloc` crate when nostd.
678/// #[cfg(not(feature = "std"))]
679/// use alloc;
680///
681/// validated_slice::impl_cmp_for_slice! {
682///     Std {
683///         core: core,
684///         alloc: alloc,
685///     }
686///     Spec { /* ... */ };
687///     Cmp { /* ... */ };
688///     /* ... */
689/// }
690/// ```
691///
692/// When you don't need `alloc` crate on nostd build, value of `alloc` field is not used.
693/// Simply specify `alloc: alloc,` or something.
694///
695/// ## Comparison base
696///
697/// The syntax of `Spec` part is very similar to [`impl_std_traits_for_slice!`] macro.
698///
699/// As `base` field, specify `Custom` or `Inner` to decide which comparison should be used
700/// internally.
701/// If you don't define custom comparison, use `base: Inner`.
702///
703/// ## Traits to implement
704///
705/// Comparison traits to implement is specified by `Cmp { .. };` format.
706/// Supproted formats are: `Cmp { PartialEq }`, `Cmp { PartialOrd }`, and
707/// `Cmp { PartialEq, PartialOrd };`.
708///
709/// ## Operand type pairs
710///
711/// Comparisons are implemented between two types, so you should provide list of pairs to implement
712/// comparison.
713///
714/// Supported syntaxes are: `{ (lhs_ty), (rhs_ty) };` and `{ (lhs_ty), (rhs_ty), rev };`.
715///
716/// Parentheses around types are not omittable.
717///
718/// With `, rev`, the macro implements not only `PartialXx<rhs_ty> for lhs_ty`, but also
719/// `PartialXx<lhs_ty> for rhs_ty`.
720///
721/// ## Type names
722///
723/// `{Custom}` and `{Inner}` will be replaced to the custom slice type and its inner type.
724///
725/// `&ty` and `Cow<ty>` are also supported.
726///
727/// Note that in case you specify arbitrary types (other than `{Custom}`, `{Inner}`, and its
728/// variations), that type should implement `AsRef<base_type>`.
729///
730/// ## Supported types
731///
732/// * `{Custom}`
733/// * `&{Custom}`
734/// * `Cow<{Custom}>`
735/// * `{Inner}`
736/// * `&{Inner}`
737/// * `Cow<{Inner}>`
738/// * ... and arbitrary types
739///
740/// Note that, with `base: Custom`, `{Inner}` and its variants are not supported (because it does
741/// not make sense).
742///
743/// [`impl_std_traits_for_slice!`]: macro.impl_std_traits_for_slice.html
744#[macro_export]
745macro_rules! impl_cmp_for_slice {
746    (
747        Spec {
748            spec: $spec:ty,
749            custom: $custom:ty,
750            inner: $inner:ty,
751            base: $base:ident,
752        };
753        Cmp { $($cmp_targets:ident),* };
754        $($rest:tt)*
755    ) => {
756        $crate::impl_cmp_for_slice! {
757            @full;
758            Std {
759                core: std,
760                alloc: std,
761            };
762            Spec {
763                spec: $spec,
764                custom: $custom,
765                inner: $inner,
766                base: $base,
767            };
768            Cmp { $($cmp_targets),* };
769            $($rest)*
770        }
771    };
772    (
773        Std {
774            core: $core:ident,
775            alloc: $alloc:ident,
776        };
777        Spec {
778            spec: $spec:ty,
779            custom: $custom:ty,
780            inner: $inner:ty,
781            base: $base:ident,
782        };
783        Cmp { $($cmp_targets:ident),* };
784        $($rest:tt)*
785    ) => {
786        $crate::impl_cmp_for_slice! {
787            @full;
788            Std {
789                core: $core,
790                alloc: $alloc,
791            };
792            Spec {
793                spec: $spec,
794                custom: $custom,
795                inner: $inner,
796                base: $base,
797            };
798            Cmp { $($cmp_targets),* };
799            $($rest)*
800        }
801    };
802
803    (
804        @full;
805        Std {
806            core: $core:ident,
807            alloc: $alloc:ident,
808        };
809        Spec {
810            spec: $spec:ty,
811            custom: $custom:ty,
812            inner: $inner:ty,
813            base: $base:ident,
814        };
815        Cmp { PartialEq, PartialOrd };
816        $({ ($($lhs:tt)*), ($($rhs:tt)*) $(, $($opt:ident),*)? });* $(;)?
817    ) => {
818        $(
819            $crate::impl_cmp_for_slice! {
820                @impl[PartialEq]; ({$core, $alloc}, $spec, $custom, $inner, $base);
821                { ($($lhs)*), ($($rhs)*) $(, $($opt),*)? };
822            }
823            $crate::impl_cmp_for_slice! {
824                @impl[PartialOrd]; ({$core, $alloc}, $spec, $custom, $inner, $base);
825                { ($($lhs)*), ($($rhs)*) $(, $($opt),*)? };
826            }
827        )*
828    };
829    (
830        @full;
831        Std {
832            core: $core:ident,
833            alloc: $alloc:ident,
834        };
835        Spec {
836            spec: $spec:ty,
837            custom: $custom:ty,
838            inner: $inner:ty,
839            base: $base:ident,
840        };
841        Cmp { PartialEq };
842        $({ ($($lhs:tt)*), ($($rhs:tt)*) $(, $($opt:ident),*)? });* $(;)?
843    ) => {
844        $(
845            $crate::impl_cmp_for_slice! {
846                @impl[PartialEq]; ({$core, $alloc}, $spec, $custom, $inner, $base);
847                { ($($lhs)*), ($($rhs)*) $(, $($opt),*)? };
848            }
849        )*
850    };
851    (
852        @full;
853        Std {
854            core: $core:ident,
855            alloc: $alloc:ident,
856        };
857        Spec {
858            spec: $spec:ty,
859            custom: $custom:ty,
860            inner: $inner:ty,
861            base: $base:ident,
862        };
863        Cmp { PartialOrd };
864        $({ ($($lhs:tt)*), ($($rhs:tt)*) $(, $($opt:ident),*)? });* $(;)?
865    ) => {
866        $(
867            $crate::impl_cmp_for_slice! {
868                @impl[PartialOrd]; ({$core, $alloc}, $spec, $custom, $inner, $base);
869                { ($($lhs)*), ($($rhs)*) $(, $($opt),*)? };
870            }
871        )*
872    };
873
874    (
875        @impl[PartialEq]; ({$core:ident, $alloc:ident}, $spec:ty, $custom:ty, $inner:ty, $base:ident);
876        { ($($lhs:tt)*), ($($rhs:tt)*) };
877    ) => {
878        impl $core::cmp::PartialEq<
879            $crate::impl_cmp_for_slice!(@type; ({$core, $alloc}, $custom, $inner); { $($rhs)* })
880        > for $crate::impl_cmp_for_slice!(@type; ({$core, $alloc}, $custom, $inner); { $($lhs)* })
881        {
882            #[inline]
883            fn eq(&self, other: &$crate::impl_cmp_for_slice!(@type; ({$core, $alloc}, $custom, $inner); { $($rhs)* })) -> bool {
884                $crate::impl_cmp_for_slice!(@cmp_fn[PartialEq]; ($custom, $inner, $base))(
885                    $crate::impl_cmp_for_slice!(@expr[$base]; ({$core, $alloc}, $spec, $custom, $inner); { $($lhs)* }; self),
886                    $crate::impl_cmp_for_slice!(@expr[$base]; ({$core, $alloc}, $spec, $custom, $inner); { $($rhs)* }; other),
887                )
888            }
889        }
890    };
891    (
892        @impl[PartialEq]; ({$core:ident, $alloc:ident}, $spec:ty, $custom:ty, $inner:ty, $base:ident);
893        { ($($lhs:tt)*), ($($rhs:tt)*), rev };
894    ) => {
895        impl $core::cmp::PartialEq<
896            $crate::impl_cmp_for_slice!(@type; ({$core, $alloc}, $custom, $inner); { $($rhs)* })
897        > for $crate::impl_cmp_for_slice!(@type; ({$core, $alloc}, $custom, $inner); { $($lhs)* })
898        {
899            #[inline]
900            fn eq(&self, other: &$crate::impl_cmp_for_slice!(@type; ({$core, $alloc}, $custom, $inner); { $($rhs)* })) -> bool {
901                $crate::impl_cmp_for_slice!(@cmp_fn[PartialEq]; ($custom, $inner, $base))(
902                    $crate::impl_cmp_for_slice!(@expr[$base]; ({$core, $alloc}, $spec, $custom, $inner); { $($lhs)* }; self),
903                    $crate::impl_cmp_for_slice!(@expr[$base]; ({$core, $alloc}, $spec, $custom, $inner); { $($rhs)* }; other),
904                )
905            }
906        }
907        impl $core::cmp::PartialEq<
908            $crate::impl_cmp_for_slice!(@type; ({$core, $alloc}, $custom, $inner); { $($lhs)* })
909        > for $crate::impl_cmp_for_slice!(@type; ({$core, $alloc}, $custom, $inner); { $($rhs)* })
910        {
911            #[inline]
912            fn eq(&self, other: &$crate::impl_cmp_for_slice!(@type; ({$core, $alloc}, $custom, $inner); { $($lhs)* })) -> bool {
913                $crate::impl_cmp_for_slice!(@cmp_fn[PartialEq]; ($custom, $inner, $base))(
914                    $crate::impl_cmp_for_slice!(@expr[$base]; ({$core, $alloc}, $spec, $custom, $inner); { $($rhs)* }; self),
915                    $crate::impl_cmp_for_slice!(@expr[$base]; ({$core, $alloc}, $spec, $custom, $inner); { $($lhs)* }; other),
916                )
917            }
918        }
919    };
920    (
921        @impl[PartialOrd]; ({$core:ident, $alloc:ident}, $spec:ty, $custom:ty, $inner:ty, $base:ident);
922        { ($($lhs:tt)*), ($($rhs:tt)*) };
923    ) => {
924        impl $core::cmp::PartialOrd<
925            $crate::impl_cmp_for_slice!(@type; ({$core, $alloc}, $custom, $inner); { $($rhs)* })
926        > for $crate::impl_cmp_for_slice!(@type; ({$core, $alloc}, $custom, $inner); { $($lhs)* })
927        {
928            #[inline]
929            fn partial_cmp(&self, other: &$crate::impl_cmp_for_slice!(@type; ({$core, $alloc}, $custom, $inner); { $($rhs)* }))
930                -> $core::option::Option<$core::cmp::Ordering>
931            {
932                $crate::impl_cmp_for_slice!(@cmp_fn[PartialOrd]; ($custom, $inner, $base))(
933                    $crate::impl_cmp_for_slice!(@expr[$base]; ({$core, $alloc}, $spec, $custom, $inner); { $($lhs)* }; self),
934                    $crate::impl_cmp_for_slice!(@expr[$base]; ({$core, $alloc}, $spec, $custom, $inner); { $($rhs)* }; other),
935                )
936            }
937        }
938    };
939    (
940        @impl[PartialOrd]; ({$core:ident, $alloc:ident}, $spec:ty, $custom:ty, $inner:ty, $base:ident);
941        { ($($lhs:tt)*), ($($rhs:tt)*), rev };
942    ) => {
943        impl $core::cmp::PartialOrd<
944            $crate::impl_cmp_for_slice!(@type; ({$core, $alloc}, $custom, $inner); { $($rhs)* })
945        > for $crate::impl_cmp_for_slice!(@type; ({$core, $alloc}, $custom, $inner); { $($lhs)* })
946        {
947            #[inline]
948            fn partial_cmp(&self, other: &$crate::impl_cmp_for_slice!(@type; ({$core, $alloc}, $custom, $inner); { $($rhs)* }))
949                -> $core::option::Option<$core::cmp::Ordering>
950            {
951                $crate::impl_cmp_for_slice!(@cmp_fn[PartialOrd]; ($custom, $inner, $base))(
952                    $crate::impl_cmp_for_slice!(@expr[$base]; ({$core, $alloc}, $spec, $custom, $inner); { $($lhs)* }; self),
953                    $crate::impl_cmp_for_slice!(@expr[$base]; ({$core, $alloc}, $spec, $custom, $inner); { $($rhs)* }; other),
954                )
955            }
956        }
957        impl $core::cmp::PartialOrd<
958            $crate::impl_cmp_for_slice!(@type; ({$core, $alloc}, $custom, $inner); { $($lhs)* })
959        > for $crate::impl_cmp_for_slice!(@type; ({$core, $alloc}, $custom, $inner); { $($rhs)* })
960        {
961            #[inline]
962            fn partial_cmp(&self, other: &$crate::impl_cmp_for_slice!(@type; ({$core, $alloc}, $custom, $inner); { $($lhs)* }))
963                -> $core::option::Option<$core::cmp::Ordering>
964            {
965                $crate::impl_cmp_for_slice!(@cmp_fn[PartialOrd]; ($custom, $inner, $base))(
966                    $crate::impl_cmp_for_slice!(@expr[$base]; ({$core, $alloc}, $spec, $custom, $inner); { $($rhs)* }; self),
967                    $crate::impl_cmp_for_slice!(@expr[$base]; ({$core, $alloc}, $spec, $custom, $inner); { $($lhs)* }; other),
968                )
969            }
970        }
971    };
972
973    (@type; ({$core:ident, $alloc:ident}, $custom:ty, $inner:ty); { {Custom} }) => { $custom };
974    (@type; ({$core:ident, $alloc:ident}, $custom:ty, $inner:ty); { &{Custom} }) => { &$custom };
975    (@type; ({$core:ident, $alloc:ident}, $custom:ty, $inner:ty); { Cow<{Custom}> }) => { $alloc::borrow::Cow<'_, $custom> };
976    (@type; ({$core:ident, $alloc:ident}, $custom:ty, $inner:ty); { {Inner} }) => { $inner };
977    (@type; ({$core:ident, $alloc:ident}, $custom:ty, $inner:ty); { &{Inner} }) => { &$inner };
978    (@type; ({$core:ident, $alloc:ident}, $custom:ty, $inner:ty); { Cow<{Inner}> }) => { $alloc::borrow::Cow<'_, $inner> };
979    (@type; ({$core:ident, $alloc:ident}, $custom:ty, $inner:ty); { $ty:ty }) => { $ty };
980
981    (@cmp_fn[PartialEq]; ($custom:ty, $inner:ty, Inner)) => { <$inner as core::cmp::PartialEq<$inner>>::eq };
982    (@cmp_fn[PartialEq]; ($custom:ty, $inner:ty, Custom)) => { <$custom as core::cmp::PartialEq<$custom>>::eq };
983    (@cmp_fn[PartialOrd]; ($custom:ty, $inner:ty, Inner)) => { <$inner as core::cmp::PartialOrd<$inner>>::partial_cmp };
984    (@cmp_fn[PartialOrd]; ($custom:ty, $inner:ty, Custom)) => { <$custom as core::cmp::PartialOrd<$custom>>::partial_cmp };
985
986    (@expr[Inner]; ({$core:ident, $alloc:ident}, $spec:ty, $custom:ty, $inner:ty); { {Custom} }; $expr:expr) => {
987        <$spec as $crate::SliceSpec>::as_inner($expr)
988    };
989    (@expr[Inner]; ({$core:ident, $alloc:ident}, $spec:ty, $custom:ty, $inner:ty); { &{Custom} }; $expr:expr) => {
990        <$spec as $crate::SliceSpec>::as_inner(*$expr)
991    };
992    (@expr[Inner]; ({$core:ident, $alloc:ident}, $spec:ty, $custom:ty, $inner:ty); { Cow<{Custom}> }; $expr:expr) => {
993        <$spec as $crate::SliceSpec>::as_inner(&**$expr)
994    };
995    (@expr[Inner]; ({$core:ident, $alloc:ident}, $spec:ty, $custom:ty, $inner:ty); { {Inner} }; $expr:expr) => {
996        $expr
997    };
998    (@expr[Inner]; ({$core:ident, $alloc:ident}, $spec:ty, $custom:ty, $inner:ty); { &{Inner} }; $expr:expr) => {
999        *$expr
1000    };
1001    (@expr[Inner]; ({$core:ident, $alloc:ident}, $spec:ty, $custom:ty, $inner:ty); { Cow<{Inner}> }; $expr:expr) => {
1002        &**$expr
1003    };
1004    (@expr[Inner]; ({$core:ident, $alloc:ident}, $spec:ty, $custom:ty, $inner:ty); { $ty:ty }; $expr:expr) => {
1005        $core::convert::AsRef::<$inner>::as_ref($expr)
1006    };
1007    (@expr[Custom]; ({$core:ident, $alloc:ident}, $spec:ty, $custom:ty, $inner:ty); { {Custom} }; $expr:expr) => {
1008        $expr
1009    };
1010    (@expr[Custom]; ({$core:ident, $alloc:ident}, $spec:ty, $custom:ty, $inner:ty); { &{Custom} }; $expr:expr) => {
1011        *$expr
1012    };
1013    (@expr[Custom]; ({$core:ident, $alloc:ident}, $spec:ty, $custom:ty, $inner:ty); { Cow<{Custom}> }; $expr:expr) => {
1014        &**$expr
1015    };
1016    (@expr[Custom]; ({$core:ident, $alloc:ident}, $spec:ty, $custom:ty, $inner:ty); { $ty:ty }; $expr:expr) => {
1017        $core::convert::AsRef::<$custom>::as_ref($expr)
1018    };
1019
1020    ($($rest:tt)*) => {
1021        compile_error!(stringify!($($rest)*));
1022    };
1023}