Skip to content

Commit 3dfe0b2

Browse files
committed
tidy up hex flag parsing and formatting
1 parent 9d2cf9e commit 3dfe0b2

5 files changed

Lines changed: 61 additions & 46 deletions

File tree

examples/fmt.rs

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,40 +2,40 @@
22
33
use core::{fmt, str};
44

5-
fn main() -> Result<(), bitflags::parser::ParseError> {
6-
bitflags::bitflags! {
7-
// You can `#[derive]` the `Debug` trait, but implementing it manually
8-
// can produce output like `A | B` instead of `Flags(A | B)`.
9-
// #[derive(Debug)]
10-
#[derive(PartialEq, Eq)]
11-
pub struct Flags: u32 {
12-
const A = 1;
13-
const B = 2;
14-
const C = 4;
15-
const D = 8;
16-
}
5+
bitflags::bitflags! {
6+
// You can `#[derive]` the `Debug` trait, but implementing it manually
7+
// can produce output like `A | B` instead of `Flags(A | B)`.
8+
// #[derive(Debug)]
9+
#[derive(PartialEq, Eq)]
10+
pub struct Flags: u32 {
11+
const A = 1;
12+
const B = 2;
13+
const C = 4;
14+
const D = 8;
1715
}
16+
}
1817

19-
impl fmt::Debug for Flags {
20-
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
21-
fmt::Debug::fmt(&self.0, f)
22-
}
18+
impl fmt::Debug for Flags {
19+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
20+
bitflags::parser::to_writer(self, f)
2321
}
22+
}
2423

25-
impl fmt::Display for Flags {
26-
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
27-
fmt::Display::fmt(&self.0, f)
28-
}
24+
impl fmt::Display for Flags {
25+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
26+
bitflags::parser::to_writer(self, f)
2927
}
28+
}
3029

31-
impl str::FromStr for Flags {
32-
type Err = bitflags::parser::ParseError;
30+
impl str::FromStr for Flags {
31+
type Err = bitflags::parser::ParseError;
3332

34-
fn from_str(flags: &str) -> Result<Self, Self::Err> {
35-
Ok(Self(flags.parse()?))
36-
}
33+
fn from_str(flags: &str) -> Result<Self, Self::Err> {
34+
bitflags::parser::from_str(flags)
3735
}
36+
}
3837

38+
fn main() -> Result<(), bitflags::parser::ParseError> {
3939
let flags = Flags::A | Flags::B;
4040

4141
println!("{}", flags);

src/external/arbitrary.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
33
use crate::Flags;
44

5+
/// Get a random known flags value.
56
pub fn arbitrary<'a, B: Flags>(
67
u: &mut arbitrary::Unstructured<'a>,
78
) -> arbitrary::Result<B>

src/lib.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -660,9 +660,6 @@ macro_rules! bitflags {
660660
non_upper_case_globals
661661
)]
662662
const _: () = {
663-
// NOTE: We don't need to check `__is_primitive` here because we don't derive
664-
// traits on the user's behalf
665-
666663
__impl_public_bitflags! {
667664
$BitFlags: $T {
668665
$(

src/parser.rs

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
2929
#![allow(clippy::let_unit_value)]
3030

31-
use core::fmt::{self, Write, LowerHex};
31+
use core::fmt::{self, Write};
3232

3333
use crate::{Flags, Bits};
3434

@@ -38,7 +38,7 @@ use crate::{Flags, Bits};
3838
/// as a hex number.
3939
pub fn to_writer<B: Flags>(flags: &B, mut writer: impl Write) -> Result<(), fmt::Error>
4040
where
41-
B::Bits: LowerHex,
41+
B::Bits: WriteHex,
4242
{
4343
// A formatter for bitflags that produces text output like:
4444
//
@@ -67,7 +67,8 @@ where
6767
writer.write_str(" | ")?;
6868
}
6969

70-
write!(writer, "{:#x}", remaining)?;
70+
writer.write_str("0x")?;
71+
remaining.write_hex(writer)?;
7172
}
7273

7374
fmt::Result::Ok(())
@@ -77,7 +78,7 @@ pub(crate) struct AsDisplay<'a, B>(pub(crate) &'a B);
7778

7879
impl<'a, B: Flags> fmt::Display for AsDisplay<'a, B>
7980
where
80-
B::Bits: LowerHex,
81+
B::Bits: WriteHex,
8182
{
8283
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8384
to_writer(self.0, f)
@@ -89,14 +90,12 @@ where
8990
/// This function will fail on unknown flags rather than ignore them.
9091
pub fn from_str<B: Flags>(input: &str) -> Result<B, ParseError>
9192
where
92-
B::Bits: FromHex,
93+
B::Bits: ParseHex,
9394
{
94-
let input = input.trim();
95-
9695
let mut parsed_flags = B::empty();
9796

9897
// If the input is empty then return an empty set of flags
99-
if input.is_empty() {
98+
if input.trim().is_empty() {
10099
return Ok(parsed_flags);
101100
}
102101

@@ -111,7 +110,7 @@ where
111110
// If the flag starts with `0x` then it's a hex number
112111
// Parse it directly to the underlying bits type
113112
let parsed_flag = if let Some(flag) = flag.strip_prefix("0x") {
114-
let bits = <B::Bits>::from_hex(flag).map_err(|_| ParseError::invalid_hex_flag(flag))?;
113+
let bits = <B::Bits>::parse_hex(flag).map_err(|_| ParseError::invalid_hex_flag(flag))?;
115114

116115
B::from_bits_retain(bits)
117116
}
@@ -128,10 +127,16 @@ where
128127
Ok(parsed_flags)
129128
}
130129

130+
/// Encode a value as a hex string.
131+
pub trait WriteHex {
132+
/// Write the value as hex.
133+
fn write_hex<W: fmt::Write>(&self, writer: W) -> fmt::Result;
134+
}
135+
131136
/// Parse a value from a number encoded as a hex string.
132-
pub trait FromHex {
133-
/// Perform the conversion.
134-
fn from_hex(input: &str) -> Result<Self, ParseError>
137+
pub trait ParseHex {
138+
/// Parse the value from hex.
139+
fn parse_hex(input: &str) -> Result<Self, ParseError>
135140
where
136141
Self: Sized;
137142
}

src/traits.rs

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
use core::ops::{BitAnd, BitOr, BitXor, Not};
1+
use core::{fmt, ops::{BitAnd, BitOr, BitXor, Not}};
22

3-
use crate::{parser::{ParseError, FromHex}, iter};
3+
use crate::{parser::{ParseError, ParseHex, WriteHex}, iter};
44

55
/// Metadata for an individual flag.
66
pub struct Flag<B> {
@@ -271,18 +271,30 @@ macro_rules! impl_bits {
271271
const ALL: $i = <$u>::MAX as $i;
272272
}
273273

274-
impl FromHex for $u {
275-
fn from_hex(input: &str) -> Result<Self, ParseError> {
274+
impl ParseHex for $u {
275+
fn parse_hex(input: &str) -> Result<Self, ParseError> {
276276
<$u>::from_str_radix(input, 16).map_err(|_| ParseError::invalid_hex_flag(input))
277277
}
278278
}
279279

280-
impl FromHex for $i {
281-
fn from_hex(input: &str) -> Result<Self, ParseError> {
280+
impl ParseHex for $i {
281+
fn parse_hex(input: &str) -> Result<Self, ParseError> {
282282
<$i>::from_str_radix(input, 16).map_err(|_| ParseError::invalid_hex_flag(input))
283283
}
284284
}
285285

286+
impl WriteHex for $u {
287+
fn write_hex<W: fmt::Write>(&self, mut writer: W) -> fmt::Result {
288+
write!(writer, "{:x}", self)
289+
}
290+
}
291+
292+
impl WriteHex for $i {
293+
fn write_hex<W: fmt::Write>(&self, mut writer: W) -> fmt::Result {
294+
write!(writer, "{:x}", self)
295+
}
296+
}
297+
286298
impl Primitive for $i {}
287299
impl Primitive for $u {}
288300
)*

0 commit comments

Comments
 (0)