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}