autopulse_utils/
rewrite.rs1use regex::Regex;
2use serde::{Deserialize, Serialize};
3
4#[derive(Serialize, Clone)]
24pub struct Rewrite {
25 pub(crate) rewrites: Vec<SingleRewrite>,
26 #[serde(skip)]
27 compiled: Vec<(Regex, String)>,
28}
29
30impl<'de> Deserialize<'de> for Rewrite {
31 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
32 where
33 D: serde::Deserializer<'de>,
34 {
35 #[derive(Deserialize)]
36 #[serde(untagged)]
37 enum Inner {
38 Single(SingleRewrite),
39 Multiple(Vec<SingleRewrite>),
40 }
41
42 let inner = Inner::deserialize(deserializer)?;
43
44 let rewrites = match inner {
45 Inner::Single(single) => {
46 vec![single]
47 }
48 Inner::Multiple(multiple) => multiple,
49 };
50
51 let compiled = rewrites
52 .iter()
53 .map(|r| {
54 let re = Regex::new(&r.from).map_err(|e| {
55 serde::de::Error::custom(format!(
56 "invalid regex '{}' in rewrite 'from' field: {e}",
57 r.from
58 ))
59 })?;
60 Ok((re, r.to.clone()))
61 })
62 .collect::<Result<Vec<_>, D::Error>>()?;
63
64 Ok(Self { rewrites, compiled })
65 }
66}
67
68#[derive(Serialize, Deserialize, Clone)]
69pub struct SingleRewrite {
70 pub from: String,
72 pub to: String,
74}
75
76impl Rewrite {
77 pub fn rewrite_path(&self, path: String) -> String {
78 let mut result = path;
79
80 for (from_regex, to) in &self.compiled {
81 result = from_regex.replace_all(&result, to).to_string();
82 }
83
84 result
85 }
86
87 #[cfg(test)]
88 pub fn single(from: &str, to: &str) -> Self {
89 let rewrites = vec![SingleRewrite {
90 from: from.to_string(),
91 to: to.to_string(),
92 }];
93 let compiled = rewrites
96 .iter()
97 .map(|r| {
98 let re = Regex::new(&r.from)
99 .unwrap_or_else(|e| panic!("invalid regex {:?} in test helper: {e}", r.from));
100 (re, r.to.clone())
101 })
102 .collect();
103 Self { rewrites, compiled }
104 }
105
106 #[cfg(test)]
107 pub fn multiple(rewrites: Vec<(&str, &str)>) -> Self {
108 let rewrites: Vec<SingleRewrite> = rewrites
109 .into_iter()
110 .map(|(from, to)| SingleRewrite {
111 from: from.to_string(),
112 to: to.to_string(),
113 })
114 .collect();
115 let compiled = rewrites
116 .iter()
117 .map(|r| {
118 let re = Regex::new(&r.from)
119 .unwrap_or_else(|e| panic!("invalid regex {:?} in test helper: {e}", r.from));
120 (re, r.to.clone())
121 })
122 .collect();
123 Self { rewrites, compiled }
124 }
125}