tre_regex/wchar/comp.rs
1use std::mem;
2
3use widestring::WideStr;
4
5use crate::{
6 err::{regerror, Result},
7 flags::RegcompFlags,
8 tre, Regex,
9};
10
11impl Regex {
12 /// Compiles a regex contained in a [`WideStr`] and wraps it in a `Regex` object.
13 ///
14 /// # Arguments
15 /// * `reg`: regular expression to compile, as a [`WideStr`] .
16 /// * `flags`: [`RegcompFlags`] to pass to the function.
17 ///
18 /// # Returns
19 /// An opaque [`Regex`] object will be returned. It will be freed automatically when dropped.
20 ///
21 /// # Errors
22 /// Will return a [`RegexError`] upon failure.
23 ///
24 /// # Examples
25 /// ```
26 /// # use tre_regex::Result;
27 /// # fn main() -> Result<()> {
28 /// use tre_regex::{RegcompFlags, RegexecFlags, Regex};
29 /// use widestring::widestr;
30 ///
31 /// let regcomp_flags = RegcompFlags::new().add(RegcompFlags::BASIC);
32 /// let regexec_flags = RegexecFlags::new().add(RegexecFlags::NONE);
33 ///
34 /// let compiled_reg = Regex::new_wide(widestr!("[A-Za-z0-9]*"), regcomp_flags)?;
35 /// let matches = compiled_reg.regwexec(widestr!("hello"), 1, regexec_flags)?;
36 ///
37 /// for (i, matched) in matches.into_iter().enumerate() {
38 /// match matched {
39 /// Some(substr) => println!("Match {i}: '{}'", substr.display()),
40 /// None => println!("Match {i}: <None>"),
41 /// }
42 /// }
43 /// # Ok(())
44 /// # }
45 /// ```
46 ///
47 /// [`RegexError`]: crate::RegexError
48 pub fn new_wide(reg: &WideStr, flags: RegcompFlags) -> Result<Self> {
49 let mut unwrapped_compiled_reg = mem::MaybeUninit::<tre::regex_t>::uninit();
50
51 // SAFETY: unwrapped_compiled_reg is being initalised. reg is immutably passed and is not
52 // modified by the caller. Wrapping is also impossible.
53 #[allow(clippy::cast_possible_wrap)]
54 let result = unsafe {
55 tre::tre_regwncomp(
56 unwrapped_compiled_reg.as_mut_ptr(),
57 reg.as_ptr().cast(),
58 reg.len(),
59 flags.get(),
60 )
61 };
62
63 // SAFETY: tre::tre_regcomp fully initalises compiled_reg
64 let compiled_reg = Self(Some(unsafe { unwrapped_compiled_reg.assume_init() }));
65 if result != 0 {
66 return Err(regerror(&compiled_reg, result));
67 }
68
69 Ok(compiled_reg)
70 }
71}
72
73/// Compiles a regex that is in the form of a [`WideStr`].
74///
75/// This is a thin wrapper around [`Regex::new_wide`].
76///
77/// # Arguments
78/// * `reg`: regular expression to compile, as a [`WideStr`].
79/// * `flags`: [`RegcompFlags`] to pass to the function.
80///
81/// # Returns
82/// An opaque [`Regex`] object will be returned.
83///
84/// # Errors
85/// Will return a [`RegexError`] upon failure.
86///
87/// # Examples
88/// ```
89/// # use tre_regex::Result;
90///
91/// # fn main() -> Result<()> {
92/// use tre_regex::{RegcompFlags, RegexecFlags, regwcomp, regwexec};
93/// use widestring::widestr;
94///
95/// let regcomp_flags = RegcompFlags::new().add(RegcompFlags::EXTENDED);
96/// let regexec_flags = RegexecFlags::new().add(RegexecFlags::NONE);
97///
98/// let compiled_reg = regwcomp(widestr!("[[:digit:]]*"), regcomp_flags)?;
99/// let matches = regwexec(&compiled_reg, widestr!("01234567890"), 1, regexec_flags)?;
100///
101/// for (i, matched) in matches.into_iter().enumerate() {
102/// match matched {
103/// Some(substr) => println!("Match {i}: '{}'", substr.display()),
104/// None => println!("Match {i}: <None>"),
105/// }
106/// }
107/// # Ok(())
108/// # }
109/// ```
110///
111/// [`RegcompFlags`]: crate::RegcompFlags
112/// [`RegexError`]: crate::RegexError
113#[inline]
114pub fn regwcomp(reg: &WideStr, flags: RegcompFlags) -> Result<Regex> {
115 Regex::new_wide(reg, flags)
116}