Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit c5f5f3b

Browse files
committed
Refactored FormattingOptions to use a bitmask for storing flags
1 parent 97f9171 commit c5f5f3b

File tree

2 files changed

+52
-54
lines changed

2 files changed

+52
-54
lines changed

library/core/src/fmt/mod.rs

Lines changed: 46 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -272,14 +272,11 @@ pub enum DebugAsHex {
272272
#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)]
273273
#[unstable(feature = "formatting_options", issue = "118117")]
274274
pub struct FormattingOptions {
275-
sign: Option<Sign>,
276-
sign_aware_zero_pad: bool,
277-
alternate: bool,
275+
flags: u32,
278276
fill: char,
279277
align: Option<Alignment>,
280278
width: Option<usize>,
281279
precision: Option<usize>,
282-
debug_as_hex: Option<DebugAsHex>,
283280
}
284281

285282
impl FormattingOptions {
@@ -296,14 +293,11 @@ impl FormattingOptions {
296293
#[unstable(feature = "formatting_options", issue = "118117")]
297294
pub const fn new() -> Self {
298295
Self {
299-
sign: None,
300-
sign_aware_zero_pad: false,
301-
alternate: false,
296+
flags: 0,
302297
fill: ' ',
303298
align: None,
304299
width: None,
305300
precision: None,
306-
debug_as_hex: None,
307301
}
308302
}
309303

@@ -317,15 +311,24 @@ impl FormattingOptions {
317311
/// - `-`: Currently not used
318312
#[unstable(feature = "formatting_options", issue = "118117")]
319313
pub const fn sign(&mut self, sign: Option<Sign>) -> &mut Self {
320-
self.sign = sign;
314+
self.flags = self.flags & !(1 << rt::Flag::SignMinus as u32 | 1 << rt::Flag::SignPlus as u32);
315+
match sign {
316+
None => {},
317+
Some(Sign::Plus) => self.flags |= 1 << rt::Flag::SignPlus as u32,
318+
Some(Sign::Minus) => self.flags |= 1 << rt::Flag::SignMinus as u32,
319+
}
321320
self
322321
}
323322
/// Sets or unsets the `0` flag.
324323
///
325324
/// This is used to indicate for integer formats that the padding to width should both be done with a 0 character as well as be sign-aware
326325
#[unstable(feature = "formatting_options", issue = "118117")]
327326
pub const fn sign_aware_zero_pad(&mut self, sign_aware_zero_pad: bool) -> &mut Self {
328-
self.sign_aware_zero_pad = sign_aware_zero_pad;
327+
if sign_aware_zero_pad {
328+
self.flags |= 1 << rt::Flag::SignAwareZeroPad as u32
329+
} else {
330+
self.flags &= !(1 << rt::Flag::SignAwareZeroPad as u32)
331+
}
329332
self
330333
}
331334
/// Sets or unsets the `#` flag.
@@ -338,7 +341,11 @@ impl FormattingOptions {
338341
/// - [`Binary`] - precedes the argument with a `0o`
339342
#[unstable(feature = "formatting_options", issue = "118117")]
340343
pub const fn alternate(&mut self, alternate: bool) -> &mut Self {
341-
self.alternate = alternate;
344+
if alternate {
345+
self.flags |= 1 << rt::Flag::Alternate as u32
346+
} else {
347+
self.flags &= !(1 << rt::Flag::Alternate as u32)
348+
}
342349
self
343350
}
344351
/// Sets the fill character.
@@ -390,24 +397,36 @@ impl FormattingOptions {
390397
/// hexadecimal or normal integers
391398
#[unstable(feature = "formatting_options", issue = "118117")]
392399
pub const fn debug_as_hex(&mut self, debug_as_hex: Option<DebugAsHex>) -> &mut Self {
393-
self.debug_as_hex = debug_as_hex;
400+
self.flags = self.flags & !(1 << rt::Flag::DebugUpperHex as u32 | 1 << rt::Flag::DebugLowerHex as u32);
401+
match debug_as_hex {
402+
None => {},
403+
Some(DebugAsHex::Upper) => self.flags |= 1 << rt::Flag::DebugUpperHex as u32,
404+
Some(DebugAsHex::Lower) => self.flags |= 1 << rt::Flag::DebugLowerHex as u32,
405+
}
394406
self
395407
}
396408

397409
/// Returns the current sign (the `+` or the `-` flag).
398410
#[unstable(feature = "formatting_options", issue = "118117")]
399411
pub const fn get_sign(&self) -> Option<Sign> {
400-
self.sign
412+
const SIGN_PLUS_BITFIELD: u32 = 1 << rt::Flag::SignPlus as u32;
413+
const SIGN_MINUS_BITFIELD: u32 = 1 << rt::Flag::SignMinus as u32;
414+
match self.flags & ((1 << rt::Flag::SignPlus as u32) | (1 << rt::Flag::SignMinus as u32)) {
415+
SIGN_PLUS_BITFIELD => Some(Sign::Plus),
416+
SIGN_MINUS_BITFIELD => Some(Sign::Minus),
417+
0 => None,
418+
_ => panic!("Invalid sign bits set in flags"),
419+
}
401420
}
402421
/// Returns the current `0` flag.
403422
#[unstable(feature = "formatting_options", issue = "118117")]
404423
pub const fn get_sign_aware_zero_pad(&self) -> bool {
405-
self.sign_aware_zero_pad
424+
self.flags & (1 << rt::Flag::SignAwareZeroPad as u32) != 0
406425
}
407426
/// Returns the current `#` flag.
408427
#[unstable(feature = "formatting_options", issue = "118117")]
409428
pub const fn get_alternate(&self) -> bool {
410-
self.alternate
429+
self.flags & (1 << rt::Flag::Alternate as u32) != 0
411430
}
412431
/// Returns the current fill character.
413432
#[unstable(feature = "formatting_options", issue = "118117")]
@@ -432,7 +451,14 @@ impl FormattingOptions {
432451
/// Returns the current precision.
433452
#[unstable(feature = "formatting_options", issue = "118117")]
434453
pub const fn get_debug_as_hex(&self) -> Option<DebugAsHex> {
435-
self.debug_as_hex
454+
const DEBUG_UPPER_BITFIELD: u32 = 1 << rt::Flag::DebugUpperHex as u32;
455+
const DEBUG_LOWER_BITFIELD: u32 = 1 << rt::Flag::DebugLowerHex as u32;
456+
match self.flags & ((1 << rt::Flag::DebugUpperHex as u32) | (1 << rt::Flag::DebugLowerHex as u32)) {
457+
DEBUG_UPPER_BITFIELD => Some(DebugAsHex::Upper),
458+
DEBUG_LOWER_BITFIELD => Some(DebugAsHex::Lower),
459+
0 => None,
460+
_ => panic!("Invalid hex debug bits set in flags"),
461+
}
436462
}
437463

438464
/// Creates a [`Formatter`] that writes its output to the given [`Write`] trait.
@@ -447,37 +473,13 @@ impl FormattingOptions {
447473
#[unstable(feature = "fmt_internals", reason = "internal to standard library", issue = "none")]
448474
/// Flags for formatting
449475
pub fn flags(&mut self, flags: u32) {
450-
self.sign = if flags & (1 << rt::Flag::SignPlus as u32) != 0 {
451-
Some(Sign::Plus)
452-
} else if flags & (1 << rt::Flag::SignMinus as u32) != 0 {
453-
Some(Sign::Minus)
454-
} else {
455-
None
456-
};
457-
self.alternate = (flags & (1 << rt::Flag::Alternate as u32)) != 0;
458-
self.sign_aware_zero_pad = (flags & (1 << rt::Flag::SignAwareZeroPad as u32)) != 0;
459-
self.debug_as_hex = if flags & (1 << rt::Flag::DebugLowerHex as u32) != 0 {
460-
Some(DebugAsHex::Lower)
461-
} else if flags & (1 << rt::Flag::DebugUpperHex as u32) != 0 {
462-
Some(DebugAsHex::Upper)
463-
} else {
464-
None
465-
};
476+
self.flags = flags
466477
}
467478
#[doc(hidden)]
468479
#[unstable(feature = "fmt_internals", reason = "internal to standard library", issue = "none")]
469480
/// Flags for formatting
470481
pub fn get_flags(&self) -> u32 {
471-
<bool as Into<u32>>::into(self.get_sign() == Some(Sign::Plus)) << rt::Flag::SignPlus as u32
472-
| <bool as Into<u32>>::into(self.get_sign() == Some(Sign::Minus))
473-
<< rt::Flag::SignMinus as u32
474-
| <bool as Into<u32>>::into(self.get_alternate()) << rt::Flag::Alternate as u32
475-
| <bool as Into<u32>>::into(self.get_sign_aware_zero_pad())
476-
<< rt::Flag::SignAwareZeroPad as u32
477-
| <bool as Into<u32>>::into(self.debug_as_hex == Some(DebugAsHex::Lower))
478-
<< rt::Flag::DebugLowerHex as u32
479-
| <bool as Into<u32>>::into(self.debug_as_hex == Some(DebugAsHex::Upper))
480-
<< rt::Flag::DebugUpperHex as u32
482+
self.flags
481483
}
482484
}
483485

@@ -2081,11 +2083,11 @@ impl<'a> Formatter<'a> {
20812083
// FIXME: Decide what public API we want for these two flags.
20822084
// https://github.com/rust-lang/rust/issues/48584
20832085
fn debug_lower_hex(&self) -> bool {
2084-
self.options.debug_as_hex == Some(DebugAsHex::Lower)
2086+
self.options.flags & (1 << rt::Flag::DebugLowerHex as u32) != 0
20852087
}
20862088

20872089
fn debug_upper_hex(&self) -> bool {
2088-
self.options.debug_as_hex == Some(DebugAsHex::Upper)
2090+
self.options.flags & (1 << rt::Flag::DebugUpperHex as u32) != 0
20892091
}
20902092

20912093
/// Creates a [`DebugStruct`] builder designed to assist with creation of

library/core/tests/fmt/mod.rs

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -51,21 +51,17 @@ fn formatting_options_flags() {
5151
for alternate in [true, false] {
5252
for sign_aware_zero_pad in [true, false] {
5353
for debug_as_hex in [None, Some(DebugAsHex::Lower), Some(DebugAsHex::Upper)] {
54-
let mut original_formatting_options = FormattingOptions::new();
55-
original_formatting_options
54+
let mut formatting_options = FormattingOptions::new();
55+
formatting_options
5656
.sign(sign)
5757
.sign_aware_zero_pad(sign_aware_zero_pad)
5858
.alternate(alternate)
5959
.debug_as_hex(debug_as_hex);
6060

61-
let mut formatting_options_with_flags_set_to_self = original_formatting_options;
62-
formatting_options_with_flags_set_to_self
63-
.flags(formatting_options_with_flags_set_to_self.get_flags());
64-
65-
assert_eq!(
66-
original_formatting_options, formatting_options_with_flags_set_to_self,
67-
"Reading and setting flags changes FormattingOptions; Sign({sign:?}), Alternate({alternate:?}). DebugAsHex({debug_as_hex:?})"
68-
)
61+
assert_eq!(formatting_options.get_sign(), sign);
62+
assert_eq!(formatting_options.get_alternate(), alternate);
63+
assert_eq!(formatting_options.get_sign_aware_zero_pad(), sign_aware_zero_pad);
64+
assert_eq!(formatting_options.get_debug_as_hex(), debug_as_hex);
6965
}
7066
}
7167
}

0 commit comments

Comments
 (0)