-
Notifications
You must be signed in to change notification settings - Fork 341
Adds partial_cmp.rs file and partial_cmp signature to mod.rs #268
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
9f604f9
f145485
8e009d0
243c52a
838f752
bfea84a
5f67420
5317d4f
1c0ee5f
815a36e
4370787
ded4137
1fd8205
17a3afb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
use std::cmp::Ordering; | ||
use std::pin::Pin; | ||
|
||
use super::fuse::Fuse; | ||
use crate::future::Future; | ||
use crate::prelude::*; | ||
use crate::stream::Stream; | ||
use crate::task::{Context, Poll}; | ||
|
||
// Lexicographically compares the elements of this `Stream` with those | ||
// of another. | ||
#[doc(hidden)] | ||
#[allow(missing_debug_implementations)] | ||
pub struct PartialCmpFuture<L: Stream, R: Stream> { | ||
l: Fuse<L>, | ||
r: Fuse<R>, | ||
l_cache: Option<L::Item>, | ||
r_cache: Option<R::Item>, | ||
} | ||
|
||
impl<L: Stream, R: Stream> PartialCmpFuture<L, R> { | ||
pin_utils::unsafe_pinned!(l: Fuse<L>); | ||
pin_utils::unsafe_pinned!(r: Fuse<R>); | ||
pin_utils::unsafe_unpinned!(l_cache: Option<L::Item>); | ||
pin_utils::unsafe_unpinned!(r_cache: Option<R::Item>); | ||
|
||
pub(super) fn new(l: L, r: R) -> Self { | ||
PartialCmpFuture { | ||
l: l.fuse(), | ||
r: r.fuse(), | ||
l_cache: None, | ||
r_cache: None, | ||
} | ||
} | ||
} | ||
|
||
impl<L: Stream, R: Stream> Future for PartialCmpFuture<L, R> | ||
where | ||
L: Stream + Sized, | ||
R: Stream + Sized, | ||
L::Item: PartialOrd<R::Item>, | ||
{ | ||
type Output = Option<Ordering>; | ||
|
||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. uhhh, this doesn't look right. Values might arrive from streams at different points at time, but if this happens this doesn't mean that the streams are not equal. The more correct behaviour here would probably be as follows:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see. I wanted to start by replicating the std::iter code for partial_cmp as much as possible, but you're correct that it doesn't account for values from each stream arriving at different times. Thanks for the feedback. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I also think that |
||
loop { | ||
// Short circuit logic | ||
// Stream that completes earliest can be considered Less, etc | ||
let l_complete = self.l.done && self.as_mut().l_cache.is_none(); | ||
let r_complete = self.r.done && self.as_mut().r_cache.is_none(); | ||
|
||
if l_complete && r_complete { | ||
return Poll::Ready(Some(Ordering::Equal)); | ||
} else if l_complete { | ||
return Poll::Ready(Some(Ordering::Less)); | ||
} else if r_complete { | ||
return Poll::Ready(Some(Ordering::Greater)); | ||
} | ||
|
||
// Get next value if possible and necesary | ||
if !self.l.done && self.as_mut().l_cache.is_none() { | ||
let l_next = futures_core::ready!(self.as_mut().l().poll_next(cx)); | ||
if let Some(item) = l_next { | ||
*self.as_mut().l_cache() = Some(item); | ||
} | ||
} | ||
|
||
if !self.r.done && self.as_mut().r_cache.is_none() { | ||
let r_next = futures_core::ready!(self.as_mut().r().poll_next(cx)); | ||
if let Some(item) = r_next { | ||
*self.as_mut().r_cache() = Some(item); | ||
} | ||
} | ||
|
||
// Compare if both values are available. | ||
if self.as_mut().l_cache.is_some() && self.as_mut().r_cache.is_some() { | ||
let l_value = self.as_mut().l_cache().take().unwrap(); | ||
let r_value = self.as_mut().r_cache().take().unwrap(); | ||
let result = l_value.partial_cmp(&r_value); | ||
|
||
if let Some(Ordering::Equal) = result { | ||
// Reset cache to prepare for next comparison | ||
*self.as_mut().l_cache() = None; | ||
*self.as_mut().r_cache() = None; | ||
} else { | ||
// Return non equal value | ||
return Poll::Ready(result); | ||
} | ||
} | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably also tests for
Greater
andLess
for streams of the same number of elements but with different values?