Skip to content

Commit 957c6b2

Browse files
authored
Merge pull request #220 from matheus-consoli/empty-vec
handle empty collections
2 parents 468538c + e447b5e commit 957c6b2

6 files changed

Lines changed: 56 additions & 1 deletion

File tree

src/future/race/array.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ where
7070
type Future = Race<Fut::IntoFuture, N>;
7171

7272
fn race(self) -> Self::Future {
73+
assert!(N > 0, "race requires at least one future");
7374
Race {
7475
futures: self.map(|fut| fut.into_future()),
7576
indexer: Indexer::new(N),
@@ -83,6 +84,13 @@ mod test {
8384
use super::*;
8485
use core::future;
8586

87+
#[test]
88+
#[should_panic(expected = "race requires at least one future")]
89+
fn empty_array() {
90+
let futs: [future::Ready<()>; 0] = [];
91+
let _ = futs.race();
92+
}
93+
8694
// NOTE: we should probably poll in random order.
8795
#[test]
8896
fn no_fairness() {

src/future/race/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,10 @@ pub trait Race {
2222
/// other futures are cancelled.
2323
///
2424
/// This function returns a new future which polls all futures concurrently.
25+
///
26+
/// # Panics
27+
///
28+
/// This method will panic if the collection is empty (for `Vec` and array
29+
/// implementations) since there would be no future to race.
2530
fn race(self) -> Self::Future;
2631
}

src/future/race/vec.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ where
7373
type Future = Race<Fut::IntoFuture>;
7474

7575
fn race(self) -> Self::Future {
76+
assert!(!self.is_empty(), "race requires at least one future");
7677
Race {
7778
indexer: Indexer::new(self.len()),
7879
futures: self.into_iter().map(|fut| fut.into_future()).collect(),
@@ -87,6 +88,15 @@ mod test {
8788
use alloc::vec;
8889
use core::future;
8990

91+
#[test]
92+
#[should_panic(expected = "race requires at least one future")]
93+
fn empty_vec() {
94+
futures_lite::future::block_on(async {
95+
let futs: Vec<future::Ready<()>> = vec![];
96+
let _ = futs.race().await;
97+
});
98+
}
99+
90100
// NOTE: we should probably poll in random order.
91101
#[test]
92102
fn no_fairness() {

src/stream/merge/array.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,11 @@ where
6262
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
6363
let mut this = self.project();
6464

65+
// return early if all streams are complete (handles empty array)
66+
if *this.complete == N {
67+
return Poll::Ready(None);
68+
}
69+
6570
let mut readiness = this.wakers.readiness();
6671
readiness.set_waker(cx.waker());
6772

@@ -127,6 +132,16 @@ mod tests {
127132
use futures_lite::prelude::*;
128133
use futures_lite::stream;
129134

135+
#[test]
136+
fn empty_array() {
137+
block_on(async {
138+
let streams: [stream::Once<i32>; 0] = [];
139+
let mut s = streams.merge();
140+
let result = s.next().await;
141+
assert_eq!(result, None);
142+
})
143+
}
144+
130145
#[test]
131146
fn merge_array_4() {
132147
block_on(async {

src/stream/merge/vec.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,11 @@ where
6666
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
6767
let mut this = self.project();
6868

69+
// return early if all streams are complete (handles empty vec)
70+
if *this.complete == this.streams.len() {
71+
return Poll::Ready(None);
72+
}
73+
6974
let mut readiness = this.wakers.readiness();
7075
readiness.set_waker(cx.waker());
7176

@@ -140,6 +145,16 @@ mod tests {
140145

141146
use crate::future::join::Join;
142147

148+
#[test]
149+
fn empty_vec() {
150+
block_on(async {
151+
let streams: Vec<stream::Once<i32>> = vec![];
152+
let mut s = streams.merge();
153+
let result = s.next().await;
154+
assert_eq!(result, None);
155+
})
156+
}
157+
143158
#[test]
144159
fn merge_vec_4() {
145160
block_on(async {

src/utils/indexer.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@ impl Indexer {
1717
pub(crate) fn iter(&mut self) -> IndexIter {
1818
// Increment the starting point for next time.
1919
let offset = self.offset;
20-
self.offset = (self.offset + 1).wrapping_rem(self.max);
20+
if self.max > 0 {
21+
self.offset = (self.offset + 1).wrapping_rem(self.max);
22+
}
2123

2224
IndexIter {
2325
iter: (0..self.max),

0 commit comments

Comments
 (0)