parse_display_with/
formats.rs1use core::{
2 fmt::{self, Display, Formatter},
3 marker::PhantomData,
4 result::Result,
5 str::FromStr,
6};
7
8use parse_display::{DisplayFormat, FromStrFormat};
9
10pub struct Fmt;
11
12impl<T: ?Sized + Display> DisplayFormat<T> for Fmt {
13 fn write(&self, f: &mut Formatter, value: &T) -> fmt::Result {
14 write!(f, "{value}")
15 }
16}
17impl<T: FromStr> FromStrFormat<T> for Fmt {
18 type Err = T::Err;
19 fn parse(&self, s: &str) -> Result<T, Self::Err> {
20 s.parse()
21 }
22}
23
24pub fn fmt() -> Fmt {
25 Fmt
26}
27
28pub fn fmt_display<T: ?Sized>(
29 f: impl Fn(&mut Formatter, &T) -> fmt::Result,
30) -> impl DisplayFormat<T> {
31 struct FnFmtDisplay<F>(F);
32 impl<T, F> DisplayFormat<T> for FnFmtDisplay<F>
33 where
34 T: ?Sized,
35 F: Fn(&mut Formatter, &T) -> fmt::Result,
36 {
37 fn write(&self, f: &mut Formatter, t: &T) -> fmt::Result {
38 (self.0)(f, t)
39 }
40 }
41 FnFmtDisplay(f)
42}
43
44pub fn fmt_from_str<T, E>(f: impl Fn(&str) -> Result<T, E>) -> impl FromStrFormat<T, Err = E> {
45 struct FnFmtFromStr<F>(F);
46 impl<T, E, F> FromStrFormat<T> for FnFmtFromStr<F>
47 where
48 F: Fn(&str) -> Result<T, E>,
49 {
50 type Err = E;
51 fn parse(&self, s: &str) -> Result<T, E> {
52 (self.0)(s)
53 }
54 }
55 FnFmtFromStr(f)
56}
57
58pub struct Join<'a, I: ?Sized, F = Fmt> {
59 item_format: F,
60 delimiter: &'a str,
61 _phantom: PhantomData<I>,
62}
63
64impl<T, I, F> DisplayFormat<T> for Join<'_, I, F>
65where
66 T: ?Sized,
67 for<'a> &'a T: IntoIterator<Item = &'a I>,
68 F: DisplayFormat<I>,
69{
70 fn write(&self, f: &mut Formatter, value: &T) -> fmt::Result {
71 let mut iter = value.into_iter();
72 if let Some(first) = iter.next() {
73 self.item_format.write(f, first)?;
74 for item in iter {
75 write!(f, "{}", self.delimiter)?;
76 self.item_format.write(f, item)?;
77 }
78 }
79 Ok(())
80 }
81}
82impl<T, I, F> FromStrFormat<T> for Join<'_, I, F>
83where
84 F: FromStrFormat<I>,
85 T: FromIterator<I>,
86{
87 type Err = F::Err;
88 fn parse(&self, s: &str) -> Result<T, Self::Err> {
89 s.split(self.delimiter)
90 .map(|item| self.item_format.parse(item))
91 .collect()
92 }
93}
94
95pub fn join<I: ?Sized, F>(item_format: F, delimiter: &str) -> Join<I, F> {
96 Join {
97 item_format,
98 delimiter,
99 _phantom: PhantomData,
100 }
101}
102
103pub fn delimiter<I: ?Sized>(delimiter: &str) -> Join<I> {
104 join(fmt(), delimiter)
105}