| 416 | } |
| 417 | |
| 418 | fn sub_impl( |
| 419 | zelf: PyRef<Self>, |
| 420 | sub_args: SubArgs, |
| 421 | subn: bool, |
| 422 | vm: &VirtualMachine, |
| 423 | ) -> PyResult { |
| 424 | let SubArgs { |
| 425 | repl, |
| 426 | string, |
| 427 | count, |
| 428 | } = sub_args; |
| 429 | |
| 430 | enum FilterType<'a> { |
| 431 | Literal(PyObjectRef), |
| 432 | Callable(PyCallable<'a>), |
| 433 | Template(PyRef<Template>), |
| 434 | } |
| 435 | |
| 436 | let filter = if let Some(callable) = repl.to_callable() { |
| 437 | FilterType::Callable(callable) |
| 438 | } else { |
| 439 | let is_template = if zelf.isbytes { |
| 440 | Self::with_bytes(&repl, vm, |x| Ok(x.contains(&b'\\')))? |
| 441 | } else { |
| 442 | Self::with_str(&repl, vm, |x| Ok(x.contains("\\".as_ref())))? |
| 443 | }; |
| 444 | |
| 445 | if is_template { |
| 446 | FilterType::Template(Template::compile(zelf.clone(), repl, vm)?) |
| 447 | } else { |
| 448 | FilterType::Literal(repl) |
| 449 | } |
| 450 | }; |
| 451 | |
| 452 | with_sre_str!(zelf, &string, vm, |s| { |
| 453 | let req = s.create_request(&zelf, 0, usize::MAX); |
| 454 | let state = State::default(); |
| 455 | let mut sub_list: Vec<PyObjectRef> = Vec::new(); |
| 456 | let mut iter = SearchIter { req, state }; |
| 457 | let mut n = 0; |
| 458 | let mut last_pos = 0; |
| 459 | |
| 460 | while (count == 0 || n < count) && iter.next().is_some() { |
| 461 | if last_pos < iter.state.start { |
| 462 | /* get segment before this match */ |
| 463 | sub_list.push(s.slice(last_pos, iter.state.start, vm)); |
| 464 | } |
| 465 | |
| 466 | match &filter { |
| 467 | FilterType::Literal(literal) => sub_list.push(literal.clone()), |
| 468 | FilterType::Callable(callable) => { |
| 469 | let m = Match::new(&mut iter.state, zelf.clone(), string.clone()) |
| 470 | .into_ref(&vm.ctx); |
| 471 | sub_list.push(callable.invoke((m,), vm)?); |
| 472 | } |
| 473 | FilterType::Template(template) => { |
| 474 | let m = Match::new(&mut iter.state, zelf.clone(), string.clone()); |
| 475 | // template.expand(m)? |