dnsi 0.2.0

A tool for investigating the DNS.
Documentation
use std::io;

use super::ansi::{ITALIC, RESET, UNDERLINE};

pub struct TableWriter<'a, const N: usize> {
    pub indent: &'a str,
    pub spacing: &'a str,
    pub header: Option<[&'a str; N]>,
    pub rows: &'a [[String; N]],
    pub enabled_columns: [bool; N],
    pub right_aligned: [bool; N],
}

impl<const N: usize> Default for TableWriter<'_, N> {
    fn default() -> Self {
        Self {
            indent: "",
            spacing: "  ",
            header: None,
            rows: &[],
            enabled_columns: [true; N],
            right_aligned: [false; N],
        }
    }
}

impl<const N: usize> TableWriter<'_, N> {
    pub fn write(&self, mut target: impl io::Write) -> io::Result<()> {
        let Self {
            indent,
            spacing,
            header,
            rows,
            enabled_columns,
            right_aligned,
        } = self;

        let mut widths = [0; N];

        if let Some(header) = header {
            for i in 0..N {
                widths[i] = header[i].len();
            }
        }

        for row in *rows {
            for i in 0..N {
                widths[i] = widths[i].max(row[i].len());
            }
        }

        let columns: Vec<_> =
            (0..N).filter(|i| enabled_columns[*i]).collect();

        if columns.is_empty() {
            return Ok(());
        }

        if let Some(header) = self.header {
            write!(target, "{indent}{UNDERLINE}{ITALIC}")?;
            for &i in &columns[..columns.len() - 1] {
                write!(
                    target,
                    "{:<width$}{spacing}",
                    header[i],
                    width = widths[i]
                )?;
            }
            let last = columns[columns.len() - 1];
            write!(target, "{:<width$}", header[last], width = widths[last])?;
            writeln!(target, "{RESET}")?;
        }

        for row in *rows {
            write!(target, "{indent}")?;
            for &i in &columns[..columns.len() - 1] {
                if right_aligned[i] {
                    write!(target, "{:>width$}", row[i], width = widths[i])?;
                } else {
                    write!(target, "{:<width$}", row[i], width = widths[i])?;
                }
                write!(target, "{spacing}")?;
            }
            let last = columns[columns.len() - 1];
            if right_aligned[last] {
                write!(
                    target,
                    "{:>width$}",
                    row[last],
                    width = widths[last]
                )?;
            } else {
                write!(
                    target,
                    "{:<width$}",
                    row[last],
                    width = widths[last]
                )?;
            }
            writeln!(target)?;
        }

        Ok(())
    }
}