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
17/// Implement `Display` for `&[T]` if T is `Display`.
18///
19/// It outputs at most `limit` elements, excluding those from the 5th to the second-to-last one:
20/// - `DisplaySlice{ slice: &[1,2,3,4,5,6], ...}` outputs: `"[1,2,3,4,...,6]"`.
21pub struct DisplaySlice<'a, T: fmt::Display> {
22    slice: &'a [T],
23    /// The maximum number of elements to display. by default, it is 5.
24    limit: Option<usize>,
25}
26
27impl<'a, T: fmt::Display> DisplaySlice<'a, T> {
28    pub fn new(slice: &'a [T]) -> Self {
29        Self { slice, limit: None }
30    }
31
32    pub fn at_most(mut self, limit: Option<usize>) -> Self {
33        self.limit = limit;
34        self
35    }
36
37    pub fn limit(&self) -> usize {
38        self.limit.unwrap_or(5)
39    }
40}
41
42impl<T: fmt::Display> fmt::Display for DisplaySlice<'_, T> {
43    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
44        let limit = self.limit();
45
46        if limit == 0 {
47            return write!(f, "[..]");
48        }
49
50        let slice = self.slice;
51        let len = slice.len();
52
53        write!(f, "[")?;
54
55        if len > limit {
56            for t in slice[..(limit - 1)].iter() {
57                write!(f, "{},", t)?;
58            }
59
60            write!(f, "..,")?;
61            write!(f, "{}", slice.last().unwrap())?;
62        } else {
63            for (i, t) in slice.iter().enumerate() {
64                if i > 0 {
65                    write!(f, ",")?;
66                }
67
68                write!(f, "{}", t)?;
69            }
70        }
71
72        write!(f, "]")
73    }
74}
75
76/// Implement `Display` for `&[T]` if T is `Display`.
77///
78/// It outputs at most `MAX` elements, excluding those from the 5th to the second-to-last one:
79/// - `DisplaySlice(&[1,2,3,4,5,6])` outputs: `"[1,2,3,4,...,6]"`.
80///
81/// # Example
82///
83/// ```rust
84/// use display_more::DisplaySliceExt;
85///
86/// let a = vec![1, 2, 3, 4, 5, 6];
87/// assert_eq!(a.display().to_string(), "[1,2,3,4,..,6]");
88/// ```
89pub trait DisplaySliceExt<'a, T: fmt::Display> {
90    fn display(&'a self) -> DisplaySlice<'a, T>;
91
92    /// Display at most `n` elements.
93    fn display_n(&'a self, n: usize) -> DisplaySlice<'a, T> {
94        self.display().at_most(Some(n))
95    }
96}
97
98impl<T> DisplaySliceExt<'_, T> for [T]
99where T: fmt::Display
100{
101    fn display(&self) -> DisplaySlice<T> {
102        DisplaySlice::new(self)
103    }
104}
105
106#[cfg(test)]
107mod tests {
108    use super::DisplaySlice;
109    use crate::DisplaySliceExt;
110
111    #[test]
112    fn test_display_slice() {
113        let a = vec![1, 2, 3, 4];
114        assert_eq!("[1,2,3,4]", DisplaySlice::new(&a).to_string());
115
116        let a = vec![1, 2, 3, 4, 5];
117        assert_eq!("[1,2,3,4,5]", DisplaySlice::new(&a).to_string());
118
119        let a = vec![1, 2, 3, 4, 5, 6];
120        assert_eq!("[1,2,3,4,..,6]", DisplaySlice::new(&a).to_string());
121
122        let a = vec![1, 2, 3, 4, 5, 6, 7];
123        assert_eq!("[1,2,3,4,..,7]", DisplaySlice::new(&a).to_string());
124
125        // with limit
126
127        let a = vec![1, 2, 3, 4, 5, 6, 7];
128        assert_eq!(
129            "[1,..,7]",
130            DisplaySlice::new(&a).at_most(Some(2)).to_string()
131        );
132
133        assert_eq!("[1,..,7]", a.display().at_most(Some(2)).to_string());
134
135        assert_eq!("[1,..,7]", a.display_n(2).to_string());
136
137        assert_eq!("[..,7]", a.display_n(1).to_string());
138
139        assert_eq!("[..]", a.display_n(0).to_string());
140    }
141}