1use std::fmt::{self, Display, Formatter, FormattingOptions};
4
5pub(crate) trait Joined: IntoIterator {
6 fn joined(self, sep: impl Display, f: &mut Formatter<'_>) -> fmt::Result;
14}
15
16impl<I, T> Joined for I
17where
18 I: IntoIterator<Item = T>,
19 T: Display,
20{
21 fn joined(self, sep: impl Display, f: &mut Formatter<'_>) -> fmt::Result {
22 let mut iter = self.into_iter();
23 let Some(first) = iter.next() else { return Ok(()) };
24 first.fmt(f)?;
25 for item in iter {
26 sep.fmt(f)?;
27 item.fmt(f)?;
28 }
29 Ok(())
30 }
31}
32
33pub(crate) trait MaybeDisplay {
34 fn maybe_display(self) -> impl Display;
36}
37
38impl<T: Display> MaybeDisplay for Option<T> {
39 fn maybe_display(self) -> impl Display {
40 fmt::from_fn(move |f| {
41 if let Some(t) = self.as_ref() {
42 t.fmt(f)?;
43 }
44 Ok(())
45 })
46 }
47}
48
49#[derive(Clone, Copy)]
50pub(crate) struct Wrapped<T> {
51 prefix: T,
52 suffix: T,
53}
54
55pub(crate) enum AngleBracket {
56 Open,
57 Close,
58}
59
60impl Display for AngleBracket {
61 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
62 f.write_str(match (self, f.alternate()) {
63 (Self::Open, true) => "<",
64 (Self::Open, false) => "<",
65 (Self::Close, true) => ">",
66 (Self::Close, false) => ">",
67 })
68 }
69}
70
71impl Wrapped<AngleBracket> {
72 pub(crate) fn with_angle_brackets() -> Self {
73 Self { prefix: AngleBracket::Open, suffix: AngleBracket::Close }
74 }
75}
76
77impl Wrapped<char> {
78 pub(crate) fn with_parens() -> Self {
79 Self { prefix: '(', suffix: ')' }
80 }
81
82 pub(crate) fn with_square_brackets() -> Self {
83 Self { prefix: '[', suffix: ']' }
84 }
85}
86
87impl<T: Display> Wrapped<T> {
88 pub(crate) fn with(prefix: T, suffix: T) -> Self {
89 Self { prefix, suffix }
90 }
91
92 pub(crate) fn when(self, if_: bool) -> Wrapped<impl Display> {
93 Wrapped {
94 prefix: if_.then_some(self.prefix).maybe_display(),
95 suffix: if_.then_some(self.suffix).maybe_display(),
96 }
97 }
98
99 pub(crate) fn wrap_fn(
100 self,
101 content: impl Fn(&mut Formatter<'_>) -> fmt::Result,
102 ) -> impl Display {
103 fmt::from_fn(move |f| {
104 self.prefix.fmt(f)?;
105 content(f)?;
106 self.suffix.fmt(f)
107 })
108 }
109
110 pub(crate) fn wrap<C: Display>(self, content: C) -> impl Display {
111 self.wrap_fn(move |f| content.fmt(f))
112 }
113}
114
115#[derive(Clone, Copy)]
116pub(crate) struct WithOpts {
117 opts: FormattingOptions,
118}
119
120impl WithOpts {
121 pub(crate) fn from(f: &Formatter<'_>) -> Self {
122 Self { opts: f.options() }
123 }
124
125 pub(crate) fn display(self, t: impl Display) -> impl Display {
126 fmt::from_fn(move |f| {
127 let mut f = f.with_options(self.opts);
128 t.fmt(&mut f)
129 })
130 }
131}