1use std::io::{Write, Error};
3use std::iter::FromIterator;
4use std::slice::{Iter, IterMut};
5use std::ops::{Index, IndexMut};
7
8use super::Terminal;
9
10use super::utils::NEWLINE;
11use super::Cell;
12use super::format::{TableFormat, ColumnPosition};
13
14#[derive(Clone, Debug, Hash, PartialEq, Eq)]
16pub struct Row {
17 cells: Vec<Cell>,
18}
19
20impl Row {
21 pub fn new(cells: Vec<Cell>) -> Row {
23 Row { cells: cells }
24 }
25
26 pub fn empty() -> Row {
28 Self::new(vec![Cell::default(); 0])
29 }
30
31 #[deprecated(since="0.8.0", note="Will become private in future release. See [issue #87](https://github.com/phsym/prettytable-rs/issues/87)")]
35 pub fn column_count(&self) -> usize {
36 self.cells.iter().map(|c| c.get_hspan()).sum()
37 }
38
39 pub fn len(&self) -> usize {
41 self.cells.len()
42 }
44
45 pub fn is_empty(&self) -> bool {
47 self.cells.is_empty()
48 }
49
50 #[deprecated(since="0.8.0", note="Will become private in future release. See [issue #87](https://github.com/phsym/prettytable-rs/issues/87)")]
52 pub fn get_height(&self) -> usize {
53 let mut height = 1; for cell in &self.cells {
55 let h = cell.get_height();
56 if h > height {
57 height = h;
58 }
59 }
60 height
61 }
62
63 #[deprecated(since="0.8.0", note="Will become private in future release. See [issue #87](https://github.com/phsym/prettytable-rs/issues/87)")]
66 pub fn get_column_width(&self, column: usize, format: &TableFormat) -> usize {
67 let mut i = 0;
68 for c in &self.cells {
69 if i + c.get_hspan()-1 >= column {
70 if c.get_hspan() == 1 {
71 return c.get_width();
72 }
73 let (lp, rp) = format.get_padding();
74 let sep = format.get_column_separator(ColumnPosition::Intern).map(|_| 1).unwrap_or_default();
75 let rem = lp + rp +sep;
76 let mut w = c.get_width();
77 if w > rem {
78 w -= rem;
79 } else {
80 w = 0;
81 }
82 return (w as f64 / c.get_hspan() as f64).ceil() as usize;
83 }
84 i += c.get_hspan();
85 }
86 0
87 }
88
89 pub fn get_cell(&self, idx: usize) -> Option<&Cell> {
91 self.cells.get(idx)
92 }
93
94 pub fn get_mut_cell(&mut self, idx: usize) -> Option<&mut Cell> {
96 self.cells.get_mut(idx)
97 }
98
99 pub fn set_cell(&mut self, cell: Cell, idx: usize) -> Result<(), &str> {
101 if idx >= self.len() {
102 return Err("Cannot find cell");
103 }
104 self.cells[idx] = cell;
105 Ok(())
106 }
107
108 pub fn add_cell(&mut self, cell: Cell) {
110 self.cells.push(cell);
111 }
112
113 pub fn insert_cell(&mut self, index: usize, cell: Cell) {
116 if index < self.cells.len() {
117 self.cells.insert(index, cell);
118 } else {
119 self.add_cell(cell);
120 }
121 }
122
123 pub fn remove_cell(&mut self, index: usize) {
125 if index < self.cells.len() {
126 self.cells.remove(index);
127 }
128 }
129
130 pub fn iter(&self) -> Iter<Cell> {
132 self.cells.iter()
133 }
134
135 pub fn iter_mut(&mut self) -> IterMut<Cell> {
137 self.cells.iter_mut()
138 }
139
140 fn __print<T: Write + ?Sized, F>(&self,
142 out: &mut T,
143 format: &TableFormat,
144 col_width: &[usize],
145 f: F)
146 -> Result<usize, Error>
147 where F: Fn(&Cell, &mut T, usize, usize, bool) -> Result<(), Error>
148 {
149 let height = self.get_height();
150 for i in 0..height {
151 out.write_all(&vec![b' '; format.get_indent()])?;
153 format.print_column_separator(out, ColumnPosition::Left)?;
154 let (lp, rp) = format.get_padding();
155 let mut j = 0;
156 let mut hspan = 0; while j+hspan < col_width.len() {
158 out.write_all(&vec![b' '; lp])?; let skip_r_fill = (j == col_width.len() - 1) &&
162 format.get_column_separator(ColumnPosition::Right).is_none();
163 match self.get_cell(j) {
164 Some(c) => {
165 let mut w = col_width[j+hspan..j+hspan+c.get_hspan()].iter().sum();
167 let real_span = c.get_hspan()-1;
168 w += real_span * (lp + rp) + real_span * format.get_column_separator(ColumnPosition::Intern).map(|_| 1).unwrap_or_default();
169 f(c, out, i, w, skip_r_fill)?;
171 hspan += real_span; },
173 None => f(&Cell::default(), out, i, col_width[j+hspan], skip_r_fill)?,
174 };
175 out.write_all(&vec![b' '; rp])?; if j+hspan < col_width.len() - 1 {
177 format.print_column_separator(out, ColumnPosition::Intern)?;
178 }
179 j+=1;
180 }
181 format.print_column_separator(out, ColumnPosition::Right)?;
182 out.write_all(NEWLINE)?;
183 }
184 Ok(height)
185 }
186
187 #[deprecated(since="0.8.0", note="Will become private in future release. See [issue #87](https://github.com/phsym/prettytable-rs/issues/87)")]
190 pub fn print<T: Write + ?Sized>(&self,
191 out: &mut T,
192 format: &TableFormat,
193 col_width: &[usize])
194 -> Result<usize, Error> {
195 self.__print(out, format, col_width, Cell::print)
196 }
197
198 #[deprecated(since="0.8.0", note="Will become private in future release. See [issue #87](https://github.com/phsym/prettytable-rs/issues/87)")]
201 pub fn print_term<T: Terminal + ?Sized>(&self,
202 out: &mut T,
203 format: &TableFormat,
204 col_width: &[usize])
205 -> Result<usize, Error> {
206 self.__print(out, format, col_width, Cell::print_term)
207 }
208}
209
210impl Default for Row {
211 fn default() -> Row {
212 Row::empty()
213 }
214}
215
216impl Index<usize> for Row {
217 type Output = Cell;
218 fn index(&self, idx: usize) -> &Self::Output {
219 &self.cells[idx]
220 }
221}
222
223impl IndexMut<usize> for Row {
224 fn index_mut(&mut self, idx: usize) -> &mut Self::Output {
225 &mut self.cells[idx]
226 }
227}
228
229impl<A: ToString> FromIterator<A> for Row {
230 fn from_iter<T>(iterator: T) -> Row
231 where T: IntoIterator<Item = A>
232 {
233 Self::new(iterator.into_iter().map(|ref e| Cell::from(e)).collect())
234 }
235}
236
237impl<T, A> From<T> for Row
238 where A: ToString,
239 T: IntoIterator<Item = A>
240{
241 fn from(it: T) -> Row {
242 Self::from_iter(it)
243 }
244}
245
246impl<'a> IntoIterator for &'a Row {
247 type Item = &'a Cell;
248 type IntoIter = Iter<'a, Cell>;
249 fn into_iter(self) -> Self::IntoIter {
250 self.iter()
251 }
252}
253
254impl<'a> IntoIterator for &'a mut Row {
263 type Item = &'a mut Cell;
264 type IntoIter = IterMut<'a, Cell>;
265 fn into_iter(self) -> Self::IntoIter {
266 self.iter_mut()
267 }
268}
269
270impl <S: ToString> Extend<S> for Row {
271 fn extend<T: IntoIterator<Item=S>>(&mut self, iter: T) {
272 self.cells.extend(iter.into_iter().map(|s| Cell::new(&s.to_string())));
273 }
274}
275
276#[macro_export]
305macro_rules! row {
306 (($($out:tt)*);) => (vec![$($out)*]);
307 (($($out:tt)*); $value:expr) => (vec![$($out)* cell!($value)]);
308 (($($out:tt)*); $value:expr, $($n:tt)*) => (row!(($($out)* cell!($value),); $($n)*));
309 (($($out:tt)*); $style:ident -> $value:expr) => (vec![$($out)* cell!($style -> $value)]);
310 (($($out:tt)*); $style:ident -> $value:expr, $($n: tt)*) => (row!(($($out)* cell!($style -> $value),); $($n)*));
311
312 ($($content:expr), *) => ($crate::Row::new(vec![$(cell!($content)), *])); ($style:ident => $($content:expr), *) => ($crate::Row::new(vec![$(cell!($style -> $content)), *]));
314 ($style:ident => $($content:expr,) *) => ($crate::Row::new(vec![$(cell!($style -> $content)), *]));
315 ($($content:tt)*) => ($crate::Row::new(row!((); $($content)*)));
316}
317
318#[cfg(test)]
319mod tests {
320 use super::*;
321 use Cell;
322
323 #[test]
324 fn row_default_empty() {
325 let row1 = Row::default();
326 assert_eq!(row1.len(), 0);
327 assert!(row1.is_empty());
328 }
329
330 #[test]
331 fn get_add_set_cell() {
332 let mut row = Row::from(vec!["foo", "bar", "foobar"]);
333 assert_eq!(row.len(), 3);
334 assert!(row.get_mut_cell(12).is_none());
335 let c1 = row.get_mut_cell(0).unwrap().clone();
336 assert_eq!(c1.get_content(), "foo");
337
338 let c1 = Cell::from(&"baz");
339 assert!(row.set_cell(c1.clone(), 1000).is_err());
340 assert!(row.set_cell(c1.clone(), 0).is_ok());
341 assert_eq!(row.get_cell(0).unwrap().get_content(), "baz");
342
343 row.add_cell(c1.clone());
344 assert_eq!(row.len(), 4);
345 assert_eq!(row.get_cell(3).unwrap().get_content(), "baz");
346 }
347
348 #[test]
349 fn insert_cell() {
350 let mut row = Row::from(vec!["foo", "bar", "foobar"]);
351 assert_eq!(row.len(), 3);
352 let cell = Cell::new("baz");
353 row.insert_cell(1000, cell.clone());
354 assert_eq!(row.len(), 4);
355 assert_eq!(row.get_cell(3).unwrap().get_content(), "baz");
356 row.insert_cell(1, cell.clone());
357 assert_eq!(row.len(), 5);
358 assert_eq!(row.get_cell(1).unwrap().get_content(), "baz");
359 }
360
361 #[test]
362 fn remove_cell() {
363 let mut row = Row::from(vec!["foo", "bar", "foobar"]);
364 assert_eq!(row.len(), 3);
365 row.remove_cell(1000);
366 assert_eq!(row.len(), 3);
367 row.remove_cell(1);
368 assert_eq!(row.len(), 2);
369 assert_eq!(row.get_cell(0).unwrap().get_content(), "foo");
370 assert_eq!(row.get_cell(1).unwrap().get_content(), "foobar");
371 }
372
373 #[test]
374 fn extend_row() {
375 let mut row = Row::from(vec!["foo", "bar", "foobar"]);
376 row.extend(vec!["A", "B", "C"]);
377 assert_eq!(row.len(), 6);
378 assert_eq!(row.get_cell(3).unwrap().get_content(), "A");
379 assert_eq!(row.get_cell(4).unwrap().get_content(), "B");
380 assert_eq!(row.get_cell(5).unwrap().get_content(), "C");
381 }
382}