Skip to content

Commit f434898

Browse files
committed
Fix bytes.zfill and integrate with str.zfill
1 parent de8b325 commit f434898

File tree

5 files changed

+29
-32
lines changed

5 files changed

+29
-32
lines changed

Lib/test/string_tests.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -840,7 +840,6 @@ def test_swapcase(self):
840840

841841
self.checkraises(TypeError, 'hello', 'swapcase', 42)
842842

843-
@unittest.skip("TODO: RUSTPYTHON test_bytes")
844843
def test_zfill(self):
845844
self.checkequal('123', '123', 'zfill', 2)
846845
self.checkequal('123', '123', 'zfill', 3)

vm/src/obj/objbytearray.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,7 @@ impl PyByteArray {
457457
}
458458

459459
#[pymethod(name = "zfill")]
460-
fn zfill(&self, width: PyIntRef) -> PyByteArray {
460+
fn zfill(&self, width: isize) -> PyByteArray {
461461
self.borrow_value().zfill(width).into()
462462
}
463463

vm/src/obj/objbyteinner.rs

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1100,24 +1100,8 @@ impl PyByteInner {
11001100
res
11011101
}
11021102

1103-
pub fn zfill(&self, width: PyIntRef) -> Vec<u8> {
1104-
if let Some(value) = width.as_bigint().to_usize() {
1105-
if value < self.elements.len() {
1106-
return self.elements.to_vec();
1107-
}
1108-
let mut res = vec![];
1109-
if self.elements.starts_with(&[b'-']) {
1110-
res.push(b'-');
1111-
res.extend_from_slice(&vec![b'0'; value - self.elements.len()]);
1112-
res.extend_from_slice(&self.elements[1..]);
1113-
} else {
1114-
res.extend_from_slice(&vec![b'0'; value - self.elements.len()]);
1115-
res.extend_from_slice(&self.elements[0..]);
1116-
}
1117-
res
1118-
} else {
1119-
self.elements.to_vec()
1120-
}
1103+
pub fn zfill(&self, width: isize) -> Vec<u8> {
1104+
bytes_zfill(&self.elements, width.to_usize().unwrap_or(0))
11211105
}
11221106

11231107
pub fn replace(
@@ -1458,3 +1442,21 @@ impl PyBytesLike {
14581442
}
14591443
}
14601444
}
1445+
1446+
pub fn bytes_zfill(bytes: &[u8], width: usize) -> Vec<u8> {
1447+
if width <= bytes.len() {
1448+
bytes.to_vec()
1449+
} else {
1450+
let (sign, s) = match bytes.first() {
1451+
Some(_sign @ b'+') | Some(_sign @ b'-') => {
1452+
(unsafe { bytes.get_unchecked(..1) }, &bytes[1..])
1453+
}
1454+
_ => (&b""[..], bytes),
1455+
};
1456+
let mut filled = Vec::new();
1457+
filled.extend_from_slice(sign);
1458+
filled.extend_from_slice(&b"0".repeat(width - bytes.len()));
1459+
filled.extend_from_slice(s);
1460+
filled
1461+
}
1462+
}

vm/src/obj/objbytes.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,7 @@ impl PyBytes {
401401
}
402402

403403
#[pymethod(name = "zfill")]
404-
fn zfill(&self, width: PyIntRef) -> PyBytes {
404+
fn zfill(&self, width: isize) -> PyBytes {
405405
self.inner.zfill(width).into()
406406
}
407407

vm/src/obj/objstr.rs

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1058,17 +1058,13 @@ impl PyString {
10581058
}
10591059

10601060
#[pymethod]
1061-
fn zfill(&self, len: usize) -> String {
1062-
let value = &self.value;
1063-
if len <= value.len() {
1064-
value.to_owned()
1065-
} else {
1066-
let mut bytes = value.bytes();
1067-
let (sign, s) = match bytes.next() {
1068-
Some(sign @ b'+') | Some(sign @ b'-') => ((sign as char).to_string(), &value[1..]),
1069-
_ => ("".to_owned(), value.as_str()),
1070-
};
1071-
format!("{}{}{}", sign, "0".repeat(len - value.len()), s,)
1061+
fn zfill(&self, width: isize) -> String {
1062+
use super::objbyteinner::bytes_zfill;
1063+
unsafe {
1064+
String::from_utf8_unchecked(bytes_zfill(
1065+
self.value.as_bytes(),
1066+
width.to_usize().unwrap_or(0),
1067+
))
10721068
}
10731069
}
10741070

0 commit comments

Comments
 (0)