path2regex/compiler/
builder.rs

1//! The Builder of the [`Compiler`](struct.Compiler.html)
2
3use anyhow::Result;
4
5use crate::{
6    internal::{type_of, FnStrWithKey},
7    try_into_with::TryIntoWith,
8    Compiler, Key, ParserOptions, Token,
9};
10
11/// The Configuration of the [`Compiler`](struct.Compiler.html)
12#[derive(Clone)]
13pub struct CompilerOptions {
14    /// Set the default delimiter for repeat parameters. (default: `'/'`)
15    pub delimiter: String,
16    /// List of characters to automatically consider prefixes when parsing.
17    pub prefixes: String,
18    /// When `true` the regexp will be case sensitive. (default: `false`)
19    pub sensitive: bool,
20    /// Function for encoding input strings for output.
21    pub encode: FnStrWithKey,
22    /// When `false` the function can produce an invalid (unmatched) path. (default: `true`)
23    pub validate: bool,
24}
25
26impl Default for CompilerOptions {
27    fn default() -> Self {
28        let ParserOptions {
29            delimiter,
30            prefixes,
31        } = ParserOptions::default();
32        Self {
33            delimiter,
34            prefixes,
35            sensitive: false,
36            encode: |x, _| x.to_owned(),
37            validate: true,
38        }
39    }
40}
41
42impl std::fmt::Display for CompilerOptions {
43    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
44        std::fmt::Debug::fmt(&self, f)
45    }
46}
47
48impl std::fmt::Debug for CompilerOptions {
49    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
50        f.debug_struct("CompilerOptions")
51            .field("delimiter", &self.delimiter)
52            .field("prefixes", &self.prefixes)
53            .field("sensitive", &self.sensitive)
54            .field("encode", &type_of(self.encode))
55            .field("validate", &self.validate)
56            .finish()
57    }
58}
59
60/// The Builder of the [`Compiler`](struct.Compiler.html)
61#[derive(Clone)]
62pub struct CompilerBuilder<I> {
63    source: I,
64    options: CompilerOptions,
65}
66
67impl<I> CompilerBuilder<I>
68where
69    I: TryIntoWith<Vec<Token>, ParserOptions>,
70{
71    /// Create a builder of the [`Compiler`](struct.Compiler.html)
72    pub fn new(source: I) -> Self {
73        Self {
74            source,
75            options: Default::default(),
76        }
77    }
78
79    /// Create a builder of the [`Compiler`](struct.Compiler.html) with the options
80    pub fn new_with_options(source: I, options: CompilerOptions) -> Self {
81        Self { source, options }
82    }
83
84    /// build a builder of the [`Compiler`](struct.Compiler.html)
85    pub fn build(&self) -> Result<Compiler> {
86        let tokens = self
87            .source
88            .clone()
89            .try_into_with(&ParserOptions::from(self.options.clone()))?;
90        let matches = tokens
91            .iter()
92            .map(|token| match token {
93                Token::Static(_) => None,
94                Token::Key(Key { pattern, .. }) => {
95                    let pattern = &format!("^(?:{pattern})$");
96                    let re = regex::RegexBuilder::new(pattern)
97                        .case_insensitive(self.options.sensitive)
98                        .build();
99                    re.ok()
100                }
101            })
102            .collect::<Vec<_>>();
103        Ok(Compiler {
104            tokens,
105            matches,
106            options: self.options.clone(),
107        })
108    }
109
110    /// Set the default delimiter for repeat parameters. (default: `'/'`)
111    pub fn set_delimiter<S>(&mut self, delimiter: S) -> &mut Self
112    where
113        S: AsRef<str>,
114    {
115        self.options.delimiter = delimiter.as_ref().to_owned();
116        self
117    }
118
119    /// List of characters to automatically consider prefixes when parsing.
120    pub fn set_prefixes<S>(&mut self, prefixes: S) -> &mut Self
121    where
122        S: AsRef<str>,
123    {
124        self.options.prefixes = prefixes.as_ref().to_owned();
125        self
126    }
127
128    /// When `true` the regexp will be case sensitive. (default: `false`)
129    pub fn set_sensitive(&mut self, yes: bool) -> &mut Self {
130        self.options.sensitive = yes;
131        self
132    }
133
134    /// Function for encoding input strings for output.
135    pub fn set_encode(&mut self, encode: FnStrWithKey) -> &mut Self {
136        self.options.encode = encode;
137        self
138    }
139
140    ///
141    pub fn set_validate(&mut self, validate: bool) -> &mut Self {
142        self.options.validate = validate;
143        self
144    }
145}