1use ferray_core::dimension::Dimension;
6use ferray_core::error::FerrayResult;
7
8use crate::string_array::StringArray;
9
10pub fn center<D: Dimension>(
17 a: &StringArray<D>,
18 width: usize,
19 fillchar: char,
20) -> FerrayResult<StringArray<D>> {
21 a.map(|s| {
22 let char_count = s.chars().count();
23 if char_count >= width {
24 return s.to_string();
25 }
26 let total_pad = width - char_count;
27 let left_pad = total_pad / 2;
28 let right_pad = total_pad - left_pad;
29 let mut result = String::with_capacity(s.len() + total_pad);
30 for _ in 0..left_pad {
31 result.push(fillchar);
32 }
33 result.push_str(s);
34 for _ in 0..right_pad {
35 result.push(fillchar);
36 }
37 result
38 })
39}
40
41pub fn ljust<D: Dimension>(a: &StringArray<D>, width: usize) -> FerrayResult<StringArray<D>> {
48 ljust_with(a, width, ' ')
49}
50
51pub fn ljust_with<D: Dimension>(
58 a: &StringArray<D>,
59 width: usize,
60 fillchar: char,
61) -> FerrayResult<StringArray<D>> {
62 a.map(|s| {
63 let char_count = s.chars().count();
64 if char_count >= width {
65 return s.to_string();
66 }
67 let pad = width - char_count;
68 let mut result = String::with_capacity(s.len() + pad * fillchar.len_utf8());
69 result.push_str(s);
70 for _ in 0..pad {
71 result.push(fillchar);
72 }
73 result
74 })
75}
76
77pub fn rjust<D: Dimension>(a: &StringArray<D>, width: usize) -> FerrayResult<StringArray<D>> {
84 rjust_with(a, width, ' ')
85}
86
87pub fn rjust_with<D: Dimension>(
94 a: &StringArray<D>,
95 width: usize,
96 fillchar: char,
97) -> FerrayResult<StringArray<D>> {
98 a.map(|s| {
99 let char_count = s.chars().count();
100 if char_count >= width {
101 return s.to_string();
102 }
103 let pad = width - char_count;
104 let mut result = String::with_capacity(s.len() + pad * fillchar.len_utf8());
105 for _ in 0..pad {
106 result.push(fillchar);
107 }
108 result.push_str(s);
109 result
110 })
111}
112
113pub fn zfill<D: Dimension>(a: &StringArray<D>, width: usize) -> FerrayResult<StringArray<D>> {
122 a.map(|s| {
123 let char_count = s.chars().count();
124 if char_count >= width {
125 return s.to_string();
126 }
127 let pad = width - char_count;
128 let (sign, rest) = if s.starts_with('+') || s.starts_with('-') {
129 (&s[..1], &s[1..])
130 } else {
131 ("", s)
132 };
133 let mut result = String::with_capacity(s.len() + pad);
134 result.push_str(sign);
135 for _ in 0..pad {
136 result.push('0');
137 }
138 result.push_str(rest);
139 result
140 })
141}
142
143#[cfg(test)]
144mod tests {
145 use super::*;
146 use crate::string_array::array;
147
148 #[test]
149 fn test_center() {
150 let a = array(&["hi", "x"]).unwrap();
151 let b = center(&a, 6, '*').unwrap();
152 assert_eq!(b.as_slice(), &["**hi**", "**x***"]);
153 }
154
155 #[test]
156 fn test_center_no_pad_needed() {
157 let a = array(&["hello"]).unwrap();
158 let b = center(&a, 3, ' ').unwrap();
159 assert_eq!(b.as_slice(), &["hello"]);
160 }
161
162 #[test]
163 fn test_ljust() {
164 let a = array(&["hi", "hello"]).unwrap();
165 let b = ljust(&a, 6).unwrap();
166 assert_eq!(b.as_slice(), &["hi ", "hello "]);
167 }
168
169 #[test]
170 fn test_ljust_no_pad_needed() {
171 let a = array(&["hello"]).unwrap();
172 let b = ljust(&a, 3).unwrap();
173 assert_eq!(b.as_slice(), &["hello"]);
174 }
175
176 #[test]
177 fn test_rjust() {
178 let a = array(&["hi", "hello"]).unwrap();
179 let b = rjust(&a, 6).unwrap();
180 assert_eq!(b.as_slice(), &[" hi", " hello"]);
181 }
182
183 #[test]
184 fn test_ljust_with_fillchar() {
185 let a = array(&["hi"]).unwrap();
186 let b = ljust_with(&a, 6, '-').unwrap();
187 assert_eq!(b.as_slice(), &["hi----"]);
188 }
189
190 #[test]
191 fn test_rjust_with_fillchar() {
192 let a = array(&["hi"]).unwrap();
193 let b = rjust_with(&a, 6, '.').unwrap();
194 assert_eq!(b.as_slice(), &["....hi"]);
195 }
196
197 #[test]
198 fn test_ljust_with_unicode_fillchar() {
199 let a = array(&["ab"]).unwrap();
200 let b = ljust_with(&a, 5, '★').unwrap();
201 assert_eq!(b.as_slice(), &["ab★★★"]);
202 }
203
204 #[test]
205 fn test_zfill() {
206 let a = array(&["42", "-17", "+5", "abc"]).unwrap();
207 let b = zfill(&a, 5).unwrap();
208 assert_eq!(b.as_slice(), &["00042", "-0017", "+0005", "00abc"]);
209 }
210
211 #[test]
212 fn test_zfill_no_pad_needed() {
213 let a = array(&["12345"]).unwrap();
214 let b = zfill(&a, 3).unwrap();
215 assert_eq!(b.as_slice(), &["12345"]);
216 }
217}