Post B8Izqa298KU9CqMKMC by lina@tech.lgbt
 (DIR) More posts by lina@tech.lgbt
 (DIR) Post #B8IzqYUmqsCsR5kAim by mcc@mastodon.social
       0 likes, 0 repeats
       
       Rust "should be obvious, but isn't" question.I have an object which is a Futures Stream/Sink. It isn't Clone or Copy. I want to set it up in an async loop where it receives data from the Stream and acts on it. Meanwhile, I want other asynchronous code to send data to the Sink.It doesn't work. `while let Some(value) = streamsink.next().await` requires me to borrow streamsink mutably. Then when other code wants to send it, it's already borrowed. The Refcell panics.(1/2)
       
 (DIR) Post #B8IzqYk1wCOrCMsLTs by mcc@mastodon.social
       0 likes, 0 repeats
       
       This *must* be a common pattern, otherwise people wouldn't combine Sinks and Streams into a single object. It seems like there must be some sort of magic in Futures designed to make full duplex usage of a Stream/Sink object possible. What am I missing? (2/2)
       
 (DIR) Post #B8IzqYufIeuHjLqq3c by mcc@mastodon.social
       0 likes, 0 repeats
       
       Aanswer appears to be .split(), which separates Stream/Sink into two different objects. Not sure how I'm supposed to know that. Also unsure if my problem is fixed. Consider this:- My read fn borrows the Stream forever. Fine- I put the Sink in a RefCell. I need to write, so I spawn_local an async task that borrows Sink then calls sink.send().await().- While this runs, I need to send a second message. I spawn a second task. RefCell panics.is there some second thing for queueing on a Sink?
       
 (DIR) Post #B8IzqZD6C7eUeWTYn2 by fl0und3r@defcon.social
       0 likes, 0 repeats
       
       @mcc this could be a good usecase for an MPSC channel?Basically you have a job which waits on a receiver and you pass senders to your other jobs?
       
 (DIR) Post #B8IzqZO5XGRVCbcKv2 by mcc@mastodon.social
       0 likes, 0 repeats
       
       @fl0und3r Do futures/the standard crates have helpers for this, or do I have to write and spawn my own function that owns the sink, continually unloads from the mpsc ( https://docs.rs/futures/latest/futures/channel/mpsc/fn.unbounded.html ) and dumps into the Sink?
       
 (DIR) Post #B8IzqZdKcadTxskVg8 by lina@tech.lgbt
       0 likes, 0 repeats
       
       @mcc @fl0und3r you could probably just replace the futures stream/sink with the mpsc channel altogether? this sounds like making wrappers for the sake of wrappers
       
 (DIR) Post #B8IzqZpNtmHEZGO8Su by mcc@mastodon.social
       0 likes, 0 repeats
       
       @lina @fl0und3r I am using a Sink because the library I am using https://docs.rs/ws_stream_wasm/latest/ws_stream_wasm/struct.WsStream.html exposes a Sink. Are you suggesting there is some way to turn a Sink into a thing that is not a Sink?
       
 (DIR) Post #B8Izqa298KU9CqMKMC by lina@tech.lgbt
       0 likes, 0 repeats
       
       @mcc @fl0und3r admittedly i haven't worked much with futures Sink/Stream, but futures::channel::mpsc::Receiver seems to impl Stream so i think you should be able to have smth like thislet (rx, tx) = futures::channel::mpsc::unbounded();let ws_sink = get_the_sink_somehow();spawn_task(async move {    ws_sink.send_all(rx).await;    ws_sink.close().await;});the send_all future should complete only when there's no tx leftdoc references:SinkExt.send_allfutures::channel::mpsc
       
 (DIR) Post #B8Izqa3v1ju3ILBk7U by mcc@mastodon.social
       0 likes, 0 repeats
       
       Consensus on this last Q appears to be "create an mpsc and serialize access yourself". That's certainly doable, but given the ton of crap in Futures::SinkExt it seems surprising there isn't standard glue for this already. I can't be the first person to take a Sink and think "okay, now I need to write to it…*twice*".What's very funny is that the Sink in question is a thin wrapper on a JS object, so the target CAN take simultaneous writes, the requirement to serialize is entirely imposed by Rust
       
 (DIR) Post #B8IzqaIS9hWs1PzLm4 by natty@astolfo.social
       0 likes, 0 repeats
       
       @lina@tech.lgbt @mcc@mastodon.social @fl0und3r@defcon.social You don't even need the futures channels tokio-stream has a bunch of useful adapters https://docs.rs/tokio-stream/latest/tokio_stream/wrappers/index.html
       
 (DIR) Post #B8IzqbqsNCesqT6M4G by mcc@mastodon.social
       0 likes, 0 repeats
       
       So I briefly thought the SinkExt-blessed solution to this problem was "don't use send(), use feed()", but that appears to not be the case as a feed *also* mutably borrows the sink for its lifetime.EDIT: also feed() horribly misbehaves but that might be a problem with the library I'm using
       
 (DIR) Post #B8J06LGRoTRQ27Z2n2 by mcc@mastodon.social
       0 likes, 0 repeats
       
       @natty @fl0und3r @lina if i was using tokio i'd have been done two days ago lol
       
 (DIR) Post #B8J06LVgtndOnOhDY8 by natty@astolfo.social
       0 likes, 0 repeats
       
       @mcc@mastodon.social @fl0und3r@defcon.social @lina@tech.lgbt Ah you didn't pick it in the end
       
 (DIR) Post #B8J0mIumwEB8uRRUHI by mcc@mastodon.social
       1 likes, 0 repeats
       
       @natty @fl0und3r @lina it technically would have required adding another abstraction layer so i decided to get it working with futures first and then add tokio once i had a futures version working so i could see what it did to my binary size