Skip to main content

display_more/
display_slice.rs

1// Copyright 2021 Datafuse Labs
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::fmt;
16
17use crate::DisplayIntoIter;
18
19/// Implement `Display` for `&[T]` if T is `Display`.
20///
21/// It outputs at most `limit` elements, excluding those from the 5th to the second-to-last one:
22/// - `DisplaySlice{ slice: &[1,2,3,4,5,6], ...}` outputs: `"[1,2,3,4,...,6]"`.
23pub struct DisplaySlice<'a, T: fmt::Display> {
24    inner: DisplayIntoIter<'a, T, std::slice::Iter<'a, T>>,
25}
26
27impl<'a, T: fmt::Display> DisplaySlice<'a, T> {
28    pub fn new(slice: &'a [T]) -> Self {
29        Self {
30            inner: DisplayIntoIter::new(slice.iter()),
31        }
32    }
33
34    pub fn at_most(mut self, limit: Option<usize>) -> Self {
35        self.inner = self.inner.at_most(limit);
36        self
37    }
38
39    pub fn sep(mut self, separator: &'a str) -> Self {
40        self.inner = self.inner.sep(separator);
41        self
42    }
43
44    pub fn braces(mut self, left: &'a str, right: &'a str) -> Self {
45        self.inner = self.inner.braces(left, right);
46        self
47    }
48
49    pub fn ellipsis(mut self, s: &'a str) -> Self {
50        self.inner = self.inner.ellipsis(s);
51        self
52    }
53
54    pub fn elem(mut self, prefix: &'a str, suffix: &'a str) -> Self {
55        self.inner = self.inner.elem(prefix, suffix);
56        self
57    }
58
59    pub fn show_count(mut self) -> Self {
60        self.inner = self.inner.show_count();
61        self
62    }
63
64    pub fn limit(&self) -> usize {
65        self.inner.limit()
66    }
67}
68
69impl<T: fmt::Display> fmt::Display for DisplaySlice<'_, T> {
70    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
71        self.inner.fmt(f)
72    }
73}
74
75/// Implement `Display` for `&[T]` if T is `Display`.
76///
77/// It outputs at most `MAX` elements, excluding those from the 5th to the second-to-last one:
78/// - `DisplaySlice(&[1,2,3,4,5,6])` outputs: `"[1,2,3,4,...,6]"`.
79///
80/// # Example
81///
82/// ```rust
83/// use display_more::DisplaySliceExt;
84///
85/// let a = vec![1, 2, 3, 4, 5, 6];
86/// assert_eq!(a.display().to_string(), "[1,2,3,4,..,6]");
87/// ```
88pub trait DisplaySliceExt<'a, T: fmt::Display> {
89    fn display(&'a self) -> DisplaySlice<'a, T>;
90
91    /// Display at most `n` elements.
92    fn display_n(&'a self, n: usize) -> DisplaySlice<'a, T> {
93        self.display().at_most(Some(n))
94    }
95}
96
97impl<T> DisplaySliceExt<'_, T> for [T]
98where T: fmt::Display
99{
100    fn display(&self) -> DisplaySlice<T> {
101        DisplaySlice::new(self)
102    }
103}
104
105#[cfg(test)]
106mod tests {
107    use super::DisplaySlice;
108    use crate::DisplaySliceExt;
109
110    #[test]
111    fn test_display_slice() {
112        let a = vec![1, 2, 3, 4];
113        assert_eq!("[1,2,3,4]", DisplaySlice::new(&a).to_string());
114
115        let a = vec![1, 2, 3, 4, 5];
116        assert_eq!("[1,2,3,4,5]", DisplaySlice::new(&a).to_string());
117
118        let a = vec![1, 2, 3, 4, 5, 6];
119        assert_eq!("[1,2,3,4,..,6]", DisplaySlice::new(&a).to_string());
120
121        let a = [1, 2, 3, 4, 5, 6, 7];
122        assert_eq!("[1,2,3,4,..,7]", DisplaySlice::new(&a).to_string());
123
124        // with limit
125
126        let a = [1, 2, 3, 4, 5, 6, 7];
127        assert_eq!(
128            "[1,..,7]",
129            DisplaySlice::new(&a).at_most(Some(2)).to_string()
130        );
131
132        assert_eq!("[1,..,7]", a.display().at_most(Some(2)).to_string());
133
134        assert_eq!("[1,..,7]", a.display_n(2).to_string());
135
136        assert_eq!("[..,7]", a.display_n(1).to_string());
137
138        assert_eq!("[..]", a.display_n(0).to_string());
139    }
140
141    #[test]
142    fn test_display_slice_separator() {
143        let a = [1, 2, 3];
144        assert_eq!("[1, 2, 3]", a.display().sep(", ").to_string());
145
146        let a = [1, 2, 3, 4, 5, 6];
147        assert_eq!("[1, 2, 3, 4, .., 6]", a.display().sep(", ").to_string());
148
149        assert_eq!("[1|..|6]", a.display_n(2).sep("|").to_string());
150
151        assert_eq!("[1 2 3 4 .. 6]", a.display().sep(" ").to_string());
152
153        assert_eq!("[1234..6]", a.display().sep("").to_string());
154        assert_eq!("[1..6]", a.display_n(2).sep("").to_string());
155
156        // limit=1 with custom separator
157        assert_eq!("[.. 6]", a.display_n(1).sep(" ").to_string());
158
159        // limit=0 is unaffected by separator
160        assert_eq!("[..]", a.display_n(0).sep(" ").to_string());
161    }
162
163    #[test]
164    fn test_display_slice_ellipsis() {
165        let a = [1, 2, 3, 4, 5, 6];
166
167        // Custom ellipsis "..."
168        assert_eq!("[1,2,3,4,...,6]", a.display().ellipsis("...").to_string());
169
170        // Unicode ellipsis
171        assert_eq!(
172            "[1,2,3,4,\u{2026},6]",
173            a.display().ellipsis("\u{2026}").to_string()
174        );
175
176        // Empty ellipsis
177        assert_eq!("[1,2,3,4,,6]", a.display().ellipsis("").to_string());
178
179        // limit=0 with custom ellipsis
180        assert_eq!("[...]", a.display_n(0).ellipsis("...").to_string());
181
182        // Combined with custom separator
183        assert_eq!(
184            "[1, 2, 3, 4, ..., 6]",
185            a.display().ellipsis("...").sep(", ").to_string()
186        );
187    }
188
189    #[test]
190    fn test_display_slice_elem() {
191        let a = [1, 2, 3];
192
193        // Quotes
194        assert_eq!("['1','2','3']", a.display().elem("'", "'").to_string());
195
196        // Quotes with truncation
197        let b = [1, 2, 3, 4, 5, 6];
198        assert_eq!(
199            "['1','2','3','4',..,'6']",
200            b.display().elem("'", "'").to_string()
201        );
202
203        // Angle brackets
204        assert_eq!("[<1>,<2>,<3>]", a.display().elem("<", ">").to_string());
205
206        // Combined with custom separator
207        assert_eq!(
208            "['1', '2', '3']",
209            a.display().elem("'", "'").sep(", ").to_string()
210        );
211
212        // Empty prefix/suffix (default behavior)
213        assert_eq!("[1,2,3]", a.display().elem("", "").to_string());
214    }
215
216    #[test]
217    fn test_display_slice_show_count() {
218        let a = [1, 2, 3, 4, 5, 6, 7];
219
220        // Basic
221        assert_eq!(
222            "[1,2,3,4,..(7 total),7]",
223            a.display().show_count().to_string()
224        );
225
226        // limit=0
227        assert_eq!("[..(7 total)]", a.display_n(0).show_count().to_string());
228
229        // limit=1
230        assert_eq!("[..(7 total),7]", a.display_n(1).show_count().to_string());
231
232        // No truncation (len <= limit): count not shown
233        let c = [1, 2, 3];
234        assert_eq!("[1,2,3]", c.display().show_count().to_string());
235
236        // Combined with custom ellipsis
237        assert_eq!(
238            "[1,2,3,4,...(7 total),7]",
239            a.display().ellipsis("...").show_count().to_string()
240        );
241
242        // Combined with all features
243        assert_eq!(
244            "{'1', '2', '3', '4', ...(7 total), '7'}",
245            a.display()
246                .ellipsis("...")
247                .show_count()
248                .elem("'", "'")
249                .sep(", ")
250                .braces("{", "}")
251                .to_string()
252        );
253    }
254
255    #[test]
256    fn test_display_slice_braces() {
257        let a = [1, 2, 3];
258
259        // Custom braces, no truncation
260        assert_eq!("{1,2,3}", a.display().braces("{", "}").to_string());
261
262        // Custom braces with truncation
263        let b = [1, 2, 3, 4, 5, 6];
264        assert_eq!("{1,2,3,4,..,6}", b.display().braces("{", "}").to_string());
265
266        // Custom braces combined with custom separator
267        assert_eq!(
268            "{1, 2, 3, 4, .., 6}",
269            b.display().braces("{", "}").sep(", ").to_string()
270        );
271
272        // Custom braces with limit=0
273        assert_eq!("{..}", b.display_n(0).braces("{", "}").to_string());
274
275        // Parentheses
276        assert_eq!("(1,2,3)", a.display().braces("(", ")").to_string());
277
278        // Angle brackets
279        assert_eq!("<1,2,3>", a.display().braces("<", ">").to_string());
280
281        // Empty braces
282        assert_eq!("1,2,3", a.display().braces("", "").to_string());
283    }
284}