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