postcard_bindgen_core/
path.rs1use core::fmt::Display;
2use std::borrow::Cow;
3
4use genco::{lang::Lang, tokens::FormatInto};
5
6pub type Part<'a> = Cow<'a, str>;
8pub type FullPath<'a> = Cow<'a, str>;
10
11#[derive(Debug, Hash, Eq, PartialEq, Clone, PartialOrd, Ord)]
34pub struct PathBuf<'a> {
35 parts: Vec<Part<'a>>,
36}
37
38impl Default for PathBuf<'_> {
39 fn default() -> Self {
40 Self::new()
41 }
42}
43
44impl<'a> PathBuf<'a> {
45 pub fn new() -> Self {
47 PathBuf { parts: Vec::new() }
48 }
49
50 pub fn join(mut self, joiner: impl Into<Part<'a>>) -> Self {
64 self.parts.push(joiner.into());
65 self
66 }
67
68 pub fn push(&mut self, part: impl Into<Part<'a>>) {
70 self.parts.push(part.into());
71 }
72
73 pub fn push_front(&mut self, part: impl Into<Part<'a>>) {
75 self.parts.insert(0, part.into());
76 }
77
78 pub fn pop_front(&mut self) {
80 if !self.parts.is_empty() {
81 let _ = self.parts.remove(0);
82 }
83 }
84
85 pub fn parts(&self) -> impl Iterator<Item = &Part<'a>> {
87 self.parts.iter()
88 }
89
90 pub fn is_empty(&self) -> bool {
92 self.parts.is_empty()
93 }
94
95 pub fn into_path<'b>(self, joiner: impl Into<Part<'b>>) -> Path<'a, 'b> {
97 let joiner = joiner.into();
98 Path {
99 path: Some(self.parts.join(joiner.as_ref()).into()),
100 joiner,
101 }
102 }
103
104 pub fn flatten(&mut self) {
106 self.parts.clear();
107 }
108
109 pub fn into_owned(self) -> PathBuf<'static> {
111 PathBuf {
112 parts: self
113 .parts
114 .into_iter()
115 .map(|p| p.into_owned().into())
116 .collect(),
117 }
118 }
119}
120
121impl<'a> FromIterator<Part<'a>> for PathBuf<'a> {
122 fn from_iter<I>(iter: I) -> Self
123 where
124 I: IntoIterator<Item = Part<'a>>,
125 {
126 PathBuf {
127 parts: iter.into_iter().collect(),
128 }
129 }
130}
131
132impl<'a> From<&'a str> for PathBuf<'a> {
133 fn from(value: &'a str) -> Self {
134 PathBuf {
135 parts: vec![Cow::Borrowed(value)],
136 }
137 }
138}
139
140#[derive(Debug, Clone, PartialEq, Eq)]
154pub struct Path<'a, 'b> {
155 path: Option<FullPath<'a>>,
156 joiner: Cow<'b, str>,
157}
158
159impl<'a, 'b> Path<'a, 'b> {
160 pub fn new(path: impl Into<FullPath<'a>>, joiner: impl Into<Cow<'b, str>>) -> Self {
163 Path {
164 path: Some(path.into()),
165 joiner: joiner.into(),
166 }
167 }
168
169 pub fn parts(&self) -> impl Iterator<Item = &str> {
171 self.path
172 .as_ref()
173 .map(|p| p.split(self.joiner.as_ref()))
174 .into_iter()
175 .flatten()
176 }
177
178 pub fn flatten(&mut self) {
180 self.path = None;
181 }
182
183 pub fn into_buf(self) -> PathBuf<'a> {
185 PathBuf {
186 parts: self
187 .path
188 .map(|p| {
189 p.split(self.joiner.as_ref())
190 .map(|p| p.to_owned().into())
191 .collect::<Vec<Part<'a>>>()
192 })
193 .unwrap_or_default(),
194 }
195 }
196
197 pub fn is_empty(&self) -> bool {
199 self.path.as_ref().map(|p| p.is_empty()).unwrap_or(true)
200 }
201
202 pub fn into_owned(self) -> Path<'static, 'static> {
204 Path {
205 joiner: self.joiner.into_owned().into(),
206 path: self.path.map(|p| p.into_owned().into()),
207 }
208 }
209}
210
211impl<'a, 'b> From<Path<'a, 'b>> for String {
212 fn from(value: Path<'a, 'b>) -> Self {
213 value.path.map(|c| c.into_owned()).unwrap_or_default()
214 }
215}
216
217impl Display for Path<'_, '_> {
218 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
219 if let Some(path) = &self.path {
220 write!(f, "{}", path)
221 } else {
222 write!(f, "")
223 }
224 }
225}
226
227impl<L: Lang> FormatInto<L> for Path<'_, '_> {
228 fn format_into(self, t: &mut genco::tokens::Tokens<L>) {
229 if let Some(path) = &self.path {
230 path.format_into(t);
231 }
232 }
233}