+/// A trivial future which joins two other futures and polls them at the same time, returning only
+/// once both complete.
+pub(crate) struct Joiner<
+ A: Future<Output=Result<(BlockHash, Option<u32>), BlockSourceError>> + Unpin,
+ B: Future<Output=Result<BlockHash, BlockSourceError>> + Unpin,
+> {
+ pub a: A,
+ pub b: B,
+ a_res: Option<(BlockHash, Option<u32>)>,
+ b_res: Option<BlockHash>,
+}
+
+impl<
+ A: Future<Output=Result<(BlockHash, Option<u32>), BlockSourceError>> + Unpin,
+ B: Future<Output=Result<BlockHash, BlockSourceError>> + Unpin,
+> Joiner<A, B> {
+ fn new(a: A, b: B) -> Self { Self { a, b, a_res: None, b_res: None } }
+}
+
+impl<
+ A: Future<Output=Result<(BlockHash, Option<u32>), BlockSourceError>> + Unpin,
+ B: Future<Output=Result<BlockHash, BlockSourceError>> + Unpin,
+> Future for Joiner<A, B> {
+ type Output = Result<((BlockHash, Option<u32>), BlockHash), BlockSourceError>;
+ fn poll(mut self: Pin<&mut Self>, ctx: &mut core::task::Context<'_>) -> Poll<Self::Output> {
+ if self.a_res.is_none() {
+ match Pin::new(&mut self.a).poll(ctx) {
+ Poll::Ready(res) => {
+ if let Ok(ok) = res {
+ self.a_res = Some(ok);
+ } else {
+ return Poll::Ready(Err(res.unwrap_err()));
+ }
+ },
+ Poll::Pending => {},
+ }
+ }
+ if self.b_res.is_none() {
+ match Pin::new(&mut self.b).poll(ctx) {
+ Poll::Ready(res) => {
+ if let Ok(ok) = res {
+ self.b_res = Some(ok);
+ } else {
+ return Poll::Ready(Err(res.unwrap_err()));
+ }
+
+ },
+ Poll::Pending => {},
+ }
+ }
+ if let Some(b_res) = self.b_res {
+ if let Some(a_res) = self.a_res {
+ return Poll::Ready(Ok((a_res, b_res)))
+ }
+ }
+ Poll::Pending
+ }
+}
+