Skip to content

Commit 75ebaed

Browse files
committed
Fix {bytes|bytearray}.{|r|l}strip
1 parent fc2949c commit 75ebaed

File tree

4 files changed

+46
-67
lines changed

4 files changed

+46
-67
lines changed

Lib/test/string_tests.py

-2
Original file line numberDiff line numberDiff line change
@@ -777,7 +777,6 @@ def test_additional_rsplit(self):
777777
self.checkequal(['arf', 'barf'], b, 'rsplit', None)
778778
self.checkequal(['arf', 'barf'], b, 'rsplit', None, 2)
779779

780-
@unittest.skip("TODO: RUSTPYTHON test_bytes")
781780
def test_strip_whitespace(self):
782781
self.checkequal('hello', ' hello ', 'strip')
783782
self.checkequal('hello ', ' hello ', 'lstrip')
@@ -795,7 +794,6 @@ def test_strip_whitespace(self):
795794
self.checkequal(' hello', ' hello ', 'rstrip', None)
796795
self.checkequal('hello', 'hello', 'strip', None)
797796

798-
@unittest.skip("TODO: RUSTPYTHON test_bytes")
799797
def test_strip(self):
800798
# strip/lstrip/rstrip with str arg
801799
self.checkequal('hello', 'xyzzyhelloxyzzy', 'strip', 'xyz')

vm/src/obj/objbytearray.rs

+9-18
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ use std::sync::{RwLock, RwLockReadGuard, RwLockWriteGuard};
55

66
use super::objbyteinner::{
77
ByteInnerExpandtabsOptions, ByteInnerFindOptions, ByteInnerNewOptions, ByteInnerPaddingOptions,
8-
ByteInnerPosition, ByteInnerSplitOptions, ByteInnerSplitlinesOptions,
9-
ByteInnerTranslateOptions, ByteOr, PyByteInner,
8+
ByteInnerSplitOptions, ByteInnerSplitlinesOptions, ByteInnerTranslateOptions, ByteOr,
9+
PyByteInner,
1010
};
1111
use super::objint::PyIntRef;
1212
use super::objiter;
@@ -15,7 +15,7 @@ use super::objstr::{PyString, PyStringRef};
1515
use super::objtuple::PyTupleRef;
1616
use super::objtype::PyClassRef;
1717
use crate::cformat::CFormatString;
18-
use crate::function::OptionalArg;
18+
use crate::function::{OptionalArg, OptionalOption};
1919
use crate::obj::objstr::do_cformat_string;
2020
use crate::pyobject::{
2121
Either, PyClassImpl, PyComparisonValue, PyContext, PyIterable, PyObjectRef, PyRef, PyResult,
@@ -373,27 +373,18 @@ impl PyByteArray {
373373
}
374374

375375
#[pymethod(name = "strip")]
376-
fn strip(&self, chars: OptionalArg<PyByteInner>) -> PyResult<PyByteArray> {
377-
Ok(self
378-
.borrow_value()
379-
.strip(chars, ByteInnerPosition::All)?
380-
.into())
376+
fn strip(&self, chars: OptionalOption<PyByteInner>) -> PyByteArray {
377+
self.borrow_value().strip(chars).into()
381378
}
382379

383380
#[pymethod(name = "lstrip")]
384-
fn lstrip(&self, chars: OptionalArg<PyByteInner>) -> PyResult<PyByteArray> {
385-
Ok(self
386-
.borrow_value()
387-
.strip(chars, ByteInnerPosition::Left)?
388-
.into())
381+
fn lstrip(&self, chars: OptionalOption<PyByteInner>) -> PyByteArray {
382+
self.borrow_value().lstrip(chars).into()
389383
}
390384

391385
#[pymethod(name = "rstrip")]
392-
fn rstrip(&self, chars: OptionalArg<PyByteInner>) -> PyResult<PyByteArray> {
393-
Ok(self
394-
.borrow_value()
395-
.strip(chars, ByteInnerPosition::Right)?
396-
.into())
386+
fn rstrip(&self, chars: OptionalOption<PyByteInner>) -> PyByteArray {
387+
self.borrow_value().rstrip(chars).into()
397388
}
398389

399390
#[pymethod(name = "split")]

vm/src/obj/objbyteinner.rs

+29-38
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use super::objsequence::{is_valid_slice_arg, PySliceableSequence};
1515
use super::objslice::PySliceRef;
1616
use super::objstr::{self, adjust_indices, PyString, PyStringRef, StringRange};
1717
use super::objtuple::PyTupleRef;
18-
use crate::function::OptionalArg;
18+
use crate::function::{OptionalArg, OptionalOption};
1919
use crate::pyhash;
2020
use crate::pyobject::{
2121
Either, PyComparisonValue, PyIterable, PyObjectRef, PyResult, ThreadSafe, TryFromObject,
@@ -938,40 +938,37 @@ impl PyByteInner {
938938
Ok(res)
939939
}
940940

941-
pub fn strip(
942-
&self,
943-
chars: OptionalArg<PyByteInner>,
944-
position: ByteInnerPosition,
945-
) -> PyResult<Vec<u8>> {
946-
let is_valid_char = |c| {
947-
if let OptionalArg::Present(ref bytes) = chars {
948-
bytes.elements.contains(c)
949-
} else {
950-
c.is_ascii_whitespace()
951-
}
941+
pub fn strip(&self, chars: OptionalOption<PyByteInner>) -> Vec<u8> {
942+
let chars = chars.flat_option();
943+
let chars = match chars {
944+
Some(ref chars) => &chars.elements,
945+
None => return self.elements.trim().to_owned(),
952946
};
947+
self.elements
948+
.trim_with(|c| chars.contains(&(c as u8)))
949+
.to_owned()
950+
}
953951

954-
let mut start = 0;
955-
let mut end = self.len();
956-
957-
if let ByteInnerPosition::Left | ByteInnerPosition::All = position {
958-
for (i, c) in self.elements.iter().enumerate() {
959-
if !is_valid_char(c) {
960-
start = i;
961-
break;
962-
}
963-
}
964-
}
952+
pub fn lstrip(&self, chars: OptionalOption<PyByteInner>) -> Vec<u8> {
953+
let chars = chars.flat_option();
954+
let chars = match chars {
955+
Some(ref chars) => &chars.elements,
956+
None => return self.elements.trim_start().to_owned(),
957+
};
958+
self.elements
959+
.trim_start_with(|c| chars.contains(&(c as u8)))
960+
.to_owned()
961+
}
965962

966-
if let ByteInnerPosition::Right | ByteInnerPosition::All = position {
967-
for (i, c) in self.elements.iter().rev().enumerate() {
968-
if !is_valid_char(c) {
969-
end = self.len() - i;
970-
break;
971-
}
972-
}
973-
}
974-
Ok(self.elements[start..end].to_vec())
963+
pub fn rstrip(&self, chars: OptionalOption<PyByteInner>) -> Vec<u8> {
964+
let chars = chars.flat_option();
965+
let chars = match chars {
966+
Some(ref chars) => &chars.elements,
967+
None => return self.elements.trim_end().to_owned(),
968+
};
969+
self.elements
970+
.trim_end_with(|c| chars.contains(&(c as u8)))
971+
.to_owned()
975972
}
976973

977974
pub fn split(&self, options: ByteInnerSplitOptions, reverse: bool) -> PyResult<Vec<&[u8]>> {
@@ -1213,12 +1210,6 @@ pub trait ByteOr: ToPrimitive {
12131210

12141211
impl ByteOr for BigInt {}
12151212

1216-
pub enum ByteInnerPosition {
1217-
Left,
1218-
Right,
1219-
All,
1220-
}
1221-
12221213
fn split_slice<'a>(slice: &'a [u8], sep: &[u8], maxsplit: isize) -> Vec<&'a [u8]> {
12231214
let mut splitted: Vec<&[u8]> = vec![];
12241215
let mut prev_index = 0;

vm/src/obj/objbytes.rs

+8-9
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@ use std::ops::Deref;
44

55
use super::objbyteinner::{
66
ByteInnerExpandtabsOptions, ByteInnerFindOptions, ByteInnerNewOptions, ByteInnerPaddingOptions,
7-
ByteInnerPosition, ByteInnerSplitOptions, ByteInnerSplitlinesOptions,
8-
ByteInnerTranslateOptions, PyByteInner,
7+
ByteInnerSplitOptions, ByteInnerSplitlinesOptions, ByteInnerTranslateOptions, PyByteInner,
98
};
109
use super::objint::PyIntRef;
1110
use super::objiter;
@@ -14,7 +13,7 @@ use super::objstr::{PyString, PyStringRef};
1413
use super::objtuple::PyTupleRef;
1514
use super::objtype::PyClassRef;
1615
use crate::cformat::CFormatString;
17-
use crate::function::OptionalArg;
16+
use crate::function::{OptionalArg, OptionalOption};
1817
use crate::obj::objstr::do_cformat_string;
1918
use crate::pyhash;
2019
use crate::pyobject::{
@@ -329,18 +328,18 @@ impl PyBytes {
329328
}
330329

331330
#[pymethod(name = "strip")]
332-
fn strip(&self, chars: OptionalArg<PyByteInner>) -> PyResult<PyBytes> {
333-
Ok(self.inner.strip(chars, ByteInnerPosition::All)?.into())
331+
fn strip(&self, chars: OptionalOption<PyByteInner>) -> PyBytes {
332+
self.inner.strip(chars).into()
334333
}
335334

336335
#[pymethod(name = "lstrip")]
337-
fn lstrip(&self, chars: OptionalArg<PyByteInner>) -> PyResult<PyBytes> {
338-
Ok(self.inner.strip(chars, ByteInnerPosition::Left)?.into())
336+
fn lstrip(&self, chars: OptionalOption<PyByteInner>) -> PyBytes {
337+
self.inner.lstrip(chars).into()
339338
}
340339

341340
#[pymethod(name = "rstrip")]
342-
fn rstrip(&self, chars: OptionalArg<PyByteInner>) -> PyResult<PyBytes> {
343-
Ok(self.inner.strip(chars, ByteInnerPosition::Right)?.into())
341+
fn rstrip(&self, chars: OptionalOption<PyByteInner>) -> PyBytes {
342+
self.inner.rstrip(chars).into()
344343
}
345344

346345
#[pymethod(name = "split")]

0 commit comments

Comments
 (0)