| 216 | } |
| 217 | |
| 218 | fn do_split( |
| 219 | vm: &VirtualMachine, |
| 220 | pattern: &PyPattern, |
| 221 | search_text: PyStrRef, |
| 222 | maxsplit: Option<PyIntRef>, |
| 223 | ) -> PyResult { |
| 224 | if maxsplit |
| 225 | .as_ref() |
| 226 | .map_or(false, |i| i.as_bigint().is_negative()) |
| 227 | { |
| 228 | return Ok(vm.ctx.new_list(vec![search_text.into()]).into()); |
| 229 | } |
| 230 | let maxsplit = maxsplit |
| 231 | .map(|i| i.try_to_primitive::<usize>(vm)) |
| 232 | .transpose()? |
| 233 | .unwrap_or(0); |
| 234 | let text = search_text.as_bytes(); |
| 235 | // essentially Regex::split, but it outputs captures as well |
| 236 | let mut output = Vec::new(); |
| 237 | let mut last = 0; |
| 238 | for (n, captures) in pattern.regex.captures_iter(text).enumerate() { |
| 239 | let full = captures.get(0).unwrap(); |
| 240 | let matched = &text[last..full.start()]; |
| 241 | last = full.end(); |
| 242 | output.push(Some(matched)); |
| 243 | for m in captures.iter().skip(1) { |
| 244 | output.push(m.map(|m| m.as_bytes())); |
| 245 | } |
| 246 | if maxsplit != 0 && n >= maxsplit { |
| 247 | break; |
| 248 | } |
| 249 | } |
| 250 | if last < text.len() { |
| 251 | output.push(Some(&text[last..])); |
| 252 | } |
| 253 | let split = output |
| 254 | .into_iter() |
| 255 | .map(|v| { |
| 256 | vm.unwrap_or_none(v.map(|v| { |
| 257 | vm.ctx |
| 258 | .new_str(String::from_utf8_lossy(v).into_owned()) |
| 259 | .into() |
| 260 | })) |
| 261 | }) |
| 262 | .collect(); |
| 263 | Ok(vm.ctx.new_list(split).into()) |
| 264 | } |
| 265 | |
| 266 | fn make_regex(vm: &VirtualMachine, pattern: &str, flags: PyRegexFlags) -> PyResult<PyPattern> { |
| 267 | let unicode = if flags.unicode && flags.ascii { |