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
128
129
130
131
132
133
macro_rules! pub_bitflags_display {
    ($flags:ident, $ty:ty, $name:ident = $value:literal) => {
        bitflags! {
            #[derive(Default)]
            pub struct $flags: $ty {
                const $name = $value;
            }
        }
        
        impl ::std::fmt::Display for $flags {
            fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
                if self.contains($flags::$name) {
                    write!(f, stringify!($name))?;
                }
                Ok(())
            }
        }
        
        impl ::std::str::FromStr for $flags {
            type Err = ();
        
            fn from_str(s: &str) -> Result<$flags, Self::Err> {
                fn flag(input: &str) -> ::nom::IResult<&str, $flags, ()> {
                    ::nom::combinator::value($flags::$name, ::nom::bytes::complete::tag(stringify!($name)))
                    (input)
                }

                let (unconsumed, flags_value) = ::nom::combinator::map(::nom::combinator::opt(
                    flag,
                ), |m| m.unwrap_or($flags::empty()))(s).map_err(|_: ::nom::Err<()>| ())?;
                if !unconsumed.is_empty() { return Err(()); }
                Ok(flags_value)
            }
        }
    };
    ($flags:ident, $ty:ty, $($name:ident = $value:literal),+) => {
        bitflags! {
            #[derive(Default)]
            pub struct $flags: $ty {
                $(const $name = $value;)*
            }
        }
        
        impl ::std::fmt::Display for $flags {
            fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
                let mut start = true;
                $(
                    if self.contains($flags::$name) {
                        if start {
                            #[allow(unused_assignments)]
                            start = false;
                        } else {
                            write!(f, " ")?;
                        }
                        write!(f, stringify!($name))?;
                    }
                )*
                Ok(())
            }
        }
        
        impl ::std::str::FromStr for $flags {
            type Err = ();
        
            fn from_str(s: &str) -> Result<$flags, Self::Err> {
                fn flag(input: &str) -> ::nom::IResult<&str, $flags, ()> {
                    ::nom::branch::alt((
                        $(
                            ::nom::combinator::value($flags::$name, ::nom::bytes::complete::tag(stringify!($name)))
                        ),*
                    ))(input)
                }

                let (unconsumed, flags_value) = ::nom::combinator::map(::nom::combinator::opt(::nom::combinator::map(::nom::sequence::pair(
                    flag,
                    ::nom::multi::fold_many0(::nom::sequence::preceded(::nom::bytes::complete::take_while(char::is_whitespace), flag), $flags::empty(), |a, v| a | v)
                ), |(a, b)| a | b)), |m| m.unwrap_or($flags::empty()))(s).map_err(|_: ::nom::Err<()>| ())?;
                if !unconsumed.is_empty() { return Err(()); }
                Ok(flags_value)
            }
        }
    };
    ($flags:ident, $ty:ty, $([$($name:ident = $value:literal),+]),+) => {
        bitflags! {
            #[derive(Default)]
            pub struct $flags: $ty {
                $($(const $name = $value;)+)+
            }
        }
        
        impl ::std::fmt::Display for $flags {
            fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
                let mut start = true;
                $($(
                    if self.contains($flags::$name) {
                        if start {
                            #[allow(unused_assignments)]
                            start = false;
                        } else {
                            write!(f, " ")?;
                        }
                        write!(f, stringify!($name))?;
                    }
                )+)+
                Ok(())
            }
        }
        
        impl ::std::str::FromStr for $flags {
            type Err = ();
        
            fn from_str(s: &str) -> Result<$flags, Self::Err> {
                fn flag(input: &str) -> ::nom::IResult<&str, $flags, ()> {
                    ::nom::branch::alt((
                        $(::nom::branch::alt((
                            $(
                                ::nom::combinator::value($flags::$name, ::nom::bytes::complete::tag(stringify!($name)))
                            ),+
                        ))),+
                    ))(input)
                }

                let (unconsumed, flags_value) = ::nom::combinator::map(::nom::combinator::opt(::nom::combinator::map(::nom::sequence::pair(
                    flag,
                    ::nom::multi::fold_many0(::nom::sequence::preceded(::nom::bytes::complete::take_while(char::is_whitespace), flag), $flags::empty(), |a, v| a | v)
                ), |(a, b)| a | b)), |m| m.unwrap_or($flags::empty()))(s).map_err(|_: ::nom::Err<()>| ())?;
                if !unconsumed.is_empty() { return Err(()); }
                Ok(flags_value)
            }
        }
    }
}