@@ -41,3 +41,108 @@ cfg_if::cfg_if! {
4141 pub mod root;
4242 }
4343}
44+
45+ /// Truncation helpers for truncating strings when formatting
46+ pub mod truncate {
47+ use std:: fmt;
48+
49+ #[ derive( Debug ) ]
50+ #[ must_use]
51+ /// A wrapper that truncates its contents when used.
52+ ///
53+ /// This should be used through the [`fmt::Display`] trait,
54+ /// in [`println!`] and other formatting circumstances
55+ ///
56+ /// # Examples
57+ ///
58+ /// ```rust
59+ /// # use quork::truncate::Truncate;
60+ /// let name = Truncate::new("Juliette Cordor", 8);
61+ ///
62+ /// assert_eq!(name.to_string(), "Juliette")
63+ /// ```
64+ pub struct Truncate < T > {
65+ length : usize ,
66+ data : T ,
67+ suffix : Option < String > ,
68+ }
69+
70+ impl < T > Truncate < T > {
71+ /// Construct a new [`Truncate`] from the provided data and length
72+ pub fn new ( data : T , length : usize ) -> Self {
73+ Self {
74+ length,
75+ data,
76+ suffix : None ,
77+ }
78+ }
79+
80+ /// Add a suffix to the provided [`Truncate`], to print after the truncation
81+ ///
82+ /// # Examples
83+ ///
84+ /// ```rust
85+ /// # use quork::truncate::Truncate;
86+ /// let mut name = Truncate::new("Juliette Cordor", 8).with_suffix("...");
87+ ///
88+ /// assert_eq!(name.to_string(), "Juliette...")
89+ /// ```
90+ pub fn with_suffix ( self , suffix : impl fmt:: Display ) -> Self {
91+ Self {
92+ suffix : Some ( suffix. to_string ( ) ) ,
93+ ..self
94+ }
95+ }
96+ }
97+
98+ impl < T : fmt:: Display > fmt:: Display for Truncate < T > {
99+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
100+ use fmt:: Write ;
101+ let mut truncator = TruncatedFormatter :: new ( f, self . length ) ;
102+
103+ write ! ( truncator, "{}" , self . data) ?;
104+
105+ if let Some ( ref suffix) = self . suffix {
106+ write ! ( f, "{suffix}" ) ?;
107+ }
108+
109+ Ok ( ( ) )
110+ }
111+ }
112+
113+ #[ derive( Debug ) ]
114+ #[ must_use]
115+ /// A wrapper over a writer that truncates the output to a certain length
116+ ///
117+ /// Primarily intended to be used through the [`Truncate`] struct
118+ pub struct TruncatedFormatter < ' a , T > {
119+ remaining : usize ,
120+ writer : & ' a mut T ,
121+ }
122+
123+ impl < ' a , T > TruncatedFormatter < ' a , T > {
124+ /// Construct a new [`TruncatedFormatter`] from the provided writer and length
125+ pub fn new ( writer : & ' a mut T , length : usize ) -> Self {
126+ Self {
127+ remaining : length,
128+ writer,
129+ }
130+ }
131+ }
132+
133+ impl < ' a , T > fmt:: Write for TruncatedFormatter < ' a , T >
134+ where
135+ T : fmt:: Write ,
136+ {
137+ fn write_str ( & mut self , s : & str ) -> fmt:: Result {
138+ if self . remaining < s. len ( ) {
139+ self . writer . write_str ( & s[ 0 ..self . remaining ] ) ?;
140+ self . remaining = 0 ;
141+ Ok ( ( ) )
142+ } else {
143+ self . remaining -= s. len ( ) ;
144+ self . writer . write_str ( s)
145+ }
146+ }
147+ }
148+ }
0 commit comments