Shouldn't I call next on future::stream::Unfold?

I'm calling next multiple times on a Stream returned by this function: rtsp-server/message_socket.rs at 96dbaf00a7111c775348430a64d6a60f16d66445 · sdroege/rtsp-server · GitHub

pub(crate) fn async_read<R: AsyncRead + Unpin + Send>(
    read: R,
    max_size: usize,
) -> impl Stream<Item = Result<Message<Body>, ReadError>> + Send {
    
    //...

    futures::stream::unfold(Some(state), move |mut state| async move {
        //...
    })
}

sometimes it works, but sometimes I get:

thread 'main' panicked at 'Unfold must not be polled after it returned `Poll::Ready(None)`', /root/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-util-0.3.13/src/stream/unfold.rs:115:21

The error comes from unfold.rs.html -- source

but I couldn't understand why. Shouldn't I be free to call next on a Stream, in a loop?

Once you get Poll::Ready(None) you are not supposed to keep calling it (see futures::stream::Stream - Rust for a description of return values). At this point, the stream should be considered exhausted.

You can fuse a stream, which will allow poll_next() to be called even after the end of the stream (you'll just keep getting None back instead of panicking).

Would it not make sense to terminate the loop when you get None back?

The way that we usually loop through a stream is:

while let Some(item) = stream.next().await {
    ...
}

In the above, once next() returns None, it will stop iterating through the loop. This is because None means that the stream is done. The panic you ran into indicates that you called next again after it has returned None.

does that mean that when I receive None I should consider my TCP socket closed?

It's unclear from your code how the Unfold stream relates to the TCP socket, but when a Stream returns None, then yes, the Stream is closed and will never produce more items.