wsv/
data_model.rs

1use core::fmt;
2use std::fmt::Display;
3
4use comfy_table::modifiers::UTF8_ROUND_CORNERS;
5use comfy_table::{Attribute, Cell, Color, Table};
6
7#[derive(Default, Debug, Copy, Clone)]
8pub(crate) enum Parser {
9    Nom,
10    State,
11    Mealy,
12    Moore,
13    Split,
14    #[default]
15    First,
16}
17
18type ParserFn = &'static dyn Fn((usize, &str)) -> Result<Vec<WsvValue>, Error>;
19
20impl Parser {
21    pub fn fn_ptr(self) -> ParserFn {
22        match self {
23            Parser::First => &crate::first::parse_line,
24            Parser::Nom => &crate::nom::parse_line,
25            Parser::Split => &crate::split::parse_line,
26            Parser::State => &crate::state::parse_line,
27            Parser::Moore => &crate::moore::parse_line,
28            Parser::Mealy => &crate::mealy::parse_line,
29        }
30    }
31}
32
33#[repr(transparent)]
34pub struct Wsv(pub Vec<Result<Vec<WsvValue>, Error>>);
35
36impl fmt::Debug for Wsv {
37    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
38        write!(f, "{:?}", self.0)
39    }
40}
41
42impl Display for Wsv {
43    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
44        let mut table = Table::new();
45        table.apply_modifier(UTF8_ROUND_CORNERS);
46        for line in &self.0 {
47            match line {
48                Err(e) => {
49                    table.add_row(vec![Cell::new(e.to_string())
50                        .add_attribute(Attribute::Bold)
51                        .fg(Color::DarkRed)]);
52                }
53                Ok(line) => {
54                    table.add_row(line.iter().map(|el| {
55                        match el {
56                            WsvValue::Null => Cell::new("NULL")
57                                .add_attribute(Attribute::Bold)
58                                .fg(Color::Green),
59                            WsvValue::V(val) if val.is_empty() => Cell::new("Empty String")
60                                .add_attribute(Attribute::Bold)
61                                .fg(Color::Blue),
62                            WsvValue::V(val) => Cell::new(val),
63                        }
64                    }));
65                }
66            }
67        }
68        write!(f, "{}", table)
69    }
70}
71
72#[derive(Debug, PartialEq, Eq, Clone)]
73pub enum WsvValue {
74    V(String),
75    Null,
76}
77
78impl WsvValue {
79    pub fn new(i: &str) -> Self {
80        WsvValue::V(i.into())
81    }
82}
83impl fmt::Display for WsvValue {
84    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
85        write!(f, "{:?}", self)
86    }
87}
88
89impl From<&mut String> for WsvValue {
90    fn from(string: &mut String) -> WsvValue {
91        WsvValue::V(string.to_owned())
92    }
93}
94impl From<&str> for WsvValue {
95    fn from(string: &str) -> WsvValue {
96        WsvValue::V(string.to_owned())
97    }
98}
99impl From<String> for WsvValue {
100    fn from(string: String) -> WsvValue {
101        WsvValue::V(string)
102    }
103}
104
105#[derive(Debug)]
106pub struct Error {
107    pub kind: ErrorKind,
108    pub row: usize,
109    pub col: usize,
110    pub source: Option<Box<dyn std::error::Error>>,
111}
112impl Display for Error {
113    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
114        match &self.source {
115            Some(val) => {
116                write!(
117                    f,
118                    "{} on row {}, col {}\nCaused by {:?}",
119                    self.kind, self.row, self.col, val
120                )
121            }
122            None => {
123                write!(f, "{} on row {}, col {}", self.kind, self.row, self.col)
124            }
125        }
126    }
127}
128impl std::error::Error for Error {}
129
130#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
131pub enum ErrorKind {
132    OddDoubleQuotes,
133    MissingWhitespace,
134    Nom,
135}
136
137impl Display for ErrorKind {
138    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
139        write!(
140            f,
141            "{}",
142            match self {
143                Self::OddDoubleQuotes => "Odd number of double quotes detected",
144                Self::MissingWhitespace => "Whitespace expected",
145                Self::Nom => "Nom Error",
146            }
147        )
148    }
149}
150
151impl Error {
152    pub fn new(
153        kind: ErrorKind,
154        row: usize,
155        col: usize,
156        source: Option<Box<dyn std::error::Error>>,
157    ) -> Error {
158        Error {
159            kind,
160            row,
161            col,
162            source,
163        }
164    }
165}