kalosm_sample/structured_parser/
parse.rs1use crate::{CreateParserState, SendCreateParserState, SeparatedParser};
2use crate::{
3 IntegerParser, LiteralParser, ParseStatus, Parser, ParserExt, SequenceParser, StringParser,
4};
5
6use super::Either;
7
8pub trait Parse: Clone + Send + Sync {
55 fn new_parser() -> impl SendCreateParserState<Output = Self>;
57}
58
59impl<T: Parse> Parse for Box<T> {
60 fn new_parser() -> impl SendCreateParserState<Output = Self> {
61 T::new_parser().map_output(Box::new)
62 }
63}
64
65macro_rules! int_parser {
66 ($ty:ident, $num:ty, $test:ident) => {
67 #[doc = "A parser for `"]
68 #[doc = stringify!($num)]
69 #[doc = "`."]
70 #[derive(Clone, Debug)]
71 pub struct $ty {
72 parser: IntegerParser,
73 }
74
75 impl $ty {
76 pub fn new() -> Self {
78 Self::default()
79 }
80
81 pub fn with_range(mut self, range: std::ops::RangeInclusive<$num>) -> Self {
83 let start = range.start();
84 let end = range.end();
85 self.parser = IntegerParser::new(*start as i128..=*end as i128);
86 self
87 }
88 }
89
90 impl Default for $ty {
91 fn default() -> Self {
92 Self {
93 parser: IntegerParser::new((<$num>::MIN as i128)..=(<$num>::MAX as i128)),
94 }
95 }
96 }
97
98 impl CreateParserState for $ty {
99 fn create_parser_state(&self) -> <Self as Parser>::PartialState {
100 self.parser.create_parser_state()
101 }
102 }
103
104 impl Parser for $ty {
105 type Output = $num;
106 type PartialState = <IntegerParser as Parser>::PartialState;
107
108 fn parse<'a>(
109 &self,
110 state: &Self::PartialState,
111 input: &'a [u8],
112 ) -> crate::ParseResult<ParseStatus<'a, Self::PartialState, Self::Output>> {
113 self.parser
114 .parse(state, input)
115 .map(|result| result.map(|output| output as $num))
116 }
117 }
118
119 impl Parse for $num {
120 fn new_parser() -> impl SendCreateParserState<Output = Self> {
121 $ty::default()
122 }
123 }
124
125 #[test]
126 fn $test() {
127 let parser = <$num as Parse>::new_parser();
128 let state = parser.create_parser_state();
129 for _ in 0..100 {
130 let input = rand::random::<$num>();
131 let input_str = input.to_string() + "\n";
132 println!("input: {:?}", input_str);
133 let result = parser.parse(&state, input_str.as_bytes());
134 if let ParseStatus::Finished {
135 result: input,
136 remaining: b"\n",
137 } = result.unwrap()
138 {
139 assert_eq!(input, input);
140 } else {
141 panic!("Parser did not finish");
142 }
143 }
144 }
145 };
146}
147
148int_parser!(U8Parser, u8, test_u8);
149int_parser!(U16Parser, u16, test_u16);
150int_parser!(U32Parser, u32, test_u32);
151int_parser!(U64Parser, u64, test_u64);
152int_parser!(I8Parser, i8, test_i8);
153int_parser!(I16Parser, i16, test_i16);
154int_parser!(I32Parser, i32, test_i32);
155int_parser!(I64Parser, i64, test_i64);
156
157impl Parse for String {
158 fn new_parser() -> impl SendCreateParserState<Output = Self> {
159 StringParser::new(0..=usize::MAX)
160 }
161}
162
163impl<T: Parse + Clone + Send + Sync> Parse for std::vec::Vec<T> {
164 fn new_parser() -> impl SendCreateParserState<Output = Self> {
165 SequenceParser::new(
166 LiteralParser::new("["),
167 SequenceParser::new(
168 SeparatedParser::new(T::new_parser(), LiteralParser::new(", "), 0..=usize::MAX),
169 LiteralParser::new("]"),
170 ),
171 )
172 .map_output(|((), (outputs, ()))| outputs)
173 }
174}
175
176impl<const N: usize, T: Parse + Clone + Send + Sync> Parse for [T; N] {
177 fn new_parser() -> impl SendCreateParserState<Output = Self> {
178 SequenceParser::new(
179 LiteralParser::new("["),
180 SequenceParser::new(
181 SeparatedParser::new(T::new_parser(), LiteralParser::new(", "), N..=N),
182 LiteralParser::new("]"),
183 ),
184 )
185 .map_output(|((), (outputs, ()))| {
186 outputs
187 .try_into()
188 .unwrap_or_else(|_| panic!("Array is not the correct size"))
189 })
190 }
191}
192
193impl<T: Parse> Parse for Option<T> {
194 fn new_parser() -> impl SendCreateParserState<Output = Self> {
195 let parser = T::new_parser();
196 parser
197 .map_output(|output| Some(output))
198 .or(LiteralParser::new("null").map_output(|_| None))
199 }
200}
201
202impl Parse for bool {
203 fn new_parser() -> impl SendCreateParserState<Output = Self> {
204 LiteralParser::new("true")
205 .otherwise(LiteralParser::new("false"))
206 .map_output(|output| matches!(output, Either::Left(_)))
207 }
208}