parse_display_with/
formats.rs

1use 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}