1use core::fmt;
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq)]
6pub struct NoOutput;
7
8impl fmt::Display for NoOutput {
9 fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
10 Ok(())
11 }
12}
13
14pub struct PathLike<D, R> {
30 delimiter: D,
31 replacer: R,
32 prepend: bool,
33}
34
35impl PathLike<char, NoOutput> {
36 pub const STRUCT: &'static Self = &Self {
37 delimiter: '.',
38 replacer: NoOutput,
39 prepend: false,
40 };
41}
42
43impl PathLike<char, char> {
44 pub const FS_RELATIVE: &'static Self = &Self {
45 delimiter: '/',
46 replacer: '.',
47 prepend: false,
48 };
49 pub const FS_ABSOLUTE: &'static Self = &Self {
50 delimiter: '/',
51 replacer: '.',
52 prepend: true,
53 };
54}
55
56impl PathLike<&'static str, NoOutput> {
57 pub const ROUTE: &'static Self = &Self {
58 delimiter: "->",
59 replacer: NoOutput,
60 prepend: false,
61 };
62 pub const LIST: &'static Self = &Self {
63 delimiter: ", ",
64 replacer: NoOutput,
65 prepend: false
66 };
67}
68
69impl<D> PathLike<D, NoOutput> {
70 pub fn new(delimiter: D, prepend: bool) -> Self {
71 Self { delimiter, replacer: NoOutput, prepend }
72 }
73}
74
75impl<D1, R> PathLike<D1, R> {
76 pub fn with_delimiter<D2>(self, delimiter: D2) -> PathLike<D2, R> {
77 let Self {
78 delimiter: _,
79 replacer,
80 prepend,
81 } = self;
82 PathLike {
83 delimiter,
84 replacer,
85 prepend,
86 }
87 }
88}
89
90impl<D, R1> PathLike<D, R1> {
91 pub fn with_replacer<R2>(self, replacer: R2) -> PathLike<D, R2> {
92 let Self {
93 delimiter,
94 replacer: _,
95 prepend,
96 } = self;
97 PathLike {
98 delimiter,
99 replacer,
100 prepend,
101 }
102 }
103}
104
105impl<D, R> PathLike<D, R> {
106 pub fn with_prepend(self, prepend: bool) -> Self {
107 Self { prepend, ..self }
108 }
109}
110
111impl<D, R, I> crate::Params<I> for PathLike<D, R>
112where
113 D: fmt::Display,
114 R: fmt::Display,
115 I: ?Sized,
116 for <'a> &'a I: IntoIterator<Item: fmt::Display>,
117{
118 fn fmt(&self, value: &I, f: &mut fmt::Formatter<'_>) -> fmt::Result {
119 let mut iter = value.into_iter();
120
121 let Some(first) = iter.next() else {
122 return self.replacer.fmt(f);
123 };
124
125 match self.prepend {
126 false => fmt::Display::fmt(&first, f),
127 true => output_component(f, &self.delimiter, first),
128 }?;
129
130 while let Some(item) = iter.next() {
131 output_component(f, &self.delimiter, item)?;
132 }
133
134 Ok(())
135 }
136}
137
138
139fn output_component(
140 f: &mut fmt::Formatter<'_>,
141 delimiter: impl fmt::Display,
142 item: impl fmt::Display,
143) -> fmt::Result {
144 write!(f, "{delimiter}{item}")
145}