chroma_types/regex/mod.rs
1pub mod hir;
2pub mod literal_expr;
3
4use hir::ChromaHir;
5use regex::Regex;
6use regex_syntax::{hir::Properties, parse};
7use thiserror::Error;
8
9/// Chroma custom wrapper for a Regex pattern.
10///
11/// The `ChromaRegex` struct should represent a regex pattern that is supported by Chroma, and
12/// it could be safely used by further implementations. During construction of this struct we
13/// will perform all necessary validation to check this.
14///
15/// We would like to leverage the regex_syntax crate to provide basic parsing and simplification
16/// of regex expression, and in the process guard against unsupported features by examing the
17/// parsed syntax tree.
18#[derive(Clone, Debug)]
19pub struct ChromaRegex {
20 hir: ChromaHir,
21 pattern: String,
22 properties: Properties,
23}
24
25#[derive(Debug, Error)]
26pub enum ChromaRegexError {
27 #[error("Byte pattern is not allowed")]
28 BytePattern,
29 // NOTE: regex::Error is a large type, so we only store its error message here.
30 #[error("Unexpected regex error: {0}")]
31 Regex(String),
32 // NOTE: regex_syntax::Error is a large type, so we only store its error message here.
33 #[error("Regex syntax errror: {0}")]
34 RegexSyntax(String),
35}
36
37impl ChromaRegex {
38 pub fn hir(&self) -> &ChromaHir {
39 &self.hir
40 }
41 pub fn properties(&self) -> &Properties {
42 &self.properties
43 }
44 pub fn regex(&self) -> Result<Regex, ChromaRegexError> {
45 // NOTE: Although this method return a Result<_, _> type, in practice it should always
46 // be Ok(_) becasue we validate the pattern during struct construction. Specifically,
47 // we verify that the pattern can be properly parsed and is thus a valid pattern supported
48 // by the regex crate.
49 Regex::new(&self.pattern).map_err(|e| ChromaRegexError::Regex(e.to_string()))
50 }
51}
52
53impl TryFrom<String> for ChromaRegex {
54 type Error = ChromaRegexError;
55
56 fn try_from(value: String) -> Result<Self, Self::Error> {
57 let hir = parse(&value).map_err(|e| ChromaRegexError::RegexSyntax(e.to_string()))?;
58 let properties = hir.properties().clone();
59 Ok(Self {
60 hir: hir.try_into()?,
61 pattern: value,
62 properties,
63 })
64 }
65}