The weird-looking Rust isn’t really Rust being weird, it’s the type telling the truth.
Result<Option<Result<Message, WsError>>, Elapsed>
That’s three independent “not the happy path” channels: timeout, stream closed,
and websocket error.
The nicer version is not a cleverer match. It’s choosing a domain error shape
and converting into it one layer at a time:
let timed = tokio::time::timeout(duration, receiver.next()).await;
let next = timed.map_err(|_| ReceiveError::Timeout)?;
let item = next.ok_or(ReceiveError::Closed)?;
let msg = item.map_err(ReceiveError::WebSocket)?;
The ugly line is what happens when you have not decided where to normalize the
shape yet.
The weird-looking Rust isn’t really Rust being weird, it’s the type telling the truth.
That’s three independent “not the happy path” channels: timeout, stream closed, and websocket error.The nicer version is not a cleverer match. It’s choosing a domain error shape and converting into it one layer at a time:
The ugly line is what happens when you have not decided where to normalize the shape yet.Was anyone else expecting OpenClaw over gopher protocol?