1

I'm looking to implement a wrapper struct for any stream that returns a certain type, to cut down on the dynamic keywords littering my application. I've come across BoxStream, but have no idea how to make use of it in Stream::poll_next. Here's what I have so far:

use std::pin::Pin;
use std::task::{Context, Poll};
use futures::prelude::stream::BoxStream;
use futures::Stream;

pub struct Row;

pub struct RowCollection<'a> {
    stream: BoxStream<'a, Row>,
}

impl RowCollection<'_> {
    pub fn new<'a>(stream: BoxStream<Row>) -> RowCollection {
        RowCollection { stream }
    }
}

impl Stream for RowCollection<'_> {
    type Item = Row;
    fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
        // I have no idea what to put here, but it needs to get the information from self.stream and return appropriate value
    }
}

Dependencies:

futures = "0.3"

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
eltiare
  • 1,817
  • 1
  • 20
  • 28
  • 2
    I'm not sure precisely what dynamic keywords you're referring to, but perhaps `pub type RowCollection<'a> = BoxStream<'a, Row>` is a simpler way of achieving your goal? – user4815162342 Nov 29 '21 at 19:45
  • BoxStream<'a, T> is shorthand for a stream that has a dynamic type, from what I've gathered from the docs. – eltiare Nov 29 '21 at 19:51
  • That's correct - the type that implements the stream is dynamic and determined at run-time. The type of stream's item is statically known. As far as I can tell, your wrapping of `BoxStream` is trivial and can be equally accomplished with a type alias. – user4815162342 Nov 29 '21 at 19:55
  • Yeah, for this trivial example an alias will probably work best. I also appreciate the answer by Shepmaster because it shows how to do exactly what I asked, just in case I need to add extra functionality. I'm going to play with both of these suggestions today. – eltiare Nov 29 '21 at 19:59

1 Answers1

3

Since Box implements Unpin, then BoxStream implements Unpin, and so will RowCollection.

Because of this, you can make use of Pin::get_mut which will give you a &mut RowCollection. From that, you can get a &mut BoxStream. You can re-pin that via Pin::new and then call poll_next on it. This is called pin-projection.

impl Stream for RowCollection<'_> {
    type Item = Row;
    
    fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
        Pin::new(&mut self.get_mut().stream).poll_next(cx)
    }
}

See also:

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366