renamer_rs/processor/
format.rs1use crate::Error;
2use crate::Error::{NoFormattingPatterns, UnknownFormatType};
3use log::{debug, trace};
4use regex::Regex;
5
6const FORMAT_PATTERN: &str = r"%[dse]\d+%";
7const SELECTOR_TYPE_PREFIX: &str = "%s";
8const DELIMITER_TYPE_PREFIX: &str = "%d";
9const EXTRACTOR_TYPE_PREFIX: &str = "%e";
10
11#[derive(Debug, Copy, Clone)]
13pub(super) enum FormatType {
14 Delimiter,
16 Extractor,
18 Selector,
20}
21
22#[derive(Debug, Clone)]
24pub(super) struct FormatPattern {
25 pattern: String,
26 format_type: FormatType,
27 id: usize,
28}
29
30#[derive(Debug, Clone)]
32pub struct Format {
33 value: String,
34 patterns: Vec<FormatPattern>,
35}
36
37impl FormatPattern {
38 pub(super) fn new<S: AsRef<str>>(pattern: S, format_type: FormatType, id: usize) -> Self {
40 Self {
41 pattern: pattern.as_ref().into(),
42 format_type,
43 id,
44 }
45 }
46
47 pub(super) fn format_type(&self) -> FormatType {
49 self.format_type
50 }
51
52 pub fn pattern(&self) -> &str {
54 &self.pattern
55 }
56
57 pub fn id(&self) -> usize {
59 self.id
60 }
61}
62
63impl Format {
64 pub fn new<S: AsRef<str>>(value: S) -> Result<Self, Error> {
66 Ok(Self {
67 value: value.as_ref().into(),
68 patterns: Self::get_format_patterns(value)?,
69 })
70 }
71
72 fn get_format_patterns<S: AsRef<str>>(value: S) -> Result<Vec<FormatPattern>, Error> {
73 let format_pattern = Regex::new(FORMAT_PATTERN)?;
74 let format_matches: Vec<_> = format_pattern
75 .find_iter(value.as_ref())
76 .map(|m| m.as_str().to_string())
77 .collect();
78 trace!("{:?}", format_matches);
79 if format_matches.is_empty() {
80 return Err(NoFormattingPatterns);
81 }
82
83 let mut format_patterns = Vec::with_capacity(format_matches.len());
84 for format_match in &format_matches {
85 let format_type = get_format_type(format_match)?;
86 let id = format_match
87 .get(2..format_match.len() - 1)
88 .unwrap_or_default()
89 .parse::<usize>()?;
90 format_patterns.push(FormatPattern::new(format_match, format_type, id - 1))
91 }
92 debug!("{:?}", format_patterns);
93 Ok(format_patterns)
94 }
95
96 pub fn value(&self) -> &str {
98 &self.value
99 }
100
101 pub(super) fn patterns(&self) -> &[FormatPattern] {
103 self.patterns.as_slice()
104 }
105}
106
107fn get_format_type<S: AsRef<str>>(value: S) -> Result<FormatType, Error> {
108 match value.as_ref() {
109 v if v.starts_with(DELIMITER_TYPE_PREFIX) => Ok(FormatType::Delimiter),
110 v if v.starts_with(SELECTOR_TYPE_PREFIX) => Ok(FormatType::Selector),
111 v if v.starts_with(EXTRACTOR_TYPE_PREFIX) => Ok(FormatType::Extractor),
112 _ => Err(UnknownFormatType(value.as_ref().into())),
113 }
114}