alith_core/
parser.rs

1use crate::json::parse_json_markdown;
2use async_trait::async_trait;
3use regex::{Error as RegexError, Regex};
4use thiserror::Error;
5
6#[derive(Error, Debug)]
7pub enum ParserError {
8    #[error("Regex error: {0}")]
9    RegexError(#[from] RegexError),
10    #[error("Parsing error: {0}")]
11    ParsingError(String),
12}
13
14#[async_trait]
15pub trait Parser: Send + Sync {
16    async fn parse(&self, input: &str) -> Result<String, ParserError>;
17}
18
19#[derive(Debug, Clone, Default)]
20pub struct StringParser;
21
22#[async_trait]
23impl Parser for StringParser {
24    async fn parse(&self, input: &str) -> Result<String, ParserError> {
25        Ok(input.to_string())
26    }
27}
28
29#[derive(Debug, Clone)]
30pub struct TrimParser {
31    trim: bool,
32}
33
34impl TrimParser {
35    pub fn new(trim: bool) -> Self {
36        Self { trim }
37    }
38}
39
40impl Default for TrimParser {
41    fn default() -> Self {
42        Self { trim: true }
43    }
44}
45
46#[async_trait]
47impl Parser for TrimParser {
48    async fn parse(&self, input: &str) -> Result<String, ParserError> {
49        if self.trim {
50            Ok(input.trim().to_string())
51        } else {
52            Ok(input.to_string())
53        }
54    }
55}
56
57#[derive(Debug, Clone)]
58pub struct MarkdownParser {
59    regex: String,
60    trim: bool,
61}
62
63impl MarkdownParser {
64    pub fn new() -> Self {
65        Self {
66            regex: r"```(?:\w+)?\s*([\s\S]+?)\s*```".to_string(),
67            trim: false,
68        }
69    }
70
71    pub fn custom_expresion(mut self, regex: &str) -> Self {
72        self.regex = regex.to_string();
73        self
74    }
75
76    pub fn trim(mut self, trim: bool) -> Self {
77        self.trim = trim;
78        self
79    }
80}
81
82impl Default for MarkdownParser {
83    fn default() -> Self {
84        Self::new()
85    }
86}
87
88#[async_trait]
89impl Parser for MarkdownParser {
90    async fn parse(&self, input: &str) -> Result<String, ParserError> {
91        let re = Regex::new(&self.regex)?;
92        if let Some(cap) = re.captures(input) {
93            let find = cap[1].to_string();
94            if self.trim {
95                Ok(find.trim().to_string())
96            } else {
97                Ok(find)
98            }
99        } else {
100            Err(ParserError::ParsingError(
101                "No markdown code block found".into(),
102            ))
103        }
104    }
105}
106
107#[derive(Debug, Clone, Default)]
108pub struct JsonParser {
109    pretty: bool,
110}
111
112impl JsonParser {
113    pub fn new() -> Self {
114        Self { pretty: false }
115    }
116
117    pub fn pretty(mut self, pretty: bool) -> Self {
118        self.pretty = pretty;
119        self
120    }
121}
122
123#[async_trait]
124impl Parser for JsonParser {
125    async fn parse(&self, input: &str) -> Result<String, ParserError> {
126        match parse_json_markdown(input)
127            .map(|v| {
128                if self.pretty {
129                    serde_json::to_string_pretty(&v)
130                } else {
131                    serde_json::to_string(&v)
132                }
133            })
134            .map_err(|err| ParserError::ParsingError(err.to_string()))
135        {
136            Ok(r) => r.map_err(|err| ParserError::ParsingError(err.to_string())),
137            Err(err) => Err(err),
138        }
139    }
140}