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}