2

Where does tokio_tungstenite::WebSocketStream implement the split() function as used in one of their examples?

The following is a snippet of the example:

let (ws_stream, _) = connect_async(url).await.expect("Failed to connect");

let (write, read) = ws_stream.split(); 

Someone else had a similar problem finding split() in tokio::net::TcpStream and the answer was that TcpStream implements AsyncRead. In the case of WebSocketStream I cannot see any impl AsyncRead for WebSocketStream code.

My broader question is what knowledge am I missing that stops me from finding methods such as split() and their implementations of a struct such as WebSocketStream in docs.rs or in the source code?

Dan
  • 5,013
  • 5
  • 33
  • 59
  • [`StreamExt::split`](https://docs.rs/futures-util/0.3.15/futures_util/stream/trait.StreamExt.html#method.split). I found this by expanding all on the docs page for [`tokio_tungstenite::WebSocketStream`](https://docs.rs/tokio-tungstenite/0.14.0/tokio_tungstenite/struct.WebSocketStream.html) and then searching the page for "split"—but this won't work if the implementation is in a different package, as it won't appear in the struct's documentation. – eggyal Jul 02 '21 at 00:47
  • Hi @eggyal thanks for the tip. It helped me realise that I misunderstood what blanket implementations are. `split()` is implemented by `Stream::split` which is a blanket implementation for `Stream`. Seeing as `WebSocketStream` implements `Stream` then it can use all the methods of `StreamExt`. Is this correct? – Dan Jul 02 '21 at 08:37
  • `WebSocketStream` implements `Stream`. There is a blanket implementation of [`StreamExt` for all types that implement `Stream`](https://docs.rs/futures/0.3.15/futures/stream/trait.StreamExt.html#impl-StreamExt). `StreamExt` has a `split` method. It happens that this implementation just uses the default body for `split` that is (and indeed all methods that are) provided in the trait definition. – eggyal Jul 02 '21 at 08:43
  • Thanks for the confirmation. I'll write it up as the answer unless you want to? – Dan Jul 02 '21 at 08:56

1 Answers1

2

The concept I was missing was that of blanket implementations where traits in modules that know nothing about the code in my module can add functionality to my structs. This is so long as the trait bounds of the external code fit my code.

In this situation WebSocketStream implements Stream. There is a trait StreamExt in the futures crate that knows nothing about WebSocketStream but is a blanket implementation for Stream. It provides the functionality of split() to Stream and as WebSocketStream implements Stream it also gets that functionality.

Dan
  • 5,013
  • 5
  • 33
  • 59