The danger is these all fail to grow. Or, rather, for them to work, you have to force the growth on either side.
Consider, you are using a writer to write data. How much can you write before it has to slow down? How do you signal broken data connections? How do you resume a previously stopped writer? How do you stop a writer?
Most of these do not have universal answers. But it gets worse. The main abstraction there was the symbolic byte. How do you convert your code's data to bytes? Is that stable? As in not changing.
So, you can have choke points of small interfaces to connect things. But to make that work, you have a lot to do on both sides.