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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
macro_rules! result {
    ($error:expr, $good:expr) => {
        match $error {
            $crate::sys::Error(0) => Ok($good),

            $crate::sys::Error(err) => {
                Err($crate::Error::from_c(err).unwrap_or($crate::Error::Bindings))
            }
        }
    };

    ($error:expr) => {
        result!($error, ())
    };
}

macro_rules! c_enum {
    (
        $(#[$enum_meta:meta])*
        $vis:vis enum $EnumName:ident: $Primitive:ident {
            $(
                $(#[$variant_meta:meta])*
                $Variant:ident $(= $Value:expr)?
            ),*
            $(,)?
        }
    ) => {
        $(#[$enum_meta])*
        #[repr($Primitive)]
        $vis enum $EnumName {
            $(
                $(#[$variant_meta])*
                $Variant $(= $Value)?
            ),*
        }

        impl $EnumName {
            /// Converts this enum to its primitive value.
            #[allow(dead_code)]
            pub(crate) fn to_primitive(self) -> $Primitive {
                self as $Primitive
            }

            /// Converts a primitive value to this enum.
            #[allow(dead_code)]
            pub(crate) fn from_primitive(primitive: $Primitive) -> Option<Self> {
                match primitive {
                    $( _ if primitive == Self::$Variant as $Primitive => Some(Self::$Variant) ,)*
                    _ => None,
                }
            }

            /// Converts this to its C value.
            #[allow(dead_code)]
            pub(crate) fn to_c(self) -> libc::c_int {
                self as $Primitive as libc::c_int
            }

            /// Converts from a C value into this.
            #[allow(dead_code)]
            pub(crate) fn from_c(c: impl core::convert::TryInto<$Primitive>) -> Option<Self> {
                if let Ok(v) = c.try_into() {
                    Self::from_primitive(v)
                } else {
                    None
                }
            }
        }
    };
}

macro_rules! c_enum_big {
    (
        $(#[$enum_meta:meta])*
        $vis:vis enum $EnumName:ident: $Primitive:ident {
            @Start = $StartVariant:ident,
            @End   = $EndVariant:ident,
            $(
                $(#[$variant_meta:meta])*
                $Variant:ident $(= $Value:expr)?
            ),*
            $(,)?
        }
    ) => {
        $(#[$enum_meta])*
        #[repr($Primitive)]
        $vis enum $EnumName {
            $(
                $(#[$variant_meta])*
                $Variant $(= $Value)?
            ),*
        }

        impl $EnumName {
            /// Converts this enum to its primitive value.
            #[allow(dead_code)]
            pub(crate) fn to_primitive(self) -> $Primitive {
                self as $Primitive
            }

            /// Converts a primitive value to this enum.
            #[allow(dead_code)]
            pub(crate) fn from_primitive(primitive: $Primitive) -> Option<Self> {
                if primitive < $EnumName::$StartVariant as $Primitive || primitive >= $EnumName::$EndVariant as $Primitive {
                    return None;
                }
                Some(unsafe { core::mem::transmute::<$Primitive, $EnumName>(primitive) })
            }

            /// Converts this to its C value.
            #[allow(dead_code)]
            pub(crate) fn to_c(self) -> libc::c_int {
                self as $Primitive as libc::c_int
            }

            /// Converts from a C value into this.
            #[allow(dead_code)]
            pub(crate) fn from_c(c: impl core::convert::TryInto<$Primitive>) -> Option<Self> {
                if let Ok(v) = c.try_into() {
                    Self::from_primitive(v)
                } else {
                    None
                }
            }
        }
    };
}