| 1363 | // https://docs.python.org/3/library/stdtypes.html#str.translate |
| 1364 | #[pymethod] |
| 1365 | fn translate(&self, table: PyObjectRef, vm: &VirtualMachine) -> PyResult<Wtf8Buf> { |
| 1366 | vm.get_method_or_type_error(table.clone(), identifier!(vm, __getitem__), || { |
| 1367 | format!("'{}' object is not subscriptable", table.class().name()) |
| 1368 | })?; |
| 1369 | |
| 1370 | let mut translated = Wtf8Buf::new(); |
| 1371 | for cp in self.as_wtf8().code_points() { |
| 1372 | match table.get_item(&*cp.to_u32().to_pyobject(vm), vm) { |
| 1373 | Ok(value) => { |
| 1374 | if let Some(text) = value.downcast_ref::<Self>() { |
| 1375 | translated.push_wtf8(text.as_wtf8()); |
| 1376 | } else if let Some(bigint) = value.downcast_ref::<PyInt>() { |
| 1377 | let mapped = bigint |
| 1378 | .as_bigint() |
| 1379 | .to_u32() |
| 1380 | .and_then(CodePoint::from_u32) |
| 1381 | .ok_or_else(|| { |
| 1382 | vm.new_value_error("character mapping must be in range(0x110000)") |
| 1383 | })?; |
| 1384 | translated.push(mapped); |
| 1385 | } else if !vm.is_none(&value) { |
| 1386 | return Err( |
| 1387 | vm.new_type_error("character mapping must return integer, None or str") |
| 1388 | ); |
| 1389 | } |
| 1390 | } |
| 1391 | Err(e) if e.fast_isinstance(vm.ctx.exceptions.key_error) => translated.push(cp), |
| 1392 | Err(e) => return Err(e), |
| 1393 | } |
| 1394 | } |
| 1395 | Ok(translated) |
| 1396 | } |
| 1397 | |
| 1398 | #[pystaticmethod] |
| 1399 | fn maketrans( |