use super::subscription_wire::next_frame;
use super::{DeliveredMessage, Frame, Mailbox, SdkError, TcpStream, ToString, Vec, format};
use crate::remote::mailbox::{ReaderEnd, offer_or_end};
pub(super) fn run_reader(
mut stream: TcpStream,
mut buffer: Vec<u8>,
mailbox: &Mailbox<DeliveredMessage>,
) -> ReaderEnd {
loop {
let frame = match next_frame(&mut stream, &mut buffer) {
Ok(frame) => frame,
Err(error) => return ReaderEnd::Failed(error),
};
match frame {
Frame::Deliver {
delivery_seq,
envelope,
message,
..
} => {
let message = DeliveredMessage {
delivery_seq,
schema_id: envelope.schema_id,
payload: envelope.payload,
message,
};
if let Some(end) = offer_or_end(mailbox, message) {
return end;
}
}
Frame::Disconnect { .. } => {
return ReaderEnd::Failed(SdkError::Connection {
description: "subscription receive failed: the server disconnected the \
subscription"
.to_string(),
});
}
Frame::SubscribeError {
reason_code,
message,
..
} => {
return ReaderEnd::Failed(subscription_ended(reason_code, message));
}
_ => {
if let Err(error) = mailbox.record_ignored_frame() {
return ReaderEnd::Failed(error);
}
}
}
}
}
fn subscription_ended(reason_code: u16, message: Option<alloc::string::String>) -> SdkError {
SdkError::Protocol {
description: format!(
"server ended the subscription (reason {reason_code}): {}",
message.unwrap_or_else(|| "no detail".to_string())
),
}
}