artichoke_backend/extn/core/matchdata/
trampoline.rs1use crate::convert::implicitly_convert_to_int;
2use crate::extn::core::array::Array;
3use crate::extn::core::matchdata::{Capture, CaptureAt, CaptureExtract, MatchData};
4use crate::extn::core::regexp::Regexp;
5use crate::extn::core::string::String;
6use crate::extn::core::symbol::Symbol;
7use crate::extn::prelude::*;
8use crate::sys::protect;
9
10pub fn begin(interp: &mut Artichoke, mut value: Value, mut at: Value) -> Result<Value, Error> {
11 let data = unsafe { MatchData::unbox_from_value(&mut value, interp)? };
12 let capture = match interp.try_convert_mut(&mut at)? {
13 CaptureExtract::GroupIndex(idx) => Capture::GroupIndex(idx),
14 CaptureExtract::GroupName(name) => Capture::GroupName(name),
15 CaptureExtract::Symbol(symbol) => Capture::GroupName(symbol.bytes(interp)),
16 };
17 let begin = data.begin(capture)?;
18 match begin.map(i64::try_from) {
19 Some(Ok(begin)) => Ok(interp.convert(begin)),
20 Some(Err(_)) => Err(ArgumentError::with_message("input string too long").into()),
21 None => Ok(Value::nil()),
22 }
23}
24
25pub fn captures(interp: &mut Artichoke, mut value: Value) -> Result<Value, Error> {
26 let data = unsafe { MatchData::unbox_from_value(&mut value, interp)? };
27 if let Some(captures) = data.captures()? {
28 interp.try_convert_mut(captures)
29 } else {
30 Ok(Value::nil())
31 }
32}
33
34pub fn element_reference(
35 interp: &mut Artichoke,
36 mut value: Value,
37 mut elem: Value,
38 len: Option<Value>,
39) -> Result<Value, Error> {
40 let data = unsafe { MatchData::unbox_from_value(&mut value, interp)? };
41
42 if let Some(len) = len {
69 let start = implicitly_convert_to_int(interp, elem)?;
70 let len = implicitly_convert_to_int(interp, len)?;
71 let at = CaptureAt::StartLen(start, len);
72 let matched = data.capture_at(at)?;
73 return interp.try_convert_mut(matched);
74 }
75
76 if let Ok(symbol) = unsafe { Symbol::unbox_from_value(&mut elem, interp) } {
89 let at = CaptureAt::GroupName(symbol.bytes(interp));
90 let matched = data.capture_at(at)?;
91 return interp.try_convert_mut(matched);
92 }
93
94 if let Ok(string) = unsafe { String::unbox_from_value(&mut elem, interp) } {
121 let at = CaptureAt::GroupName(string.as_slice());
122 let matched = data.capture_at(at)?;
123 return interp.try_convert_mut(matched);
124 }
125
126 let captures_len = data.regexp.inner().captures_len(None)?;
129 let rangelen = i64::try_from(captures_len).map_err(|_| ArgumentError::with_message("input string too long"))?;
130 let at = match elem.is_range(interp, rangelen)? {
131 None => {
158 let index = implicitly_convert_to_int(interp, elem)?;
159 CaptureAt::GroupIndex(index)
160 }
161 Some(protect::Range::Out) => return Ok(Value::nil()),
168 Some(protect::Range::Valid { start, len }) => CaptureAt::StartLen(start, len),
185 };
186 let matched = data.capture_at(at)?;
187 interp.try_convert_mut(matched)
188}
189
190pub fn end(interp: &mut Artichoke, mut value: Value, mut at: Value) -> Result<Value, Error> {
191 let data = unsafe { MatchData::unbox_from_value(&mut value, interp)? };
192 let capture = match interp.try_convert_mut(&mut at)? {
193 CaptureExtract::GroupIndex(idx) => Capture::GroupIndex(idx),
194 CaptureExtract::GroupName(name) => Capture::GroupName(name),
195 CaptureExtract::Symbol(symbol) => Capture::GroupName(symbol.bytes(interp)),
196 };
197 let end = data.end(capture)?;
198 match end.map(i64::try_from) {
199 Some(Ok(end)) => Ok(interp.convert(end)),
200 Some(Err(_)) => Err(ArgumentError::with_message("input string too long").into()),
201 None => Ok(Value::nil()),
202 }
203}
204
205pub fn length(interp: &mut Artichoke, mut value: Value) -> Result<Value, Error> {
206 let data = unsafe { MatchData::unbox_from_value(&mut value, interp)? };
207 let len = data.len()?;
208 if let Ok(len) = i64::try_from(len) {
209 Ok(interp.convert(len))
210 } else {
211 Err(ArgumentError::with_message("input string too long").into())
212 }
213}
214
215pub fn named_captures(interp: &mut Artichoke, mut value: Value) -> Result<Value, Error> {
216 let data = unsafe { MatchData::unbox_from_value(&mut value, interp)? };
217 let named_captures = data.named_captures()?;
218 interp.try_convert_mut(named_captures)
219}
220
221pub fn names(interp: &mut Artichoke, mut value: Value) -> Result<Value, Error> {
222 let data = unsafe { MatchData::unbox_from_value(&mut value, interp)? };
223 let names = data.names();
224 interp.try_convert_mut(names)
225}
226
227pub fn offset(interp: &mut Artichoke, mut value: Value, mut at: Value) -> Result<Value, Error> {
228 let data = unsafe { MatchData::unbox_from_value(&mut value, interp)? };
229 let capture = match interp.try_convert_mut(&mut at)? {
230 CaptureExtract::GroupIndex(idx) => Capture::GroupIndex(idx),
231 CaptureExtract::GroupName(name) => Capture::GroupName(name),
232 CaptureExtract::Symbol(symbol) => Capture::GroupName(symbol.bytes(interp)),
233 };
234 if let Some([begin, end]) = data.offset(capture)? {
235 if let (Ok(begin), Ok(end)) = (i64::try_from(begin), i64::try_from(end)) {
236 let ary = Array::assoc(interp.convert(begin), interp.convert(end));
237 Array::alloc_value(ary, interp)
238 } else {
239 Err(ArgumentError::with_message("input string too long").into())
240 }
241 } else {
242 let ary = Array::assoc(Value::nil(), Value::nil());
243 Array::alloc_value(ary, interp)
244 }
245}
246
247pub fn post_match(interp: &mut Artichoke, mut value: Value) -> Result<Value, Error> {
248 let data = unsafe { MatchData::unbox_from_value(&mut value, interp)? };
249 let post = data.post();
250 interp.try_convert_mut(post)
251}
252
253pub fn pre_match(interp: &mut Artichoke, mut value: Value) -> Result<Value, Error> {
254 let data = unsafe { MatchData::unbox_from_value(&mut value, interp)? };
255 let pre = data.pre();
256 interp.try_convert_mut(pre)
257}
258
259pub fn regexp(interp: &mut Artichoke, mut value: Value) -> Result<Value, Error> {
260 let data = unsafe { MatchData::unbox_from_value(&mut value, interp)? };
261 let regexp = data.regexp();
262 let regexp = Regexp::alloc_value(regexp.clone(), interp)?;
270 Ok(regexp)
271}
272
273pub fn string(interp: &mut Artichoke, mut value: Value) -> Result<Value, Error> {
274 let data = unsafe { MatchData::unbox_from_value(&mut value, interp)? };
275 let mut string = interp.try_convert_mut(data.string())?;
276 string.freeze(interp)?;
277 Ok(string)
278}
279
280pub fn to_a(interp: &mut Artichoke, mut value: Value) -> Result<Value, Error> {
281 let data = unsafe { MatchData::unbox_from_value(&mut value, interp)? };
282 if let Some(ary) = data.to_a()? {
283 interp.try_convert_mut(ary)
284 } else {
285 Ok(Value::nil())
286 }
287}
288
289pub fn to_s(interp: &mut Artichoke, mut value: Value) -> Result<Value, Error> {
290 let data = unsafe { MatchData::unbox_from_value(&mut value, interp)? };
291 let display = data.to_s()?;
292 interp.try_convert_mut(display)
293}