Skip to content

Commit e3be05f

Browse files
authored
Merge pull request #2 from bitflags/feat/display
Add support for Display and FromStr
2 parents 8b3cff9 + 046c3ee commit e3be05f

File tree

8 files changed

+100
-8
lines changed

8 files changed

+100
-8
lines changed

README.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,17 @@ extern crate bitflags;
2626
extern crate bitflags_derive;
2727

2828
bitflags! {
29-
#[derive(FlagsDebug)]
30-
struct Flags: u8 {
29+
#[derive(FlagsDisplay, FlagsFromStr)]
30+
struct MyFlags: u8 {
3131
const A = 1;
3232
const B = 1 << 1;
3333
const C = 1 << 2;
3434
}
3535
}
3636

37-
// The regular `#[derive(Debug)]` would produce "Flags(A | B)" here
38-
assert_eq!("A | B", format!("{:?}", Flags::A | Flags::B));
37+
let flags = "A | B".parse::<MyFlags>()?;
38+
39+
assert_eq!("A | B", flags.to_string());
3940
```
4041

4142
See [the docs](https://docs.rs/bitflags-derive) for details on all supported attributes.

macros/src/display.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
use proc_macro2::TokenStream;
2+
3+
pub(crate) fn expand(item: syn::DeriveInput) -> Result<TokenStream, syn::Error> {
4+
let ident = item.ident;
5+
let (impl_generics, ty_generics, where_clause) = item.generics.split_for_impl();
6+
7+
Ok(
8+
quote!(impl #impl_generics bitflags_derive::__private::core::fmt::Display for #ident #ty_generics #where_clause {
9+
fn fmt(&self, f: &mut bitflags_derive::__private::core::fmt::Formatter) -> bitflags_derive::__private::core::fmt::Result {
10+
bitflags_derive::__private::bitflags::parser::to_writer(self, f)
11+
}
12+
}),
13+
)
14+
}

macros/src/from_str.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
use proc_macro2::TokenStream;
2+
3+
pub(crate) fn expand(item: syn::DeriveInput) -> Result<TokenStream, syn::Error> {
4+
let ident = item.ident;
5+
let (impl_generics, ty_generics, where_clause) = item.generics.split_for_impl();
6+
7+
Ok(
8+
quote!(impl #impl_generics bitflags_derive::__private::core::str::FromStr for #ident #ty_generics #where_clause {
9+
type Err = bitflags_derive::__private::bitflags::parser::ParseError;
10+
11+
fn from_str(v: &str) -> bitflags_derive::__private::core::result::Result<Self, bitflags_derive::__private::bitflags::parser::ParseError> {
12+
bitflags_derive::__private::bitflags::parser::from_str(v)
13+
}
14+
}),
15+
)
16+
}

macros/src/lib.rs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@ extern crate proc_macro;
1212
extern crate quote;
1313

1414
mod debug;
15+
mod display;
16+
mod from_str;
1517

1618
/**
17-
Derive [`Debug`](https://doc.rust-lang.org/std/fmt/trait.Debug.html) for a flags type.
19+
Derive [`Debug`](https://doc.rust-lang.org/std/fmt/trait.Debug.html).
1820
1921
This macro will use [`to_writer`](https://docs.rs/bitflags/latest/bitflags/parser/fn.to_writer.html) to
2022
format flags values.
@@ -24,6 +26,28 @@ pub fn derive_bitflags_debug(item: proc_macro::TokenStream) -> proc_macro::Token
2426
debug::expand(syn::parse_macro_input!(item as syn::DeriveInput)).unwrap_or_compile_error()
2527
}
2628

29+
/**
30+
Derive [`Display`](https://doc.rust-lang.org/std/fmt/trait.Display.html).
31+
32+
This macro will use [`to_writer`](https://docs.rs/bitflags/latest/bitflags/parser/fn.to_writer.html) to
33+
format flags values.
34+
*/
35+
#[proc_macro_derive(FlagsDisplay)]
36+
pub fn derive_bitflags_display(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
37+
display::expand(syn::parse_macro_input!(item as syn::DeriveInput)).unwrap_or_compile_error()
38+
}
39+
40+
/**
41+
Derive [`FromStr`](https://doc.rust-lang.org/std/str/trait.FromStr.html).
42+
43+
This macro will use [`from_str`](https://docs.rs/bitflags/latest/bitflags/parser/fn.from_str.html) to
44+
parse flags values.
45+
*/
46+
#[proc_macro_derive(FlagsFromStr)]
47+
pub fn derive_bitflags_from_str(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
48+
from_str::expand(syn::parse_macro_input!(item as syn::DeriveInput)).unwrap_or_compile_error()
49+
}
50+
2751
trait ResultExt {
2852
fn unwrap_or_compile_error(self) -> proc_macro::TokenStream;
2953
}

src/lib.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,27 @@ extern crate bitflags;
2222
#[macro_use]
2323
extern crate bitflags_derive;
2424
25+
# fn main() -> Result<(), bitflags::parser::ParseError> {
2526
bitflags! {
26-
#[derive(FlagsDebug)]
27-
struct Flags: u8 {
27+
#[derive(FlagsDisplay, FlagsFromStr)]
28+
struct MyFlags: u8 {
2829
const A = 1;
2930
const B = 1 << 1;
3031
const C = 1 << 2;
3132
}
3233
}
33-
# fn main() {}
34+
35+
let flags = "A | B".parse::<MyFlags>()?;
36+
37+
assert_eq!("A | B", flags.to_string());
38+
# Ok(())
39+
# }
3440
```
41+
42+
These derives work for any type that implements the [`Flags`](https://docs.rs/bitflags/latest/bitflags/trait.Flags.html) trait.
3543
*/
3644

45+
#![no_std]
3746
#![deny(missing_docs)]
3847

3948
#[doc(inline)]

tests/ui/src/display.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#[test]
2+
fn derive_display() {
3+
bitflags! {
4+
#[derive(FlagsDisplay)]
5+
struct Flags: u8 {
6+
const A = 1;
7+
const B = 1 << 1;
8+
const C = 1 << 2;
9+
}
10+
}
11+
12+
assert_eq!("A | B", (Flags::A | Flags::B).to_string());
13+
}

tests/ui/src/from_str.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#[test]
2+
fn derive_from_str() {
3+
bitflags! {
4+
#[derive(FlagsFromStr, PartialEq, Eq, Debug)]
5+
struct Flags: u8 {
6+
const A = 1;
7+
const B = 1 << 1;
8+
const C = 1 << 2;
9+
}
10+
}
11+
12+
assert_eq!("A | B".parse::<Flags>().unwrap(), Flags::A | Flags::B);
13+
}

tests/ui/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,5 @@ extern crate bitflags;
77
extern crate bitflags_derive;
88

99
mod debug;
10+
mod display;
11+
mod from_str;

0 commit comments

Comments
 (0)