glib/
regex.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3// rustdoc-stripper-ignore-next
4//! This module is inefficient and should not be used by Rust programs except for
5//! compatibility with GLib.Regex based APIs.
6
7use crate::{
8    ffi, translate::*, GStr, GStringPtr, MatchInfo, PtrSlice, Regex, RegexCompileFlags,
9    RegexMatchFlags,
10};
11use std::{mem, ptr};
12
13impl Regex {
14    #[doc(alias = "g_regex_get_string_number")]
15    #[doc(alias = "get_string_number")]
16    pub fn string_number(&self, name: impl IntoGStr) -> i32 {
17        name.run_with_gstr(|name| unsafe {
18            ffi::g_regex_get_string_number(self.to_glib_none().0, name.to_glib_none().0)
19        })
20    }
21
22    #[doc(alias = "g_regex_escape_nul")]
23    pub fn escape_nul(string: impl IntoGStr) -> crate::GString {
24        unsafe {
25            string.run_with_gstr(|string| {
26                from_glib_full(ffi::g_regex_escape_nul(
27                    string.to_glib_none().0,
28                    string.len() as _,
29                ))
30            })
31        }
32    }
33
34    #[doc(alias = "g_regex_escape_string")]
35    pub fn escape_string(string: impl IntoGStr) -> crate::GString {
36        unsafe {
37            string.run_with_gstr(|string| {
38                from_glib_full(ffi::g_regex_escape_string(
39                    string.to_glib_none().0,
40                    string.len() as _,
41                ))
42            })
43        }
44    }
45
46    #[doc(alias = "g_regex_check_replacement")]
47    pub fn check_replacement(replacement: impl IntoGStr) -> Result<bool, crate::Error> {
48        replacement.run_with_gstr(|replacement| unsafe {
49            let mut has_references = mem::MaybeUninit::uninit();
50            let mut error = ptr::null_mut();
51            let is_ok = ffi::g_regex_check_replacement(
52                replacement.to_glib_none().0,
53                has_references.as_mut_ptr(),
54                &mut error,
55            );
56            debug_assert_eq!(is_ok == crate::ffi::GFALSE, !error.is_null());
57            if error.is_null() {
58                Ok(from_glib(has_references.assume_init()))
59            } else {
60                Err(from_glib_full(error))
61            }
62        })
63    }
64
65    #[doc(alias = "g_regex_match_simple")]
66    pub fn match_simple(
67        pattern: impl IntoGStr,
68        string: impl IntoGStr,
69        compile_options: RegexCompileFlags,
70        match_options: RegexMatchFlags,
71    ) -> bool {
72        pattern.run_with_gstr(|pattern| {
73            string.run_with_gstr(|string| unsafe {
74                from_glib(ffi::g_regex_match_simple(
75                    pattern.to_glib_none().0,
76                    string.to_glib_none().0,
77                    compile_options.into_glib(),
78                    match_options.into_glib(),
79                ))
80            })
81        })
82    }
83
84    #[doc(alias = "g_regex_replace")]
85    pub fn replace(
86        &self,
87        string: impl IntoGStr,
88        start_position: i32,
89        replacement: impl IntoGStr,
90        match_options: RegexMatchFlags,
91    ) -> Result<crate::GString, crate::Error> {
92        unsafe {
93            string.run_with_gstr(|string| {
94                replacement.run_with_gstr(|replacement| {
95                    let mut error = ptr::null_mut();
96                    let ret = ffi::g_regex_replace(
97                        self.to_glib_none().0,
98                        string.as_ptr() as *const _,
99                        string.len() as _,
100                        start_position,
101                        replacement.to_glib_none().0,
102                        match_options.into_glib(),
103                        &mut error,
104                    );
105                    if error.is_null() {
106                        Ok(from_glib_full(ret))
107                    } else {
108                        Err(from_glib_full(error))
109                    }
110                })
111            })
112        }
113    }
114
115    #[doc(alias = "g_regex_match_all")]
116    pub fn match_all<'input>(
117        &self,
118        string: &'input GStr,
119        match_options: RegexMatchFlags,
120    ) -> Option<MatchInfo<'input>> {
121        self.match_all_full(string, 0, match_options).ok()
122    }
123
124    #[doc(alias = "g_regex_match_all_full")]
125    pub fn match_all_full<'input>(
126        &self,
127        string: &'input GStr,
128        start_position: i32,
129        match_options: RegexMatchFlags,
130    ) -> Result<MatchInfo<'input>, crate::Error> {
131        unsafe {
132            let mut match_info = ptr::null_mut();
133            let mut error = ptr::null_mut();
134            let is_ok = ffi::g_regex_match_all_full(
135                self.to_glib_none().0,
136                string.to_glib_none().0,
137                string.len() as _,
138                start_position,
139                match_options.into_glib(),
140                &mut match_info,
141                &mut error,
142            );
143            debug_assert_eq!(is_ok == crate::ffi::GFALSE, !error.is_null());
144            if error.is_null() {
145                Ok(from_glib_full(match_info))
146            } else {
147                Err(from_glib_full(error))
148            }
149        }
150    }
151
152    #[doc(alias = "g_regex_match")]
153    pub fn match_<'input>(
154        &self,
155        string: &'input GStr,
156        match_options: RegexMatchFlags,
157    ) -> Option<MatchInfo<'input>> {
158        self.match_full(string, 0, match_options).ok()
159    }
160
161    #[doc(alias = "g_regex_match_full")]
162    pub fn match_full<'input>(
163        &self,
164        string: &'input GStr,
165        start_position: i32,
166        match_options: RegexMatchFlags,
167    ) -> Result<MatchInfo<'input>, crate::Error> {
168        unsafe {
169            let mut match_info = ptr::null_mut();
170            let mut error = ptr::null_mut();
171            let is_ok = ffi::g_regex_match_full(
172                self.to_glib_none().0,
173                string.to_glib_none().0,
174                string.len() as _,
175                start_position,
176                match_options.into_glib(),
177                &mut match_info,
178                &mut error,
179            );
180            debug_assert_eq!(is_ok == crate::ffi::GFALSE, !error.is_null());
181            if error.is_null() {
182                Ok(from_glib_full(match_info))
183            } else {
184                Err(from_glib_full(error))
185            }
186        }
187    }
188
189    #[doc(alias = "g_regex_replace_literal")]
190    pub fn replace_literal(
191        &self,
192        string: impl IntoGStr,
193        start_position: i32,
194        replacement: impl IntoGStr,
195        match_options: RegexMatchFlags,
196    ) -> Result<crate::GString, crate::Error> {
197        unsafe {
198            string.run_with_gstr(|string| {
199                replacement.run_with_gstr(|replacement| {
200                    let mut error = ptr::null_mut();
201                    let ret = ffi::g_regex_replace_literal(
202                        self.to_glib_none().0,
203                        string.to_glib_none().0,
204                        string.len() as _,
205                        start_position,
206                        replacement.to_glib_none().0,
207                        match_options.into_glib(),
208                        &mut error,
209                    );
210                    if error.is_null() {
211                        Ok(from_glib_full(ret))
212                    } else {
213                        Err(from_glib_full(error))
214                    }
215                })
216            })
217        }
218    }
219
220    #[doc(alias = "g_regex_split")]
221    pub fn split(
222        &self,
223        string: impl IntoGStr,
224        match_options: RegexMatchFlags,
225    ) -> PtrSlice<GStringPtr> {
226        self.split_full(string, 0, match_options, 0)
227            .unwrap_or_default()
228    }
229
230    #[doc(alias = "g_regex_split_full")]
231    pub fn split_full(
232        &self,
233        string: impl IntoGStr,
234        start_position: i32,
235        match_options: RegexMatchFlags,
236        max_tokens: i32,
237    ) -> Result<PtrSlice<GStringPtr>, crate::Error> {
238        unsafe {
239            let mut error = ptr::null_mut();
240            string.run_with_gstr(|string| {
241                let ret = ffi::g_regex_split_full(
242                    self.to_glib_none().0,
243                    string.to_glib_none().0,
244                    string.len() as _,
245                    start_position,
246                    match_options.into_glib(),
247                    max_tokens,
248                    &mut error,
249                );
250                if error.is_null() {
251                    Ok(FromGlibPtrContainer::from_glib_full(ret))
252                } else {
253                    Err(from_glib_full(error))
254                }
255            })
256        }
257    }
258
259    #[doc(alias = "g_regex_split_simple")]
260    pub fn split_simple(
261        pattern: impl IntoGStr,
262        string: impl IntoGStr,
263        compile_options: RegexCompileFlags,
264        match_options: RegexMatchFlags,
265    ) -> PtrSlice<GStringPtr> {
266        pattern.run_with_gstr(|pattern| {
267            string.run_with_gstr(|string| unsafe {
268                FromGlibPtrContainer::from_glib_full(ffi::g_regex_split_simple(
269                    pattern.to_glib_none().0,
270                    string.to_glib_none().0,
271                    compile_options.into_glib(),
272                    match_options.into_glib(),
273                ))
274            })
275        })
276    }
277}
278
279#[cfg(test)]
280mod tests {
281    use super::*;
282    use crate::RegexCompileFlags;
283
284    #[test]
285    fn test_replace_literal() {
286        let regex = Regex::new(
287            "s[ai]mple",
288            RegexCompileFlags::OPTIMIZE,
289            RegexMatchFlags::DEFAULT,
290        )
291        .expect("Regex new")
292        .expect("Null regex");
293
294        let quote = "This is a simple sample.";
295        let result = regex
296            .replace_literal(quote, 0, "XXX", RegexMatchFlags::DEFAULT)
297            .expect("regex replace");
298
299        assert_eq!(result, "This is a XXX XXX.");
300    }
301
302    #[test]
303    fn test_split() {
304        let regex = Regex::new(
305            "s[ai]mple",
306            RegexCompileFlags::OPTIMIZE,
307            RegexMatchFlags::DEFAULT,
308        )
309        .expect("Regex new")
310        .expect("Null regex");
311
312        let quote = "This is a simple sample.";
313        let result = regex.split(quote, RegexMatchFlags::DEFAULT);
314
315        assert_eq!(result.len(), 3);
316        assert_eq!(result[0], "This is a ");
317        assert_eq!(result[1], " ");
318        assert_eq!(result[2], ".");
319    }
320}