Skip to content

Commit cf70323

Browse files
committed
add replace
1 parent b60d741 commit cf70323

File tree

3 files changed

+77
-0
lines changed

3 files changed

+77
-0
lines changed

tests/snippets/bytes.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -574,3 +574,11 @@
574574
assert b"-42".zfill(5) == b"-0042"
575575
assert b"42".zfill(1) == b"42"
576576
assert b"42".zfill(-1) == b"42"
577+
578+
# replace
579+
assert b"123456789123".replace(b"23", b"XX") == b'1XX4567891XX'
580+
assert b"123456789123".replace(b"23", b"XX", 1) == b'1XX456789123'
581+
assert b"123456789123".replace(b"23", b"XX", 0) == b"123456789123"
582+
assert b"123456789123".replace(b"23", b"XX", -1) == b'1XX4567891XX'
583+
assert b"123456789123".replace(b"23", b"") == b"14567891"
584+

vm/src/obj/objbyteinner.rs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -972,6 +972,64 @@ impl PyByteInner {
972972
self.elements.to_vec()
973973
}
974974
}
975+
976+
pub fn replace(
977+
&self,
978+
old: PyObjectRef,
979+
new: PyObjectRef,
980+
count: OptionalArg<PyIntRef>,
981+
vm: &VirtualMachine,
982+
) -> PyResult<Vec<u8>> {
983+
let old = match try_as_bytes_like(&old) {
984+
Some(value) => value,
985+
None => {
986+
return Err(
987+
vm.new_type_error(format!("a bytes-like object is required, not {}", old))
988+
);
989+
}
990+
};
991+
992+
let new = match try_as_bytes_like(&new) {
993+
Some(value) => value,
994+
None => {
995+
return Err(
996+
vm.new_type_error(format!("a bytes-like object is required, not {}", new))
997+
);
998+
}
999+
};
1000+
1001+
let count = if let OptionalArg::Present(int) = count {
1002+
if let Some(value) = int.as_bigint().to_u32() {
1003+
value
1004+
} else {
1005+
self.elements.len() as u32
1006+
}
1007+
} else {
1008+
self.elements.len() as u32
1009+
};
1010+
1011+
let mut res = vec![];
1012+
let mut index = 0;
1013+
let mut done = 0;
1014+
1015+
let slice = &self.elements;
1016+
while index <= slice.len() - old.len() {
1017+
if done == count {
1018+
res.extend_from_slice(&slice[index..]);
1019+
break;
1020+
}
1021+
if &slice[index..index + old.len()] == old.as_slice() {
1022+
res.extend_from_slice(&new);
1023+
index += old.len();
1024+
done += 1;
1025+
} else {
1026+
res.push(slice[index]);
1027+
index += 1
1028+
}
1029+
}
1030+
1031+
Ok(res)
1032+
}
9751033
}
9761034

9771035
pub fn try_as_byte(obj: &PyObjectRef) -> Option<Vec<u8>> {

vm/src/obj/objbytes.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,17 @@ impl PyBytesRef {
396396
fn zfill(self, width: PyIntRef, vm: &VirtualMachine) -> PyResult {
397397
Ok(vm.ctx.new_bytes(self.inner.zfill(width)))
398398
}
399+
400+
#[pymethod(name = "replace")]
401+
fn replace(
402+
self,
403+
old: PyObjectRef,
404+
new: PyObjectRef,
405+
count: OptionalArg<PyIntRef>,
406+
vm: &VirtualMachine,
407+
) -> PyResult {
408+
Ok(vm.ctx.new_bytes(self.inner.replace(old, new, count, vm)?))
409+
}
399410
}
400411

401412
#[derive(Debug)]

0 commit comments

Comments
 (0)