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}