1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
use std::cmp; use std::io::{self, Write}; use std::iter::IntoIterator; use std::marker::Sized; fn prepare_line<U, V>(line: U, col_widths: &mut Vec<usize>, cell_strs: &mut Vec<String>) where U: IntoIterator<Item = V>, V: ToString + Sized, { for (i, cell) in line.into_iter().enumerate() { if i >= col_widths.len() { col_widths.resize(i + 1, 0); } let cell_str = cell.to_string(); col_widths[i] = cmp::max(col_widths[i], cell_str.len()); cell_strs.push(cell_str); } } pub fn write<H, I, T, U, V, W>(mut writer: W, header: H, mat: T) -> Result<(), io::Error> where H: IntoIterator<Item = I>, I: ToString + Sized, T: IntoIterator<Item = U>, U: IntoIterator<Item = V>, V: ToString + Sized, W: Write, { let mut col_widths = vec![]; let mut cell_strs = vec![]; prepare_line(header, &mut col_widths, &mut cell_strs); for line in mat { prepare_line(line, &mut col_widths, &mut cell_strs); } let mut col = 0; let width = col_widths.len(); let mut in_header = true; for cell_str in &cell_strs { writer.write_all(format!("{}", cell_str).as_bytes())?; for _ in cell_str.len()..col_widths[col] { writer.write_all(b" ")?; } col += 1; if col == width { col = 0; writer.write_all(b"\n")?; if in_header { for (i, col_width) in (&col_widths).iter().enumerate() { for _ in 0..*col_width { writer.write_all(b"-")?; } if i < width - 1 { writer.write_all(b"-+-")?; } } writer.write_all(b"\n")?; in_header = false } } else { writer.write_all(b" | ")?; } } Ok(()) }