1
+ use std:: cmp:: Ordering ;
2
+ use std:: pin:: Pin ;
3
+
4
+ use super :: fuse:: Fuse ;
5
+ use crate :: prelude:: * ;
6
+ use crate :: future:: Future ;
7
+ use crate :: stream:: Stream ;
8
+ use crate :: task:: { Context , Poll } ;
9
+
10
+ // Lexicographically compares the elements of this `Stream` with those
11
+ // of another using `Ord`.
12
+ #[ doc( hidden) ]
13
+ #[ allow( missing_debug_implementations) ]
14
+ pub struct CmpFuture < L : Stream , R : Stream > {
15
+ l : Fuse < L > ,
16
+ r : Fuse < R > ,
17
+ l_cache : Option < L :: Item > ,
18
+ r_cache : Option < R :: Item > ,
19
+ }
20
+
21
+ impl < L : Stream , R : Stream > CmpFuture < L , R > {
22
+ pin_utils:: unsafe_pinned!( l: Fuse <L >) ;
23
+ pin_utils:: unsafe_pinned!( r: Fuse <R >) ;
24
+ pin_utils:: unsafe_unpinned!( l_cache: Option <L :: Item >) ;
25
+ pin_utils:: unsafe_unpinned!( r_cache: Option <R :: Item >) ;
26
+
27
+ pub ( super ) fn new ( l : L , r : R ) -> Self {
28
+ CmpFuture {
29
+ l : l. fuse ( ) ,
30
+ r : r. fuse ( ) ,
31
+ l_cache : None ,
32
+ r_cache : None ,
33
+ }
34
+ }
35
+ }
36
+
37
+ impl < L : Stream , R : Stream > Future for CmpFuture < L , R >
38
+ where
39
+ L : Stream + Sized ,
40
+ R : Stream < Item = L :: Item > + Sized ,
41
+ L :: Item : Ord ,
42
+ {
43
+ type Output = Ordering ;
44
+
45
+ fn poll ( mut self : Pin < & mut Self > , cx : & mut Context < ' _ > ) -> Poll < Self :: Output > {
46
+ loop {
47
+ // Stream that completes earliest can be considered Less, etc
48
+ let l_complete = self . l . done && self . as_mut ( ) . l_cache . is_none ( ) ;
49
+ let r_complete = self . r . done && self . as_mut ( ) . r_cache . is_none ( ) ;
50
+
51
+ if l_complete && r_complete {
52
+ return Poll :: Ready ( Ordering :: Equal )
53
+ } else if l_complete {
54
+ return Poll :: Ready ( Ordering :: Less )
55
+ } else if r_complete {
56
+ return Poll :: Ready ( Ordering :: Greater )
57
+ }
58
+
59
+ // Get next value if possible and necesary
60
+ if !self . l . done && self . as_mut ( ) . l_cache . is_none ( ) {
61
+ let l_next = futures_core:: ready!( self . as_mut( ) . l( ) . poll_next( cx) ) ;
62
+ if let Some ( item) = l_next {
63
+ * self . as_mut ( ) . l_cache ( ) = Some ( item) ;
64
+ }
65
+ }
66
+
67
+ if !self . r . done && self . as_mut ( ) . r_cache . is_none ( ) {
68
+ let r_next = futures_core:: ready!( self . as_mut( ) . r( ) . poll_next( cx) ) ;
69
+ if let Some ( item) = r_next {
70
+ * self . as_mut ( ) . r_cache ( ) = Some ( item) ;
71
+ }
72
+ }
73
+
74
+ // Compare if both values are available.
75
+ if self . as_mut ( ) . l_cache . is_some ( ) && self . as_mut ( ) . r_cache . is_some ( ) {
76
+ let l_value = self . as_mut ( ) . l_cache ( ) . take ( ) . unwrap ( ) ;
77
+ let r_value = self . as_mut ( ) . r_cache ( ) . take ( ) . unwrap ( ) ;
78
+ let result = l_value. cmp ( & r_value) ;
79
+
80
+ if let Ordering :: Equal = result {
81
+ // Reset cache to prepare for next comparison
82
+ * self . as_mut ( ) . l_cache ( ) = None ;
83
+ * self . as_mut ( ) . r_cache ( ) = None ;
84
+ } else {
85
+ // Return non equal value
86
+ return Poll :: Ready ( result) ;
87
+ }
88
+ }
89
+ }
90
+ }
91
+ }
0 commit comments