1 //! Render utilities which don't belong anywhere else.
2 use std::fmt::{Display, Formatter, Result};
3 
as_display<F: Fn(&mut Formatter<'_>) -> Result>(f: F) -> impl Display4 pub fn as_display<F: Fn(&mut Formatter<'_>) -> Result>(f: F) -> impl Display {
5     struct ClosureDisplay<F: Fn(&mut Formatter<'_>) -> Result>(F);
6 
7     impl<F: Fn(&mut Formatter<'_>) -> Result> Display for ClosureDisplay<F> {
8         fn fmt(&self, f: &mut Formatter<'_>) -> Result {
9             self.0(f)
10         }
11     }
12 
13     ClosureDisplay(f)
14 }
15 
16 macro_rules! write_joined_non_empty_list {
17     ($f:expr,$template:tt,$list:expr,$sep:expr) => {{
18         let mut x = $list.into_iter().peekable();
19         if x.peek().is_some() {
20             write!($f, $template, x.format($sep))
21         } else {
22             Ok(())
23         }
24     }};
25 }
26 
27 /// Processes a name given by an [`Interner`][chalk_ir::interner::Interner] debug
28 /// method into something usable by the `display` module.
29 ///
30 /// This is specifically useful when implementing
31 /// [`RustIrDatabase`][crate::RustIrDatabase] `name_*` methods.
sanitize_debug_name(func: impl Fn(&mut Formatter<'_>) -> Option<Result>) -> String32 pub fn sanitize_debug_name(func: impl Fn(&mut Formatter<'_>) -> Option<Result>) -> String {
33     use std::fmt::Write;
34 
35     // First, write the debug method contents to a String.
36     let mut debug_out = String::new();
37     // ignore if the result is `None`, as we can just as easily tell by looking
38     // to see if anything was written to `debug_out`.
39     write!(
40         debug_out,
41         "{}",
42         as_display(|fmt| { func(fmt).unwrap_or(Ok(())) })
43     )
44     .expect("expected writing to a String to succeed");
45     if debug_out.is_empty() {
46         return "Unknown".to_owned();
47     }
48 
49     // now the actual sanitization
50     debug_out.replace(|c: char| !c.is_ascii_alphanumeric(), "_")
51 }
52