rust_jsc/
reg_exp.rs

1use rust_jsc_sys::{JSObjectMakeRegExp, JSValueRef};
2
3use crate::{JSContext, JSError, JSObject, JSRegExp, JSResult, JSValue};
4
5impl JSRegExp {
6    pub fn new(object: JSObject) -> Self {
7        Self { object }
8    }
9
10    /// Creates a new `JSRegExp` object.
11    ///
12    /// # Arguments
13    /// - `ctx`: The JavaScript context to create the regexp in.
14    /// - `args`: The values to initialize the regexp with.
15    ///
16    /// # Example
17    /// ```
18    /// use rust_jsc::{JSContext, JSRegExp, JSValue};
19    ///
20    /// let ctx = JSContext::new();
21    /// let regexp = JSRegExp::new_regexp(&ctx, &[JSValue::string(&ctx, "a")]).unwrap();
22    /// let result = regexp.exec(&ctx, "abc").unwrap();
23    /// assert_eq!(result.as_string().unwrap(), "a");
24    /// ```
25    ///
26    /// # Errors
27    /// If an exception is thrown while creating the regexp.
28    /// A `JSError` will be returned.
29    ///
30    /// # Returns
31    /// The new `JSRegExp` object.
32    pub fn new_regexp(ctx: &JSContext, args: &[JSValue]) -> JSResult<Self> {
33        let mut exception: JSValueRef = std::ptr::null_mut();
34        let args: Vec<JSValueRef> = args.iter().map(|arg| arg.inner).collect();
35
36        let result = unsafe {
37            JSObjectMakeRegExp(ctx.inner, args.len(), args.as_ptr(), &mut exception)
38        };
39
40        if !exception.is_null() {
41            let value = JSValue::new(exception, ctx.inner);
42            return Err(JSError::from(value));
43        }
44
45        Ok(Self::new(JSObject::from_ref(result, ctx.inner)))
46    }
47
48    /// Executes a search for a match in a specified string.
49    /// Returns the first match, or `null` if no match was found.
50    /// This is equivalent to `regexp.exec(string)` in JavaScript.
51    ///
52    /// # Arguments
53    /// - `ctx`: The JavaScript context to execute the search in.
54    /// - `string`: The string to search for a match in.
55    ///
56    /// # Returns
57    /// The first match, or `null` if no match was found.
58    ///
59    /// # Errors
60    /// If an exception is thrown while executing the search.
61    /// A `JSError` will be returned.
62    ///
63    /// # Example
64    /// ```
65    /// use rust_jsc::{JSContext, JSRegExp, JSValue};
66    ///
67    /// let ctx = JSContext::new();
68    /// let regexp = JSRegExp::new_regexp(&ctx, &[JSValue::string(&ctx, "a")]).unwrap();
69    /// let result = regexp.exec(&ctx, "abc").unwrap();
70    /// assert_eq!(result.as_string().unwrap(), "a");
71    /// ```
72    pub fn exec(&self, ctx: &JSContext, string: &str) -> JSResult<JSValue> {
73        let string = JSValue::string(ctx, string);
74        self.object
75            .get_property("exec")?
76            .as_object()?
77            .call(Some(&self.object), &[string])
78    }
79
80    /// Tests for a match in a specified string.
81    /// Returns `true` if a match was found, otherwise `false`.
82    /// This is equivalent to `regexp.test(string)` in JavaScript.
83    ///
84    /// # Arguments
85    /// - `ctx`: The JavaScript context to execute the test in.
86    /// - `string`: The string to test for a match in.
87    ///
88    /// # Example
89    /// ```
90    /// use rust_jsc::{JSContext, JSRegExp, JSValue};
91    ///
92    /// let ctx = JSContext::new();
93    /// let regexp = JSRegExp::new_regexp(&ctx, &[JSValue::string(&ctx, "a")]).unwrap();
94    /// let result = regexp.test(&ctx, "abc").unwrap();
95    /// assert_eq!(result.as_boolean(), true);
96    /// ```
97    ///
98    /// # Errors
99    /// If an exception is thrown while executing the test.
100    /// A `JSError` will be returned.
101    ///
102    /// # Returns
103    /// `true` if a match was found, otherwise `false`.
104    pub fn test(&self, ctx: &JSContext, string: &str) -> JSResult<JSValue> {
105        let string = JSValue::string(ctx, string);
106        self.object
107            .get_property("test")?
108            .as_object()?
109            .call(Some(&self.object), &[string])
110    }
111}
112
113impl From<JSRegExp> for JSObject {
114    fn from(regexp: JSRegExp) -> Self {
115        regexp.object
116    }
117}
118
119impl From<JSRegExp> for JSValue {
120    fn from(regexp: JSRegExp) -> Self {
121        regexp.object.into()
122    }
123}
124
125#[cfg(test)]
126mod tests {
127    use crate::{JSContext, JSRegExp, JSValue};
128
129    #[test]
130    fn test_regexp() {
131        let ctx = JSContext::new();
132        let regexp = JSRegExp::new_regexp(&ctx, &[JSValue::string(&ctx, "a")]).unwrap();
133        let result = regexp.exec(&ctx, "abc").unwrap();
134        assert_eq!(result.as_string().unwrap(), "a");
135
136        let result = regexp.test(&ctx, "abc").unwrap();
137        assert_eq!(result.as_boolean(), true);
138    }
139}