|
1 | 1 | use crate::obj::objint::PyIntRef;
|
2 | 2 | use crate::obj::objslice::PySlice;
|
3 | 3 | use crate::pyobject::{PyIterable, PyObjectRef};
|
| 4 | +use core::ops::Range; |
4 | 5 | use num_bigint::BigInt;
|
5 | 6 |
|
6 | 7 | use crate::function::OptionalArg;
|
@@ -99,6 +100,53 @@ impl ByteInnerNewOptions {
|
99 | 100 | }
|
100 | 101 | }
|
101 | 102 |
|
| 103 | +#[derive(FromArgs)] |
| 104 | +pub struct ByteInnerFindOptions { |
| 105 | + #[pyarg(positional_only, optional = false)] |
| 106 | + sub: PyObjectRef, |
| 107 | + #[pyarg(positional_only, optional = true)] |
| 108 | + start: OptionalArg<PyObjectRef>, |
| 109 | + #[pyarg(positional_only, optional = true)] |
| 110 | + end: OptionalArg<PyObjectRef>, |
| 111 | +} |
| 112 | + |
| 113 | +impl ByteInnerFindOptions { |
| 114 | + pub fn get_value( |
| 115 | + self, |
| 116 | + elements: &[u8], |
| 117 | + vm: &VirtualMachine, |
| 118 | + ) -> PyResult<(Vec<u8>, Range<usize>)> { |
| 119 | + let sub = match try_as_bytes_like(&self.sub.clone()) { |
| 120 | + Some(value) => value, |
| 121 | + None => match_class!(self.sub, |
| 122 | + i @ PyInt => vec![i.as_bigint().byte_or(vm)?], |
| 123 | + obj => {return Err(vm.new_type_error(format!("argument should be integer or bytes-like object, not {}", obj)));}), |
| 124 | + }; |
| 125 | + let start = if let OptionalArg::Present(st) = self.start { |
| 126 | + match_class!(st, |
| 127 | + i @ PyInt => {Some(i.as_bigint().clone())}, |
| 128 | + _obj @ PyNone => None, |
| 129 | + _=> {return Err(vm.new_type_error("slice indices must be integers or None or have an __index__ method".to_string()));} |
| 130 | + ) |
| 131 | + } else { |
| 132 | + None |
| 133 | + }; |
| 134 | + let end = if let OptionalArg::Present(e) = self.end { |
| 135 | + match_class!(e, |
| 136 | + i @ PyInt => {Some(i.as_bigint().clone())}, |
| 137 | + _obj @ PyNone => None, |
| 138 | + _=> {return Err(vm.new_type_error("slice indices must be integers or None or have an __index__ method".to_string()));} |
| 139 | + ) |
| 140 | + } else { |
| 141 | + None |
| 142 | + }; |
| 143 | + |
| 144 | + let range = elements.to_vec().get_slice_range(&start, &end); |
| 145 | + |
| 146 | + Ok((sub, range)) |
| 147 | + } |
| 148 | +} |
| 149 | + |
102 | 150 | impl PyByteInner {
|
103 | 151 | pub fn repr(&self) -> PyResult<String> {
|
104 | 152 | let mut res = String::with_capacity(self.elements.len());
|
@@ -482,39 +530,8 @@ impl PyByteInner {
|
482 | 530 | Ok(res)
|
483 | 531 | }
|
484 | 532 |
|
485 |
| - pub fn count( |
486 |
| - &self, |
487 |
| - sub: PyObjectRef, |
488 |
| - start: OptionalArg<PyObjectRef>, |
489 |
| - end: OptionalArg<PyObjectRef>, |
490 |
| - vm: &VirtualMachine, |
491 |
| - ) -> PyResult<usize> { |
492 |
| - let sub = match try_as_bytes_like(&sub) { |
493 |
| - Some(value) => value, |
494 |
| - None => match_class!(sub, |
495 |
| - i @ PyInt => vec![i.as_bigint().byte_or(vm)?], |
496 |
| - obj => {return Err(vm.new_type_error(format!("argument should be integer or bytes-like object, not {}", obj)));}), |
497 |
| - }; |
498 |
| - let start = if let OptionalArg::Present(st) = start { |
499 |
| - match_class!(st, |
500 |
| - i @ PyInt => {Some(i.as_bigint().clone())}, |
501 |
| - _obj @ PyNone => None, |
502 |
| - _=> {return Err(vm.new_type_error("slice indices must be integers or None or have an __index__ method".to_string()));} |
503 |
| - ) |
504 |
| - } else { |
505 |
| - None |
506 |
| - }; |
507 |
| - let end = if let OptionalArg::Present(e) = end { |
508 |
| - match_class!(e, |
509 |
| - i @ PyInt => {Some(i.as_bigint().clone())}, |
510 |
| - _obj @ PyNone => None, |
511 |
| - _=> {return Err(vm.new_type_error("slice indices must be integers or None or have an __index__ method".to_string()));} |
512 |
| - ) |
513 |
| - } else { |
514 |
| - None |
515 |
| - }; |
516 |
| - |
517 |
| - let range = self.elements.get_slice_range(&start, &end); |
| 533 | + pub fn count(&self, options: ByteInnerFindOptions, vm: &VirtualMachine) -> PyResult<usize> { |
| 534 | + let (sub, range) = options.get_value(&self.elements, vm)?; |
518 | 535 |
|
519 | 536 | if sub.is_empty() {
|
520 | 537 | return Ok(self.len() + 1);
|
|
0 commit comments