1use std::fmt;
16
17pub struct DisplaySlice<'a, T: fmt::Display> {
22 slice: &'a [T],
23 limit: Option<usize>,
25 separator: &'a str,
27 left_brace: &'a str,
29 right_brace: &'a str,
31 ellipsis: &'a str,
33 elem_prefix: &'a str,
35 elem_suffix: &'a str,
37 show_count: bool,
39}
40
41impl<'a, T: fmt::Display> DisplaySlice<'a, T> {
42 pub fn new(slice: &'a [T]) -> Self {
43 Self {
44 slice,
45 limit: None,
46 separator: ",",
47 left_brace: "[",
48 right_brace: "]",
49 ellipsis: "..",
50 elem_prefix: "",
51 elem_suffix: "",
52 show_count: false,
53 }
54 }
55
56 pub fn at_most(mut self, limit: Option<usize>) -> Self {
57 self.limit = limit;
58 self
59 }
60
61 pub fn sep(mut self, separator: &'a str) -> Self {
62 self.separator = separator;
63 self
64 }
65
66 pub fn braces(mut self, left: &'a str, right: &'a str) -> Self {
67 self.left_brace = left;
68 self.right_brace = right;
69 self
70 }
71
72 pub fn ellipsis(mut self, s: &'a str) -> Self {
73 self.ellipsis = s;
74 self
75 }
76
77 pub fn elem(mut self, prefix: &'a str, suffix: &'a str) -> Self {
78 self.elem_prefix = prefix;
79 self.elem_suffix = suffix;
80 self
81 }
82
83 pub fn show_count(mut self) -> Self {
84 self.show_count = true;
85 self
86 }
87
88 pub fn limit(&self) -> usize {
89 self.limit.unwrap_or(5)
90 }
91}
92
93impl<T: fmt::Display> fmt::Display for DisplaySlice<'_, T> {
94 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
95 let limit = self.limit();
96 let slice = self.slice;
97 let len = slice.len();
98 let truncated = len > limit;
99
100 let ell;
101 let ellipsis = if self.show_count && truncated {
102 ell = format!("{}({len} total)", self.ellipsis);
103 &ell
104 } else {
105 self.ellipsis
106 };
107
108 if limit == 0 {
109 return write!(f, "{}{ellipsis}{}", self.left_brace, self.right_brace);
110 }
111
112 write!(f, "{}", self.left_brace)?;
113
114 let (pre, suf, sep) = (self.elem_prefix, self.elem_suffix, self.separator);
115
116 if truncated {
117 for t in slice[..(limit - 1)].iter() {
118 write!(f, "{pre}{t}{suf}{sep}")?;
119 }
120
121 write!(f, "{ellipsis}{sep}")?;
122 write!(f, "{pre}{}{suf}", slice.last().unwrap())?;
123 } else {
124 for (i, t) in slice.iter().enumerate() {
125 if i > 0 {
126 write!(f, "{sep}")?;
127 }
128
129 write!(f, "{pre}{t}{suf}")?;
130 }
131 }
132
133 write!(f, "{}", self.right_brace)
134 }
135}
136
137pub trait DisplaySliceExt<'a, T: fmt::Display> {
151 fn display(&'a self) -> DisplaySlice<'a, T>;
152
153 fn display_n(&'a self, n: usize) -> DisplaySlice<'a, T> {
155 self.display().at_most(Some(n))
156 }
157}
158
159impl<T> DisplaySliceExt<'_, T> for [T]
160where T: fmt::Display
161{
162 fn display(&self) -> DisplaySlice<T> {
163 DisplaySlice::new(self)
164 }
165}
166
167#[cfg(test)]
168mod tests {
169 use super::DisplaySlice;
170 use crate::DisplaySliceExt;
171
172 #[test]
173 fn test_display_slice() {
174 let a = vec![1, 2, 3, 4];
175 assert_eq!("[1,2,3,4]", DisplaySlice::new(&a).to_string());
176
177 let a = vec![1, 2, 3, 4, 5];
178 assert_eq!("[1,2,3,4,5]", DisplaySlice::new(&a).to_string());
179
180 let a = vec![1, 2, 3, 4, 5, 6];
181 assert_eq!("[1,2,3,4,..,6]", DisplaySlice::new(&a).to_string());
182
183 let a = vec![1, 2, 3, 4, 5, 6, 7];
184 assert_eq!("[1,2,3,4,..,7]", DisplaySlice::new(&a).to_string());
185
186 let a = vec![1, 2, 3, 4, 5, 6, 7];
189 assert_eq!(
190 "[1,..,7]",
191 DisplaySlice::new(&a).at_most(Some(2)).to_string()
192 );
193
194 assert_eq!("[1,..,7]", a.display().at_most(Some(2)).to_string());
195
196 assert_eq!("[1,..,7]", a.display_n(2).to_string());
197
198 assert_eq!("[..,7]", a.display_n(1).to_string());
199
200 assert_eq!("[..]", a.display_n(0).to_string());
201 }
202
203 #[test]
204 fn test_display_slice_separator() {
205 let a = vec![1, 2, 3];
206 assert_eq!("[1, 2, 3]", a.display().sep(", ").to_string());
207
208 let a = vec![1, 2, 3, 4, 5, 6];
209 assert_eq!("[1, 2, 3, 4, .., 6]", a.display().sep(", ").to_string());
210
211 assert_eq!("[1|..|6]", a.display_n(2).sep("|").to_string());
212
213 assert_eq!("[1 2 3 4 .. 6]", a.display().sep(" ").to_string());
214
215 assert_eq!("[1234..6]", a.display().sep("").to_string());
216 assert_eq!("[1..6]", a.display_n(2).sep("").to_string());
217
218 assert_eq!("[.. 6]", a.display_n(1).sep(" ").to_string());
220
221 assert_eq!("[..]", a.display_n(0).sep(" ").to_string());
223 }
224
225 #[test]
226 fn test_display_slice_ellipsis() {
227 let a = vec![1, 2, 3, 4, 5, 6];
228
229 assert_eq!("[1,2,3,4,...,6]", a.display().ellipsis("...").to_string());
231
232 assert_eq!(
234 "[1,2,3,4,\u{2026},6]",
235 a.display().ellipsis("\u{2026}").to_string()
236 );
237
238 assert_eq!("[1,2,3,4,,6]", a.display().ellipsis("").to_string());
240
241 assert_eq!("[...]", a.display_n(0).ellipsis("...").to_string());
243
244 assert_eq!(
246 "[1, 2, 3, 4, ..., 6]",
247 a.display().ellipsis("...").sep(", ").to_string()
248 );
249 }
250
251 #[test]
252 fn test_display_slice_elem() {
253 let a = vec![1, 2, 3];
254
255 assert_eq!("['1','2','3']", a.display().elem("'", "'").to_string());
257
258 let b = vec![1, 2, 3, 4, 5, 6];
260 assert_eq!(
261 "['1','2','3','4',..,'6']",
262 b.display().elem("'", "'").to_string()
263 );
264
265 assert_eq!("[<1>,<2>,<3>]", a.display().elem("<", ">").to_string());
267
268 assert_eq!(
270 "['1', '2', '3']",
271 a.display().elem("'", "'").sep(", ").to_string()
272 );
273
274 assert_eq!("[1,2,3]", a.display().elem("", "").to_string());
276 }
277
278 #[test]
279 fn test_display_slice_show_count() {
280 let a = vec![1, 2, 3, 4, 5, 6, 7];
281
282 assert_eq!(
284 "[1,2,3,4,..(7 total),7]",
285 a.display().show_count().to_string()
286 );
287
288 assert_eq!("[..(7 total)]", a.display_n(0).show_count().to_string());
290
291 assert_eq!("[..(7 total),7]", a.display_n(1).show_count().to_string());
293
294 let c = vec![1, 2, 3];
296 assert_eq!("[1,2,3]", c.display().show_count().to_string());
297
298 assert_eq!(
300 "[1,2,3,4,...(7 total),7]",
301 a.display().ellipsis("...").show_count().to_string()
302 );
303
304 assert_eq!(
306 "{'1', '2', '3', '4', ...(7 total), '7'}",
307 a.display()
308 .ellipsis("...")
309 .show_count()
310 .elem("'", "'")
311 .sep(", ")
312 .braces("{", "}")
313 .to_string()
314 );
315 }
316
317 #[test]
318 fn test_display_slice_braces() {
319 let a = vec![1, 2, 3];
320
321 assert_eq!("{1,2,3}", a.display().braces("{", "}").to_string());
323
324 let b = vec![1, 2, 3, 4, 5, 6];
326 assert_eq!("{1,2,3,4,..,6}", b.display().braces("{", "}").to_string());
327
328 assert_eq!(
330 "{1, 2, 3, 4, .., 6}",
331 b.display().braces("{", "}").sep(", ").to_string()
332 );
333
334 assert_eq!("{..}", b.display_n(0).braces("{", "}").to_string());
336
337 assert_eq!("(1,2,3)", a.display().braces("(", ")").to_string());
339
340 assert_eq!("<1,2,3>", a.display().braces("<", ">").to_string());
342
343 assert_eq!("1,2,3", a.display().braces("", "").to_string());
345 }
346}