1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
//! Macros.

macro_rules! impl_cmp {
    ($ty_common:ty, $ty_lhs:ty, $ty_rhs:ty) => {
        impl PartialEq<$ty_rhs> for $ty_lhs {
            fn eq(&self, o: &$ty_rhs) -> bool {
                <$ty_common as PartialEq<$ty_common>>::eq(self.as_ref(), o.as_ref())
            }
        }
        impl PartialEq<$ty_lhs> for $ty_rhs {
            fn eq(&self, o: &$ty_lhs) -> bool {
                <$ty_common as PartialEq<$ty_common>>::eq(self.as_ref(), o.as_ref())
            }
        }
        impl PartialOrd<$ty_rhs> for $ty_lhs {
            fn partial_cmp(&self, o: &$ty_rhs) -> Option<std::cmp::Ordering> {
                <$ty_common as PartialOrd<$ty_common>>::partial_cmp(self.as_ref(), o.as_ref())
            }
        }
        impl PartialOrd<$ty_lhs> for $ty_rhs {
            fn partial_cmp(&self, o: &$ty_lhs) -> Option<std::cmp::Ordering> {
                <$ty_common as PartialOrd<$ty_common>>::partial_cmp(self.as_ref(), o.as_ref())
            }
        }
    };
}

/// Implement std traits for the given URI / IRI types.
macro_rules! impl_std_traits {
    (
        source: {
            owned: $owned:ty,
            slice: $slice:ty,
            error: $ty_error:ty,
        },
        target: [
        $(
            {
                owned: $target_owned:ty,
                slice: $target_slice:ty,
            }
        ),* $(,)?
        ],
    ) => {
        $(
            impl From<$owned> for $target_owned {
                fn from(s: $owned) -> $target_owned {
                    unsafe {
                        // This should be safe.
                        // Caller of `impl_std_traits` is responsible for that.
                        <$target_owned>::new_unchecked(s.into())
                    }
                }
            }

            impl<'a> From<&'a $slice> for &'a $target_slice {
                fn from(s: &'a $slice) -> &'a $target_slice {
                    s.as_ref()
                }
            }

            impl std::convert::TryFrom<$target_owned> for $owned {
                type Error = $ty_error;

                fn try_from(v: $target_owned) -> Result<Self, Self::Error> {
                    Self::try_from(Into::<String>::into(v))
                }
            }

            impl<'a> std::convert::TryFrom<&'a $target_slice> for &'a $slice {
                type Error = $ty_error;

                fn try_from(v: &'a $target_slice) -> Result<Self, Self::Error> {
                    Self::try_from(AsRef::<str>::as_ref(v))
                }
            }

            impl AsRef<$target_slice> for $owned {
                fn as_ref(&self) -> &$target_slice {
                    AsRef::<$slice>::as_ref(self).as_ref()
                }
            }

            impl AsRef<$target_slice> for $slice {
                fn as_ref(&self) -> &$target_slice {
                    unsafe {
                        // This should be safe.
                        // Caller of `impl_std_traits` is responsible for that.
                        <$target_slice>::new_unchecked(self.as_ref())
                    }
                }
            }

            impl_cmp!($target_slice, $owned, $target_slice);
            impl_cmp!($target_slice, $owned, &$target_slice);
            impl_cmp!($target_slice, $owned, std::borrow::Cow<'_, $target_slice>);

            impl_cmp!($target_slice, $slice, $target_slice);
            impl_cmp!($target_slice, $slice, &$target_slice);
            impl_cmp!($target_slice, $slice, $target_owned);
            impl_cmp!($target_slice, $slice, std::borrow::Cow<'_, $target_slice>);
            impl_cmp!($target_slice, &$slice, $target_slice);
            impl_cmp!($target_slice, &$slice, $target_owned);
            impl_cmp!($target_slice, &$slice, std::borrow::Cow<'_, $target_slice>);
        )*
    };
}