Skip to content

Commit ceace40

Browse files
committed
Extend and expose API for {:x?} and {:X?} formatting
1 parent 56a35bc commit ceace40

File tree

13 files changed

+279
-114
lines changed

13 files changed

+279
-114
lines changed

compiler/rustc_parse_format/src/lib.rs

+60-31
Original file line numberDiff line numberDiff line change
@@ -142,19 +142,36 @@ pub enum Alignment {
142142
#[derive(Copy, Clone, Debug, PartialEq)]
143143
pub enum Flag {
144144
/// A `+` will be used to denote positive numbers.
145-
FlagSignPlus,
145+
FlagSignPlus = 0b0000_0001,
146146
/// A `-` will be used to denote negative numbers. This is the default.
147-
FlagSignMinus,
147+
FlagSignMinus = 0b0000_0010,
148148
/// An alternate form will be used for the value. In the case of numbers,
149149
/// this means that the number will be prefixed with the supplied string.
150-
FlagAlternate,
150+
FlagAlternate = 0b0000_0100,
151151
/// For numbers, this means that the number will be padded with zeroes,
152152
/// and the sign (`+` or `-`) will precede them.
153-
FlagSignAwareZeroPad,
154-
/// For Debug / `?`, format integers in lower-case hexadecimal.
155-
FlagDebugLowerHex,
156-
/// For Debug / `?`, format integers in upper-case hexadecimal.
157-
FlagDebugUpperHex,
153+
FlagSignAwareZeroPad = 0b0000_1000,
154+
/// For Debug / `?`, the variant used.
155+
FlagDebugVariant = 0b1111_0000_0000,
156+
}
157+
158+
/// Version of `DebugVariant` that can be used on stable.
159+
#[derive(Copy, Clone, Debug, PartialEq)]
160+
pub enum DebugVariant {
161+
/// [`LowerHex`]-like formatting. (`{:x?}`)
162+
LowerHex = 0b0001_0000_0000,
163+
/// [`UpperHex`]-like formatting. (`{:X?}`)
164+
UpperHex = 0b0010_0000_0000,
165+
/// [`Octal`]-like formatting. (`{:o?}`)
166+
Octal = 0b0100_0000_0000,
167+
/// [`Binary`]-like formatting. (`{:b?}`)
168+
Binary = 0b1000_0000_0000,
169+
/// [`LowerExp`]-like formatting. (`{:e?}`)
170+
LowerExp = 0b0011_0000_0000,
171+
/// [`UpperExp`]-like formatting. (`{:E?}`)
172+
UpperExp = 0b0110_0000_0000,
173+
/// [`Pointer`]-like formatting. (`{:p?}`)
174+
Pointer = 0b1100_0000_0000,
158175
}
159176

160177
/// A count is used for the precision and width parameters of an integer, and
@@ -580,13 +597,13 @@ impl<'a> Parser<'a> {
580597
}
581598
// Sign flags
582599
if self.consume('+') {
583-
spec.flags |= 1 << (FlagSignPlus as u32);
600+
spec.flags |= FlagSignPlus as u32;
584601
} else if self.consume('-') {
585-
spec.flags |= 1 << (FlagSignMinus as u32);
602+
spec.flags |= FlagSignMinus as u32;
586603
}
587604
// Alternate marker
588605
if self.consume('#') {
589-
spec.flags |= 1 << (FlagAlternate as u32);
606+
spec.flags |= FlagAlternate as u32;
590607
}
591608
// Width and precision
592609
let mut havewidth = false;
@@ -601,7 +618,7 @@ impl<'a> Parser<'a> {
601618
spec.width_span = Some(self.span(end - 1, end + 1));
602619
havewidth = true;
603620
} else {
604-
spec.flags |= 1 << (FlagSignAwareZeroPad as u32);
621+
spec.flags |= FlagSignAwareZeroPad as u32;
605622
}
606623
}
607624

@@ -628,31 +645,43 @@ impl<'a> Parser<'a> {
628645
spec.precision_span = Some(self.span(start, end));
629646
}
630647

631-
let ty_span_start = self.current_pos();
648+
let mut ty_span_start = self.cur.peek().map(|(pos, _)| *pos);
632649
// Optional radix followed by the actual format specifier
633-
if self.consume('x') {
634-
if self.consume('?') {
635-
spec.flags |= 1 << (FlagDebugLowerHex as u32);
636-
spec.ty = "?";
637-
} else {
638-
spec.ty = "x";
639-
}
640-
} else if self.consume('X') {
641-
if self.consume('?') {
642-
spec.flags |= 1 << (FlagDebugUpperHex as u32);
643-
spec.ty = "?";
644-
} else {
645-
spec.ty = "X";
646-
}
647-
} else if self.consume('?') {
650+
if self.consume('?') {
648651
spec.ty = "?";
649652
} else {
650653
spec.ty = self.word();
651-
if !spec.ty.is_empty() {
652-
let ty_span_end = self.current_pos();
653-
spec.ty_span = Some(self.span(ty_span_start, ty_span_end));
654+
655+
// FIXME: let chains
656+
if let Some(&(pos, c)) = self.cur.peek() {
657+
if c == '?' {
658+
let variant = match spec.ty {
659+
"x" => Some(DebugVariant::LowerHex),
660+
"X" => Some(DebugVariant::UpperHex),
661+
"o" => Some(DebugVariant::Octal),
662+
"b" => Some(DebugVariant::Binary),
663+
"e" => Some(DebugVariant::LowerExp),
664+
"E" => Some(DebugVariant::UpperExp),
665+
"p" => Some(DebugVariant::Pointer),
666+
_ => None,
667+
};
668+
if let Some(variant) = variant {
669+
spec.ty = "?";
670+
spec.flags |= variant as u32;
671+
ty_span_start = Some(pos);
672+
673+
// only advance if we have a valid variant
674+
self.cur.next();
675+
}
676+
}
654677
}
655678
}
679+
let ty_span_end = self.cur.peek().map(|(pos, _)| *pos);
680+
if !spec.ty.is_empty() {
681+
spec.ty_span = ty_span_start
682+
.and_then(|s| ty_span_end.map(|e| (s, e)))
683+
.map(|(start, end)| self.to_span_index(start).to(self.to_span_index(end)));
684+
}
656685
spec
657686
}
658687

0 commit comments

Comments
 (0)