table_extractor/parser/
mysql.rs1use crate::error::Result;
2use crate::{Parser, Table};
3
4pub struct MySqlParser;
5
6impl Parser for MySqlParser {
7 fn parse(&self, input: &str) -> Result<Table> {
8 let lines: Vec<&str> = input.lines().collect();
9
10 if lines.is_empty() {
11 return Ok(Table::new(vec![], vec![]));
12 }
13
14 let mut headers = Vec::new();
15 let mut rows = Vec::new();
16
17 for line in lines {
18 let trimmed = line.trim();
19
20 if trimmed.is_empty() || trimmed.starts_with('+') {
22 continue;
23 }
24
25 if trimmed.starts_with('|') && trimmed.ends_with('|') {
27 let cells = parse_mysql_row(trimmed);
28
29 if headers.is_empty() {
30 headers = cells;
31 } else {
32 rows.push(cells);
33 }
34 }
35 }
36
37 Table::new_validated(headers, rows)
38 }
39}
40
41fn parse_mysql_row(line: &str) -> Vec<String> {
42 let trimmed = line.trim().trim_start_matches('|').trim_end_matches('|');
44
45 let estimated_cols = trimmed.chars().filter(|&c| c == '|').count() + 1;
47 let mut cells = Vec::with_capacity(estimated_cols);
48
49 for cell in trimmed.split('|') {
52 cells.push(cell.trim().to_string());
53 }
54
55 cells
56}
57
58#[cfg(test)]
59mod tests {
60 use super::*;
61
62 #[test]
63 fn test_parse_mysql() {
64 let input = r#"+----+----------------------------+
65| id | name |
66+----+----------------------------+
67| 1 | Preston Carlton's Company |
68| 2 | Fawzia Masud's Company |
69+----+----------------------------+"#;
70
71 let parser = MySqlParser;
72 let table = parser.parse(input).unwrap();
73
74 assert_eq!(table.headers(), &["id", "name"]);
75 assert_eq!(table.rows().len(), 2);
76 assert_eq!(table.rows()[0], vec!["1", "Preston Carlton's Company"]);
77 assert_eq!(table.rows()[1], vec!["2", "Fawzia Masud's Company"]);
78 }
79}