Skip to content

Commit 7d87d52

Browse files
committed
Compile format_args! to a closure instead of list of pieces.
Idea stolen from rust-lang/rust#101568
1 parent 51f2c75 commit 7d87d52

File tree

12 files changed

+140
-130
lines changed

12 files changed

+140
-130
lines changed

core/src/arguments.rs

Lines changed: 42 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,44 @@
1-
use crate::{formatter::FormatterArgs, Display, Formatter, Result, StyleDiff};
1+
use crate::{Display, Formatter, Result};
22

3-
type StdFmtFn<'a> = dyn Fn(&mut core::fmt::Formatter<'_>) -> Result + 'a;
4-
5-
#[doc(hidden)] // workaround https://github.com/rust-lang/rust/issues/85522
6-
pub struct StdFmt<'a>(stack_dst::ValueA<StdFmtFn<'a>, [usize; 3]>);
7-
8-
impl<'a> StdFmt<'a> {
9-
#[doc(hidden)] // workaround https://github.com/rust-lang/rust/issues/85526
10-
pub fn new(f: impl Fn(&mut core::fmt::Formatter<'_>) -> Result + 'a) -> StdFmt<'a> {
11-
// not possible(/easy) to correctly type the closure, but with the cast
12-
// inference works
13-
#[allow(trivial_casts)]
14-
StdFmt(
15-
stack_dst::ValueA::new_stable(f, |p| p as _)
16-
.map_err(|_| ())
17-
.expect("StdFmt was more than 3 words, this is a bug in stylish-core"),
18-
)
19-
}
3+
#[doc(hidden)]
4+
/// pub for macros
5+
pub struct StdFmt<'a> {
6+
#[doc(hidden)]
7+
/// pub for macros
8+
pub f: &'a (dyn Fn(&mut core::fmt::Formatter<'_>) -> Result + 'a),
209
}
2110

2211
impl core::fmt::Display for StdFmt<'_> {
12+
#[inline]
2313
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result {
24-
(self.0)(f)
14+
(self.f)(f)
2515
}
2616
}
2717

2818
impl core::fmt::Debug for StdFmt<'_> {
19+
#[inline]
2920
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result {
30-
(self.0)(f)
21+
(self.f)(f)
3122
}
3223
}
3324

34-
#[doc(hidden)] // workaround https://github.com/rust-lang/rust/issues/85522
25+
#[doc(hidden)]
3526
#[allow(missing_debug_implementations)]
36-
pub enum FormatTrait<'a> {
37-
Display(StdFmt<'a>),
38-
Debug(StdFmt<'a>),
39-
Octal(StdFmt<'a>),
40-
LowerHex(StdFmt<'a>),
41-
UpperHex(StdFmt<'a>),
42-
Pointer(StdFmt<'a>),
43-
Binary(StdFmt<'a>),
44-
LowerExp(StdFmt<'a>),
45-
UpperExp(StdFmt<'a>),
46-
Stylish(&'a dyn Display),
47-
}
27+
/// pub for macros
28+
pub struct StdFmtOther<'a>(
29+
#[doc(hidden)]
30+
/// pub for macros
31+
pub StdFmt<'a>,
32+
);
4833

49-
#[doc(hidden)] // workaround https://github.com/rust-lang/rust/issues/85522
34+
#[doc(hidden)]
5035
#[allow(missing_debug_implementations)]
51-
pub enum Argument<'a> {
52-
Lit(&'a str),
53-
54-
Arg {
55-
args: &'a FormatterArgs<'a>,
56-
style: StyleDiff,
57-
arg: FormatTrait<'a>,
58-
},
59-
}
36+
/// pub for macros
37+
pub struct StdFmtDebug<'a>(
38+
#[doc(hidden)]
39+
/// pub for macros
40+
pub StdFmt<'a>,
41+
);
6042

6143
/// A precompiled version of a format string and its by-reference arguments.
6244
///
@@ -72,37 +54,30 @@ pub enum Argument<'a> {
7254
/// ```
7355
#[allow(missing_debug_implementations)]
7456
pub struct Arguments<'a> {
75-
#[doc(hidden)] // pub for macros
76-
pub pieces: &'a [Argument<'a>],
57+
#[doc(hidden)]
58+
/// pub for macros
59+
pub f: &'a (dyn Fn(&mut Formatter<'_>) -> Result + 'a),
60+
}
61+
62+
impl Display for StdFmtOther<'_> {
63+
#[inline]
64+
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
65+
let arg = &self.0;
66+
std_write!(f, Other, arg)
67+
}
7768
}
7869

79-
impl Display for FormatTrait<'_> {
70+
impl Display for StdFmtDebug<'_> {
71+
#[inline]
8072
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
81-
match self {
82-
Self::Display(arg) => std_write!(f, Display, arg),
83-
Self::Debug(arg) => std_write!(f, Debug, arg),
84-
Self::Octal(arg) => std_write!(f, Display, arg),
85-
Self::LowerHex(arg) => std_write!(f, Display, arg),
86-
Self::UpperHex(arg) => std_write!(f, Display, arg),
87-
Self::Pointer(arg) => std_write!(f, Display, arg),
88-
Self::Binary(arg) => std_write!(f, Display, arg),
89-
Self::LowerExp(arg) => std_write!(f, Display, arg),
90-
Self::UpperExp(arg) => std_write!(f, Display, arg),
91-
Self::Stylish(arg) => arg.fmt(f),
92-
}
73+
let arg = &self.0;
74+
std_write!(f, Debug, arg)
9375
}
9476
}
9577

9678
impl Display for Arguments<'_> {
79+
#[inline]
9780
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
98-
for piece in self.pieces {
99-
match piece {
100-
Argument::Lit(lit) => f.write_str(lit)?,
101-
Argument::Arg { args, style, arg } => {
102-
arg.fmt(&mut f.with(style).with_args(args))?
103-
}
104-
}
105-
}
106-
Ok(())
81+
(self.f)(f)
10782
}
10883
}

core/src/format.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ macro_rules! format {
5454
/// "Hello, <span style=color:green>world</span>!"
5555
/// );
5656
/// ```
57+
#[inline]
5758
pub fn format(args: Arguments<'_>) -> String {
5859
let mut output = String::new();
5960
output

core/src/formatter.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ pub struct Formatter<'a> {
4848
}
4949

5050
impl core::fmt::Debug for Formatter<'_> {
51+
#[inline]
5152
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result {
5253
f.debug_struct("Formatter")
5354
.field("style", &self.style)
@@ -57,6 +58,7 @@ impl core::fmt::Debug for Formatter<'_> {
5758
}
5859

5960
impl<'a> Formatter<'a> {
61+
#[inline]
6062
pub(crate) fn new(write: &'a mut (dyn Write + 'a)) -> Self {
6163
Self {
6264
style: Style::default(),
@@ -99,11 +101,13 @@ impl<'a> Formatter<'a> {
99101
}
100102
}
101103

102-
pub(crate) fn with_args<'b>(&'b mut self, format: &FormatterArgs<'b>) -> Formatter<'b> {
104+
#[doc(hidden)]
105+
/// pub for macros
106+
pub fn with_args<'b>(&'b mut self, format: &FormatterArgs<'b>, restyle: impl Restyle) -> Formatter<'b> {
103107
Formatter {
104108
write: &mut *self.write,
105109
format: *format,
106-
style: self.style,
110+
style: self.style.with(restyle),
107111
}
108112
}
109113

@@ -130,6 +134,7 @@ impl<'a> Formatter<'a> {
130134
/// "Hello <span style=color:red>Ferris</span> and <span style=color:cyan>Gorris</span>"
131135
/// );
132136
/// ```
137+
#[inline]
133138
pub fn write_str(&mut self, s: &str) -> Result {
134139
self.write.write_str(s, self.style)?;
135140
Ok(())
@@ -157,23 +162,27 @@ impl<'a> Formatter<'a> {
157162
/// "Hello <span style=color:red>Ferris</span> and <span style=color:cyan>Gorris</span>"
158163
/// );
159164
/// ```
165+
#[inline]
160166
pub fn write_fmt(&mut self, args: Arguments<'_>) -> Result {
161167
args.fmt(self)?;
162168
Ok(())
163169
}
164170
}
165171

166172
impl<'a> Write for Formatter<'a> {
173+
#[inline]
167174
fn write_str(&mut self, s: &str, style: Style) -> Result {
168175
self.with(style).write_str(s)
169176
}
170177

178+
#[inline]
171179
fn write_fmt(&mut self, args: Arguments<'_>) -> Result {
172180
self.write_fmt(args)
173181
}
174182
}
175183

176184
impl<'a> core::fmt::Write for Formatter<'a> {
185+
#[inline]
177186
fn write_str(&mut self, s: &str) -> Result {
178187
self.write_str(s)
179188
}

core/src/io.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ pub trait Write {
214214
/// output.write_fmt(stylish::format_args!("{:(fg=red)}", '☎'))?;
215215
/// # Ok::<(), std::io::Error>(())
216216
/// ```
217+
#[inline]
217218
fn write_fmt(&mut self, args: Arguments<'_>) -> Result<()> {
218219
let mut trap = ErrorTrap::new(self);
219220

@@ -241,6 +242,7 @@ pub trait Write {
241242
/// )?;
242243
/// # Ok::<(), std::io::Error>(())
243244
/// ```
245+
#[inline]
244246
fn by_ref(&mut self) -> &mut Self
245247
where
246248
Self: Sized,

core/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,8 @@ pub mod 𓀄 {
5454
pub use with_builtin_macros::with_builtin;
5555

5656
pub use crate::{
57-
arguments::{Argument, Arguments, FormatTrait, StdFmt},
58-
formatter::{Align, DebugHex, FormatterArgs, Sign},
57+
arguments::{Arguments, StdFmt, StdFmtDebug, StdFmtOther},
58+
formatter::{Align, DebugHex, Formatter, FormatterArgs, Sign},
5959
Background, Color, Display, Foreground, Intensity, StyleDiff,
6060
};
6161
}

core/src/std_compat.rs

Lines changed: 5 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -55,37 +55,20 @@ macro_rules! std_write {
5555
})
5656
};
5757

58-
(@str $f:ident $val:ident [Display $($flag:ident)*]) => {
58+
// For most traits we can pipe them through `Display` since they have the same function
59+
// signature
60+
(@str $f:ident $val:ident [Other $($flag:ident)*]) => {
5961
std_write!(@str $f $val [$($flag)*] { { debug_hex: _, } => (("",),); })
6062
};
63+
64+
// But `Debug` is special as it has extra hex flags
6165
(@str $f:ident $val:ident [Debug $($flag:ident)*]) => {
6266
std_write!(@str $f $val [$($flag)*] {
6367
{ debug_hex: None, } => (("?",),);
6468
{ debug_hex: Some(crate::formatter::DebugHex::Lower), } => (("x?",),);
6569
{ debug_hex: Some(crate::formatter::DebugHex::Upper), } => (("X?",),);
6670
})
6771
};
68-
(@str $f:ident $val:ident [Octal $($flag:ident)*]) => {
69-
std_write!(@str $f $val [$($flag)*] { { debug_hex: _, } => (("o",),); })
70-
};
71-
(@str $f:ident $val:ident [LowerHex $($flag:ident)*]) => {
72-
std_write!(@str $f $val [$($flag)*] { { debug_hex: _, } => (("x",),); })
73-
};
74-
(@str $f:ident $val:ident [UpperHex $($flag:ident)*]) => {
75-
std_write!(@str $f $val [$($flag)*] { { debug_hex: _, } => (("X",),); })
76-
};
77-
(@str $f:ident $val:ident [Pointer $($flag:ident)*]) => {
78-
std_write!(@str $f $val [$($flag)*] { { debug_hex: _, } => (("p",),); })
79-
};
80-
(@str $f:ident $val:ident [Binary $($flag:ident)*]) => {
81-
std_write!(@str $f $val [$($flag)*] { { debug_hex: _, } => (("b",),); })
82-
};
83-
(@str $f:ident $val:ident [LowerExp $($flag:ident)*]) => {
84-
std_write!(@str $f $val [$($flag)*] { { debug_hex: _, } => (("e",),); })
85-
};
86-
(@str $f:ident $val:ident [UpperExp $($flag:ident)*]) => {
87-
std_write!(@str $f $val [$($flag)*] { { debug_hex: _, } => (("E",),); })
88-
};
8972

9073
($f:ident, $trait:ident, $val:ident) => {
9174
std_write!(@str $f $val [$trait precision width zero alternate sign align])

core/src/string.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,14 @@ impl String {
5151
/// ```rust
5252
/// assert_eq!(stylish::html::format!("{:s}", stylish::String::new()), "");
5353
/// ```
54+
#[inline]
5455
pub fn new() -> Self {
5556
Self::default()
5657
}
5758
}
5859

5960
impl Write for String {
61+
#[inline]
6062
fn write_str(&mut self, s: &str, style: Style) -> Result {
6163
if Some(style) != self.styles.last().map(|&(_, style)| style) {
6264
self.styles.push((self.string.len(), style));
@@ -67,6 +69,7 @@ impl Write for String {
6769
}
6870

6971
impl Display for String {
72+
#[inline]
7073
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
7174
let mut styles = self.styles.iter().peekable();
7275
while let Some(&(start, style)) = styles.next() {

core/src/write.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ pub trait Write {
6464
/// );
6565
/// # Ok::<(), core::fmt::Error>(())
6666
/// ```
67+
#[inline]
6768
fn write_char(&mut self, c: char, style: Style) -> Result {
6869
self.write_str(c.encode_utf8(&mut [0; 4]), style)
6970
}
@@ -85,6 +86,7 @@ pub trait Write {
8586
/// assert_eq!(s, "<span style=color:red>☎</span>");
8687
/// # Ok::<(), core::fmt::Error>(())
8788
/// ```
89+
#[inline]
8890
fn write_fmt(mut self: &mut Self, args: Arguments<'_>) -> Result {
8991
Formatter::new(&mut self).write_fmt(args)
9092
}

0 commit comments

Comments
 (0)