Skip to content

Commit 86decbb

Browse files
Merge pull request RustPython#1097 from RustPython/coolreader18/collections-deque
Add deque to collections
2 parents 7b23a96 + 5b32dfb commit 86decbb

File tree

7 files changed

+483
-34
lines changed

7 files changed

+483
-34
lines changed

azure-pipelines.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ jobs:
2222
"C:\Program Files\Git\mingw64\bin\curl.exe" -sSf -o rustup-init.exe https://win.rustup.rs/
2323
.\rustup-init.exe -y
2424
set PATH=%PATH%;%USERPROFILE%\.cargo\bin
25+
rustup update
2526
rustc -V
2627
cargo -V
2728
displayName: 'Installing Rust'

tests/snippets/test_collections.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
from collections import deque
2+
3+
4+
d = deque([0, 1, 2])
5+
6+
d.append(1)
7+
d.appendleft(3)
8+
9+
assert d == deque([3, 0, 1, 2, 1])
10+
11+
assert d <= deque([4])
12+
13+
assert d.copy() is not d
14+
15+
d = deque([1, 2, 3], 5)
16+
17+
d.extend([4, 5, 6])
18+
19+
assert d == deque([2, 3, 4, 5, 6])
20+
21+
d.remove(4)
22+
23+
assert d == deque([2, 3, 5, 6])
24+
25+
d.clear()
26+
27+
assert d == deque()
28+
29+
assert d == deque([], 4)
30+
31+
assert deque([1, 2, 3]) * 2 == deque([1, 2, 3, 1, 2, 3])
32+
33+
assert deque([1, 2, 3], 4) * 2 == deque([3, 1, 2, 3])
34+
35+
assert deque(maxlen=3) == deque()
36+
37+
assert deque([1, 2, 3, 4], maxlen=2) == deque([3, 4])
38+
39+
assert len(deque([1, 2, 3, 4])) == 4

vm/src/obj/objlist.rs

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -392,12 +392,16 @@ impl PyListRef {
392392
}
393393

394394
fn mul(self, counter: isize, vm: &VirtualMachine) -> PyObjectRef {
395-
let new_elements = seq_mul(&self.elements.borrow(), counter);
395+
let new_elements = seq_mul(&self.elements.borrow().as_slice(), counter)
396+
.cloned()
397+
.collect();
396398
vm.ctx.new_list(new_elements)
397399
}
398400

399401
fn imul(self, counter: isize, _vm: &VirtualMachine) -> Self {
400-
let new_elements = seq_mul(&self.elements.borrow(), counter);
402+
let new_elements = seq_mul(&self.elements.borrow().as_slice(), counter)
403+
.cloned()
404+
.collect();
401405
self.elements.replace(new_elements);
402406
self
403407
}
@@ -491,7 +495,7 @@ impl PyListRef {
491495
if objtype::isinstance(&other, &vm.ctx.list_type()) {
492496
let zelf = self.elements.borrow();
493497
let other = get_elements_list(&other);
494-
let res = seq_equal(vm, &zelf, &other)?;
498+
let res = seq_equal(vm, &zelf.as_slice(), &other.as_slice())?;
495499
Ok(vm.new_bool(res))
496500
} else {
497501
Ok(vm.ctx.not_implemented())
@@ -502,7 +506,7 @@ impl PyListRef {
502506
if objtype::isinstance(&other, &vm.ctx.list_type()) {
503507
let zelf = self.elements.borrow();
504508
let other = get_elements_list(&other);
505-
let res = seq_lt(vm, &zelf, &other)?;
509+
let res = seq_lt(vm, &zelf.as_slice(), &other.as_slice())?;
506510
Ok(vm.new_bool(res))
507511
} else {
508512
Ok(vm.ctx.not_implemented())
@@ -513,7 +517,7 @@ impl PyListRef {
513517
if objtype::isinstance(&other, &vm.ctx.list_type()) {
514518
let zelf = self.elements.borrow();
515519
let other = get_elements_list(&other);
516-
let res = seq_gt(vm, &zelf, &other)?;
520+
let res = seq_gt(vm, &zelf.as_slice(), &other.as_slice())?;
517521
Ok(vm.new_bool(res))
518522
} else {
519523
Ok(vm.ctx.not_implemented())
@@ -524,7 +528,7 @@ impl PyListRef {
524528
if objtype::isinstance(&other, &vm.ctx.list_type()) {
525529
let zelf = self.elements.borrow();
526530
let other = get_elements_list(&other);
527-
let res = seq_ge(vm, &zelf, &other)?;
531+
let res = seq_ge(vm, &zelf.as_slice(), &other.as_slice())?;
528532
Ok(vm.new_bool(res))
529533
} else {
530534
Ok(vm.ctx.not_implemented())
@@ -535,7 +539,7 @@ impl PyListRef {
535539
if objtype::isinstance(&other, &vm.ctx.list_type()) {
536540
let zelf = self.elements.borrow();
537541
let other = get_elements_list(&other);
538-
let res = seq_le(vm, &zelf, &other)?;
542+
let res = seq_le(vm, &zelf.as_slice(), &other.as_slice())?;
539543
Ok(vm.new_bool(res))
540544
} else {
541545
Ok(vm.ctx.not_implemented())

vm/src/obj/objsequence.rs

Lines changed: 74 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -216,10 +216,38 @@ pub fn get_item(
216216
}
217217
}
218218

219+
type DynPyIter<'a> = Box<dyn ExactSizeIterator<Item = &'a PyObjectRef> + 'a>;
220+
221+
#[allow(clippy::len_without_is_empty)]
222+
pub trait SimpleSeq {
223+
fn len(&self) -> usize;
224+
fn iter(&self) -> DynPyIter;
225+
}
226+
227+
impl SimpleSeq for &[PyObjectRef] {
228+
fn len(&self) -> usize {
229+
(&**self).len()
230+
}
231+
fn iter(&self) -> DynPyIter {
232+
Box::new((&**self).iter())
233+
}
234+
}
235+
236+
impl SimpleSeq for std::collections::VecDeque<PyObjectRef> {
237+
fn len(&self) -> usize {
238+
self.len()
239+
}
240+
fn iter(&self) -> DynPyIter {
241+
Box::new(self.iter())
242+
}
243+
}
244+
245+
// impl<'a, I>
246+
219247
pub fn seq_equal(
220248
vm: &VirtualMachine,
221-
zelf: &[PyObjectRef],
222-
other: &[PyObjectRef],
249+
zelf: &dyn SimpleSeq,
250+
other: &dyn SimpleSeq,
223251
) -> Result<bool, PyObjectRef> {
224252
if zelf.len() == other.len() {
225253
for (a, b) in Iterator::zip(zelf.iter(), other.iter()) {
@@ -239,8 +267,8 @@ pub fn seq_equal(
239267

240268
pub fn seq_lt(
241269
vm: &VirtualMachine,
242-
zelf: &[PyObjectRef],
243-
other: &[PyObjectRef],
270+
zelf: &dyn SimpleSeq,
271+
other: &dyn SimpleSeq,
244272
) -> Result<bool, PyObjectRef> {
245273
if zelf.len() == other.len() {
246274
for (a, b) in Iterator::zip(zelf.iter(), other.iter()) {
@@ -279,8 +307,8 @@ pub fn seq_lt(
279307

280308
pub fn seq_gt(
281309
vm: &VirtualMachine,
282-
zelf: &[PyObjectRef],
283-
other: &[PyObjectRef],
310+
zelf: &dyn SimpleSeq,
311+
other: &dyn SimpleSeq,
284312
) -> Result<bool, PyObjectRef> {
285313
if zelf.len() == other.len() {
286314
for (a, b) in Iterator::zip(zelf.iter(), other.iter()) {
@@ -318,30 +346,58 @@ pub fn seq_gt(
318346

319347
pub fn seq_ge(
320348
vm: &VirtualMachine,
321-
zelf: &[PyObjectRef],
322-
other: &[PyObjectRef],
349+
zelf: &dyn SimpleSeq,
350+
other: &dyn SimpleSeq,
323351
) -> Result<bool, PyObjectRef> {
324352
Ok(seq_gt(vm, zelf, other)? || seq_equal(vm, zelf, other)?)
325353
}
326354

327355
pub fn seq_le(
328356
vm: &VirtualMachine,
329-
zelf: &[PyObjectRef],
330-
other: &[PyObjectRef],
357+
zelf: &dyn SimpleSeq,
358+
other: &dyn SimpleSeq,
331359
) -> Result<bool, PyObjectRef> {
332360
Ok(seq_lt(vm, zelf, other)? || seq_equal(vm, zelf, other)?)
333361
}
334362

335-
pub fn seq_mul(elements: &[PyObjectRef], counter: isize) -> Vec<PyObjectRef> {
336-
let current_len = elements.len();
337-
let new_len = counter.max(0) as usize * current_len;
338-
let mut new_elements = Vec::with_capacity(new_len);
339-
340-
for _ in 0..counter {
341-
new_elements.extend(elements.to_owned());
363+
pub struct SeqMul<'a> {
364+
seq: &'a dyn SimpleSeq,
365+
repetitions: usize,
366+
iter: Option<DynPyIter<'a>>,
367+
}
368+
impl<'a> Iterator for SeqMul<'a> {
369+
type Item = &'a PyObjectRef;
370+
fn next(&mut self) -> Option<Self::Item> {
371+
if self.seq.len() == 0 {
372+
return None;
373+
}
374+
match self.iter.as_mut().and_then(Iterator::next) {
375+
Some(item) => Some(item),
376+
None => {
377+
if self.repetitions == 0 {
378+
None
379+
} else {
380+
self.repetitions -= 1;
381+
self.iter = Some(self.seq.iter());
382+
self.next()
383+
}
384+
}
385+
}
342386
}
387+
fn size_hint(&self) -> (usize, Option<usize>) {
388+
let size = self.iter.as_ref().map_or(0, ExactSizeIterator::len)
389+
+ (self.repetitions * self.seq.len());
390+
(size, Some(size))
391+
}
392+
}
393+
impl ExactSizeIterator for SeqMul<'_> {}
343394

344-
new_elements
395+
pub fn seq_mul(seq: &dyn SimpleSeq, repetitions: isize) -> SeqMul {
396+
SeqMul {
397+
seq,
398+
repetitions: repetitions.max(0) as usize,
399+
iter: None,
400+
}
345401
}
346402

347403
pub fn get_elements_cell<'a>(obj: &'a PyObjectRef) -> &'a RefCell<Vec<PyObjectRef>> {

vm/src/obj/objtuple.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ impl PyTupleRef {
5353
fn lt(self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
5454
if objtype::isinstance(&other, &vm.ctx.tuple_type()) {
5555
let other = get_elements_tuple(&other);
56-
let res = seq_lt(vm, &self.elements, &other)?;
56+
let res = seq_lt(vm, &self.elements.as_slice(), &other.as_slice())?;
5757
Ok(vm.new_bool(res))
5858
} else {
5959
Ok(vm.ctx.not_implemented())
@@ -63,7 +63,7 @@ impl PyTupleRef {
6363
fn gt(self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
6464
if objtype::isinstance(&other, &vm.ctx.tuple_type()) {
6565
let other = get_elements_tuple(&other);
66-
let res = seq_gt(vm, &self.elements, &other)?;
66+
let res = seq_gt(vm, &self.elements.as_slice(), &other.as_slice())?;
6767
Ok(vm.new_bool(res))
6868
} else {
6969
Ok(vm.ctx.not_implemented())
@@ -73,7 +73,7 @@ impl PyTupleRef {
7373
fn ge(self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
7474
if objtype::isinstance(&other, &vm.ctx.tuple_type()) {
7575
let other = get_elements_tuple(&other);
76-
let res = seq_ge(vm, &self.elements, &other)?;
76+
let res = seq_ge(vm, &self.elements.as_slice(), &other.as_slice())?;
7777
Ok(vm.new_bool(res))
7878
} else {
7979
Ok(vm.ctx.not_implemented())
@@ -83,7 +83,7 @@ impl PyTupleRef {
8383
fn le(self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
8484
if objtype::isinstance(&other, &vm.ctx.tuple_type()) {
8585
let other = get_elements_tuple(&other);
86-
let res = seq_le(vm, &self.elements, &other)?;
86+
let res = seq_le(vm, &self.elements.as_slice(), &other.as_slice())?;
8787
Ok(vm.new_bool(res))
8888
} else {
8989
Ok(vm.ctx.not_implemented())
@@ -122,7 +122,7 @@ impl PyTupleRef {
122122
fn eq(self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
123123
if objtype::isinstance(&other, &vm.ctx.tuple_type()) {
124124
let other = get_elements_tuple(&other);
125-
let res = seq_equal(vm, &self.elements, &other)?;
125+
let res = seq_equal(vm, &self.elements.as_slice(), &other.as_slice())?;
126126
Ok(vm.new_bool(res))
127127
} else {
128128
Ok(vm.ctx.not_implemented())
@@ -164,13 +164,14 @@ impl PyTupleRef {
164164
}
165165

166166
fn mul(self, counter: isize, vm: &VirtualMachine) -> PyObjectRef {
167-
let new_elements = seq_mul(&self.elements, counter);
167+
let new_elements = seq_mul(&self.elements.as_slice(), counter)
168+
.cloned()
169+
.collect();
168170
vm.ctx.new_tuple(new_elements)
169171
}
170172

171173
fn rmul(self, counter: isize, vm: &VirtualMachine) -> PyObjectRef {
172-
let new_elements = seq_mul(&self.elements, counter);
173-
vm.ctx.new_tuple(new_elements)
174+
self.mul(counter, vm)
174175
}
175176

176177
fn getitem(self, needle: PyObjectRef, vm: &VirtualMachine) -> PyResult {

0 commit comments

Comments
 (0)