1use alloc::borrow::Cow;
2use alloc::string::String;
3
4use crate::Captures;
5
6pub trait Replacer {
13 fn replace_append(&mut self, caps: &Captures<'_>, dst: &mut String);
21
22 fn no_expansion(&mut self) -> Option<Cow<str>> {
30 None
31 }
32
33 fn by_ref(&mut self) -> ReplacerRef<Self> {
55 ReplacerRef(self)
56 }
57}
58
59#[derive(Debug)]
63pub struct ReplacerRef<'a, R: ?Sized>(&'a mut R);
64
65impl<'a, R: Replacer + ?Sized + 'a> Replacer for ReplacerRef<'a, R> {
66 fn replace_append(&mut self, caps: &Captures<'_>, dst: &mut String) {
67 self.0.replace_append(caps, dst)
68 }
69 fn no_expansion(&mut self) -> Option<Cow<'_, str>> {
70 self.0.no_expansion()
71 }
72}
73
74impl<'a> Replacer for &'a str {
75 fn replace_append(&mut self, caps: &Captures<'_>, dst: &mut String) {
76 caps.expand(*self, dst);
77 }
78
79 fn no_expansion(&mut self) -> Option<Cow<'_, str>> {
80 no_expansion(self)
81 }
82}
83
84impl<'a> Replacer for &'a String {
85 fn replace_append(&mut self, caps: &Captures<'_>, dst: &mut String) {
86 self.as_str().replace_append(caps, dst)
87 }
88
89 fn no_expansion(&mut self) -> Option<Cow<'_, str>> {
90 no_expansion(self)
91 }
92}
93
94impl Replacer for String {
95 fn replace_append(&mut self, caps: &Captures<'_>, dst: &mut String) {
96 self.as_str().replace_append(caps, dst)
97 }
98
99 fn no_expansion(&mut self) -> Option<Cow<'_, str>> {
100 no_expansion(self)
101 }
102}
103
104impl<'a> Replacer for Cow<'a, str> {
105 fn replace_append(&mut self, caps: &Captures<'_>, dst: &mut String) {
106 self.as_ref().replace_append(caps, dst)
107 }
108
109 fn no_expansion(&mut self) -> Option<Cow<'_, str>> {
110 no_expansion(self)
111 }
112}
113
114impl<'a> Replacer for &'a Cow<'a, str> {
115 fn replace_append(&mut self, caps: &Captures<'_>, dst: &mut String) {
116 self.as_ref().replace_append(caps, dst)
117 }
118
119 fn no_expansion(&mut self) -> Option<Cow<'_, str>> {
120 no_expansion(self)
121 }
122}
123
124fn no_expansion<T: AsRef<str>>(t: &T) -> Option<Cow<'_, str>> {
125 let s = t.as_ref();
126 if s.contains('$') {
127 None
128 } else {
129 Some(Cow::Borrowed(s))
130 }
131}
132
133impl<F, T> Replacer for F
134where
135 F: FnMut(&Captures<'_>) -> T,
136 T: AsRef<str>,
137{
138 fn replace_append(&mut self, caps: &Captures<'_>, dst: &mut String) {
139 dst.push_str((*self)(caps).as_ref());
140 }
141}
142
143#[derive(Clone, Debug)]
152pub struct NoExpand<'t>(pub &'t str);
153
154impl<'t> Replacer for NoExpand<'t> {
155 fn replace_append(&mut self, _: &Captures<'_>, dst: &mut String) {
156 dst.push_str(self.0);
157 }
158
159 fn no_expansion(&mut self) -> Option<Cow<'_, str>> {
160 Some(Cow::Borrowed(self.0))
161 }
162}