1use std::{
2 convert::Infallible,
3 fmt::Display,
4 hash::{Hash, Hasher},
5};
6
7use serde::Serialize;
8
9use super::{
10 lexer::{Cursor, Token, TokenKind},
11 MessageKey,
12};
13
14#[derive(Debug, PartialEq, Eq, Hash, Clone)]
15pub enum FieldName {
16 Literal(String),
17 Array(usize),
18 Tuple(u8),
19 Option,
20
21 StructVariant(String),
23}
24
25impl FieldName {
26 pub fn as_str(&self) -> &str {
27 match self {
28 FieldName::Literal(s) => s.as_str(),
29 FieldName::StructVariant(s) => s.as_str(),
30 _ => "",
31 }
32 }
33}
34
35impl Display for FieldName {
36 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
37 match self {
38 FieldName::Literal(s) => s.fmt(f),
39 FieldName::Array(n) => n.fmt(f),
40 FieldName::Tuple(n) => n.fmt(f),
41 FieldName::Option => "?".fmt(f),
42 FieldName::StructVariant(s) => s.fmt(f),
43 }
44 }
45}
46
47fn names_to_string(vec: &[FieldName]) -> String {
48 let mut string = String::new();
49 for item in vec.iter() {
50 match item {
51 FieldName::Literal(s) => {
52 if !string.is_empty() {
53 string.push('.');
54 }
55 string.push_str(s);
56 }
57 FieldName::Array(n) => {
58 string.push('[');
59 string.push_str(&n.to_string());
60 string.push(']');
61 }
62 FieldName::Tuple(n) => {
63 if !string.is_empty() {
64 string.push('.');
65 }
66 string.push_str(&n.to_string());
67 }
68 FieldName::Option => string.push('?'),
69 FieldName::StructVariant(s) => {
70 string.push('[');
71 string.push_str(s);
72 string.push(']');
73 }
74 }
75 }
76 string
77}
78
79#[derive(Debug, PartialEq, Eq, Clone, Default)]
80pub struct FieldNames {
81 string: String,
82}
83
84impl Serialize for FieldNames {
85 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
86 where
87 S: serde::Serializer,
88 {
89 serializer.serialize_str(&self.string)
90 }
91}
92
93impl Hash for FieldNames {
94 fn hash<H: Hasher>(&self, state: &mut H) {
95 self.string.hash(state)
96 }
97}
98
99impl FieldNames {
100 pub(crate) fn new(string: String) -> Self {
101 Self { string }
102 }
103
104 pub fn as_str(&self) -> &str {
108 &self.string
109 }
110}
111
112impl From<Vec<FieldName>> for FieldNames {
113 fn from(value: Vec<FieldName>) -> Self {
114 Self {
115 string: names_to_string(&value),
116 }
117 }
118}
119impl From<FieldName> for FieldNames {
120 fn from(value: FieldName) -> Self {
121 let vec = vec![value];
122 Self {
123 string: names_to_string(&vec),
124 }
125 }
126}
127impl<const N: usize> From<[FieldName; N]> for FieldNames {
128 fn from(value: [FieldName; N]) -> Self {
129 let vec: Vec<_> = value.into_iter().collect();
130 Self::from(vec)
131 }
132}
133
134impl From<String> for FieldNames {
135 fn from(string: String) -> Self {
136 Self { string }
137 }
138}
139impl From<&str> for FieldNames {
140 fn from(string: &str) -> Self {
141 Self {
142 string: string.to_owned(),
143 }
144 }
145}
146
147pub trait IntoFieldName {
149 type Error: std::fmt::Display;
150 fn into_field(self) -> Result<FieldNames, Self::Error>;
151}
152
153impl IntoFieldName for &str {
154 type Error = Infallible;
155 fn into_field(self) -> Result<FieldNames, Self::Error> {
156 Ok(FieldNames {
157 string: self.to_string(),
158 })
159 }
160}
161impl IntoFieldName for u8 {
162 type Error = Infallible;
163 fn into_field(self) -> Result<FieldNames, Self::Error> {
164 Ok(FieldNames {
165 string: self.to_string(),
166 })
167 }
168}
169impl IntoFieldName for (u8, u8) {
170 type Error = Infallible;
171 fn into_field(self) -> Result<FieldNames, Self::Error> {
172 Ok(FieldNames {
173 string: format!("{}.{}", self.0, self.1),
174 })
175 }
176}
177impl IntoFieldName for (u8, u8, u8) {
178 type Error = Infallible;
179 fn into_field(self) -> Result<FieldNames, Self::Error> {
180 Ok(FieldNames {
181 string: format!("{}.{}.{}", self.0, self.1, self.2),
182 })
183 }
184}
185impl IntoFieldName for [usize; 1] {
186 type Error = Infallible;
187 fn into_field(self) -> Result<FieldNames, Self::Error> {
188 Ok(FieldNames {
189 string: format!("[{}]", self[0]),
190 })
191 }
192}
193impl<T> IntoFieldName for &'_ T
201where
202 T: IntoFieldName + Copy,
203{
204 type Error = T::Error;
205
206 fn into_field(self) -> Result<FieldNames, Self::Error> {
207 T::into_field(*self)
208 }
209}
210
211pub(crate) struct Parser<'a> {
212 source: &'a str,
213 token: Cursor<'a>,
214}
215
216impl<'a> Parser<'a> {
217 pub(crate) fn new(source: &'a str) -> Self {
218 let token = Cursor::new(source);
219 Self { source, token }
220 }
221
222 pub fn next_name(&mut self) -> Result<Option<FieldName>, ParserError> {
223 let token = self.token.advance();
224 match token.kind() {
225 TokenKind::Ident => {
226 let ident;
228 (ident, self.source) = self.source.split_at(token.len);
229 let res = FieldName::Literal(ident.to_owned());
230 self.eat_dot()?;
231 Ok(Some(res))
232 }
233 TokenKind::Dot => Err(ParserError::DotStart),
234 TokenKind::LeftBracket => {
235 self.source = &self.source[token.len..];
236 self.parse_bracket().map(Some)
237 }
238 TokenKind::Option => {
239 self.source = &self.source[token.len..];
240 let res = FieldName::Option;
241 self.eat_dot()?;
242 Ok(Some(res))
243 }
244 TokenKind::RightBracket => Err(ParserError::BracketRight),
245 TokenKind::Index => {
246 let index_str;
247 (index_str, self.source) = self.source.split_at(token.len);
248 let res = FieldName::Tuple(
249 index_str
250 .parse()
251 .map_err(|_| ParserError::ParseTupleIndex)?,
252 );
253 if !(self.expect(TokenKind::Dot)
254 || self.expect(TokenKind::LeftBracket)
255 || self.expect(TokenKind::Eof))
256 {
257 return Err(ParserError::TupleClose);
258 }
259
260 self.eat_dot()?;
261 Ok(Some(res))
262 }
263 TokenKind::Undefined => Err(ParserError::Undefined),
264 TokenKind::Eof => Ok(None),
265 }
266 }
267
268 fn parse_bracket(&mut self) -> Result<FieldName, ParserError> {
270 let mut peek = self.token.clone();
271 let t = peek.advance();
272 match t.kind() {
273 TokenKind::Index => {
274 if let Token {
275 kind: TokenKind::RightBracket,
276 ..
277 } = peek.advance()
278 {
279 let name = FieldName::Array(
280 (self.source[..t.len])
281 .parse()
282 .map_err(|_| ParserError::ParseArrayIndex)?,
283 );
284 self.token.advance();
286 self.source = &self.source[t.len..];
287 self.token.advance();
289 self.source = &self.source[1..];
290
291 if !(self.expect(TokenKind::Dot)
292 || self.expect(TokenKind::LeftBracket)
293 || self.expect(TokenKind::Eof)
294 || self.expect(TokenKind::Option))
295 {
296 return Err(ParserError::ArrayClose);
297 }
298 self.eat_dot()?;
299 return Ok(name);
300 }
301 }
302 TokenKind::Ident => {
303 if let Token {
304 kind: TokenKind::RightBracket,
305 ..
306 } = peek.advance()
307 {
308 let str;
309 (str, self.source) = self.source.split_at(t.len);
310 let name = FieldName::StructVariant(str.to_owned());
311
312 self.token.advance();
314 self.token.advance();
316 self.source = &self.source[1..];
317
318 if !(self.expect(TokenKind::Dot)
319 || self.expect(TokenKind::LeftBracket)
320 || self.expect(TokenKind::Eof)
321 || self.expect(TokenKind::Option))
322 {
323 return Err(ParserError::ArrayClose);
324 }
325
326 self.eat_dot()?;
327 return Ok(name);
328 }
329 }
330 _ => return Err(ParserError::BracketSyntaxError),
331 }
332
333 Err(ParserError::BracketSyntaxError)
334 }
335
336 fn expect(&self, token: TokenKind) -> bool {
337 let peek = self.token.clone().advance();
338 token == peek.kind
339 }
340
341 fn eat_dot(&mut self) -> Result<(), ParserError> {
342 let mut peek = self.token.clone();
343 if let Token {
344 kind: TokenKind::Dot,
345 ..
346 } = peek.advance()
347 {
348 let Token { kind, .. } = peek.advance();
349 match kind {
350 TokenKind::Eof => return Err(ParserError::DotIsLast),
351 TokenKind::LeftBracket => return Err(ParserError::DotTieLeftBracket),
352 _ => (),
353 }
354 self.token.advance();
355 self.source = &self.source[1..];
356 }
357
358 Ok(())
359 }
360}
361
362#[cfg(test)]
363pub(crate) fn parse(source: &str) -> Result<Vec<FieldName>, ParserError> {
364 let mut parser = Parser::new(source);
365
366 let mut vec = Vec::new();
367 loop {
368 match parser.next_name()? {
369 Some(name) => vec.push(name),
370 None => break Ok(vec),
371 }
372 }
373}
374
375pub fn parse_message(source: &str) -> Result<MessageKey, String> {
376 let (name_str, string) = source
377 .rsplit_once('.')
378 .ok_or("not found message".to_owned())?;
379
380 Ok(MessageKey::new(
381 FieldNames::new(name_str.to_string()),
382 string,
383 ))
384}
385
386#[derive(Debug)]
387pub(crate) enum ParserError {
388 DotStart,
389 BracketRight,
390 ParseTupleIndex,
391 TupleClose,
392 Undefined,
393 ParseArrayIndex,
394 ArrayClose,
395 BracketSyntaxError,
396 DotIsLast,
397 DotTieLeftBracket,
398}
399
400impl Display for ParserError {
401 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
402 use ParserError::*;
403 match self {
404 DotStart => "`.` can not be start".fmt(f),
405 BracketRight => "`]` should to stay behind `[`".fmt(f),
406 ParseTupleIndex => "tuple index is not u8 type".fmt(f),
407 TupleClose => "after tuple index must be `.` or `[` or eof".fmt(f),
408 Undefined => "undefined character".fmt(f),
409 ParseArrayIndex => "array index is not usize type".fmt(f),
410 ArrayClose => "after `]` must be `.` or `[` or eof".fmt(f),
411 BracketSyntaxError => "bracket syntax error".fmt(f),
412 DotIsLast => "`.` can not be end".fmt(f),
413 DotTieLeftBracket => "after `.` can not be `[`".fmt(f),
414 }
415 }
416}
417
418#[test]
419fn test_parse() {
420 let names = parse("abc").unwrap();
421 assert_eq!(names, vec![FieldName::Literal("abc".into())]);
422
423 let names = parse("name.full_name").unwrap();
424 assert_eq!(
425 names,
426 vec![
427 FieldName::Literal("name".into()),
428 FieldName::Literal("full_name".into())
429 ]
430 );
431
432 let names = parse("name.1").unwrap();
433 assert_eq!(
434 names,
435 vec![FieldName::Literal("name".into()), FieldName::Tuple(1)]
436 );
437
438 let names = parse("name[511]").unwrap();
439 assert_eq!(
440 names,
441 vec![FieldName::Literal("name".into()), FieldName::Array(511)]
442 );
443
444 let names = parse("name[age]").unwrap();
445 assert_eq!(
446 names,
447 vec![
448 FieldName::Literal("name".into()),
449 FieldName::StructVariant("age".into())
450 ]
451 );
452
453 let names = parse("5").unwrap();
454 assert_eq!(names, vec![FieldName::Tuple(5)]);
455
456 parse("511").unwrap_err();
457 parse("5age").unwrap_err();
458 parse("[5]age").unwrap_err();
459 parse(".age").unwrap_err();
460
461 let names = parse("name.age[foo]?[0]?.color.0").unwrap();
462 assert_eq!(
463 names,
464 vec![
465 FieldName::Literal("name".into()),
466 FieldName::Literal("age".into()),
467 FieldName::StructVariant("foo".into()),
468 FieldName::Option,
469 FieldName::Array(0),
470 FieldName::Option,
471 FieldName::Literal("color".into()),
472 FieldName::Tuple(0),
473 ]
474 );
475}