Skip to content

Commit bd21667

Browse files
committed
add bytes index and find
1 parent 8a7c46d commit bd21667

File tree

3 files changed

+89
-0
lines changed

3 files changed

+89
-0
lines changed

tests/snippets/bytes.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,3 +207,28 @@
207207
assert b"abcde".startswith(b"cd", 2)
208208
assert not b"abcde".startswith(b"cd", 1, 4)
209209
assert b"abcde".startswith((b"a", b"bc"))
210+
211+
212+
# index find
213+
assert b"abcd".index(b"cd") == 2
214+
assert b"abcd".index(b"cd", 0) == 2
215+
assert b"abcd".index(b"cd", 1) == 2
216+
assert b"abcd".index(99) == 2
217+
with assertRaises(ValueError):
218+
b"abcde".index(b"c", 3, 1)
219+
with assertRaises(ValueError):
220+
b"abcd".index(b"cdaaaaa")
221+
with assertRaises(ValueError):
222+
b"abcd".index(b"b", 3, 4)
223+
with assertRaises(ValueError):
224+
b"abcd".index(1)
225+
226+
227+
assert b"abcd".find(b"cd") == 2
228+
assert b"abcd".find(b"cd", 0) == 2
229+
assert b"abcd".find(b"cd", 1) == 2
230+
assert b"abcde".find(b"c", 3, 1) == -1
231+
assert b"abcd".find(b"cdaaaaa") == -1
232+
assert b"abcd".find(b"b", 3, 4) == -1
233+
assert b"abcd".find(1) == -1
234+
assert b"abcd".find(99) == 2

vm/src/obj/objbyteinner.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -552,6 +552,44 @@ impl PyByteInner {
552552

553553
Ok(vm.new_bool(suff.as_slice() == &self.elements.do_slice(range)[offset]))
554554
}
555+
556+
pub fn find(
557+
&self,
558+
sub: PyObjectRef,
559+
start: OptionalArg<PyObjectRef>,
560+
end: OptionalArg<PyObjectRef>,
561+
vm: &VirtualMachine,
562+
) -> Result<isize, PyObjectRef> {
563+
let sub = match try_as_bytes_like(&sub) {
564+
Some(value) => value,
565+
None => match_class!(sub,
566+
i @ PyInt =>
567+
vec![i.as_bigint().byte_or(vm)?],
568+
obj => {return Err(vm.new_type_error(format!("a bytes-like object is required, not {}", obj)));}),
569+
};
570+
571+
let range = self.elements.get_slice_range(
572+
&is_valid_slice_arg(start, vm)?,
573+
&is_valid_slice_arg(end, vm)?,
574+
);
575+
576+
// not allowed for this method
577+
if range.end < range.start {
578+
return Ok(-1isize);
579+
}
580+
581+
let start = range.start;
582+
583+
let slice = &self.elements[range];
584+
for (n, _) in slice.iter().enumerate() {
585+
if n + sub.len() <= slice.len()
586+
&& &slice[n..n + sub.len()] == sub.as_slice()
587+
{
588+
return Ok((start+n) as isize);
589+
}
590+
}
591+
Ok(-1isize)
592+
}
555593
}
556594

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

vm/src/obj/objbytes.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,32 @@ impl PyBytesRef {
280280
) -> PyResult {
281281
self.inner.startsendswith(suffix, start, end, false, vm)
282282
}
283+
284+
#[pymethod(name = "find")]
285+
fn find(
286+
self,
287+
sub: PyObjectRef,
288+
start: OptionalArg<PyObjectRef>,
289+
end: OptionalArg<PyObjectRef>,
290+
vm: &VirtualMachine,
291+
) -> PyResult {
292+
Ok(vm.new_int(self.inner.find(sub, start, end, vm)?))
293+
}
294+
295+
#[pymethod(name = "index")]
296+
fn index(
297+
self,
298+
sub: PyObjectRef,
299+
start: OptionalArg<PyObjectRef>,
300+
end: OptionalArg<PyObjectRef>,
301+
vm: &VirtualMachine,
302+
) -> PyResult {
303+
let res = self.inner.find(sub, start, end, vm)?;
304+
if res == -1 {
305+
return Err(vm.new_value_error("substring not found".to_string()));
306+
}
307+
Ok(vm.new_int(res))
308+
}
283309
}
284310

285311
#[derive(Debug)]

0 commit comments

Comments
 (0)