use crate::libs::ws::message::{CloseFrame, Utf8Bytes, WireMessage};
use nago_wss::proto::message::{CloseFrame as NCloseFrame, Message as NMessage};
impl From<WireMessage> for NMessage {
fn from(msg: WireMessage) -> Self {
match msg {
WireMessage::Text(text) => Self::Text(text.into_bytes()),
WireMessage::Binary(payload) => Self::Binary(payload),
WireMessage::Ping(payload) => Self::Ping(payload),
WireMessage::Pong(payload) => Self::Pong(payload),
WireMessage::Close(frame) => Self::Close(frame.map(|frame| NCloseFrame {
code: frame.code.into(),
reason: frame.reason.into_bytes(),
})),
}
}
}
impl From<NMessage> for WireMessage {
fn from(msg: NMessage) -> Self {
match msg {
NMessage::Text(payload) => {
Self::Text(unsafe { Utf8Bytes::from_bytes_unchecked(payload) })
}
NMessage::Binary(payload) => Self::Binary(payload),
NMessage::Ping(payload) => Self::Ping(payload),
NMessage::Pong(payload) => Self::Pong(payload),
NMessage::Close(frame) => Self::Close(frame.map(|frame| CloseFrame {
code: frame.code.into(),
reason: unsafe { Utf8Bytes::from_bytes_unchecked(frame.reason) },
})),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn round_trips_every_variant() {
let cases = vec![
WireMessage::Text("hello".into()),
WireMessage::Binary(vec![1, 2, 3].into()),
WireMessage::Ping(vec![4].into()),
WireMessage::Pong(vec![5].into()),
WireMessage::Close(None),
WireMessage::Close(Some(CloseFrame {
code: 1000,
reason: "bye".into(),
})),
];
for case in cases {
let there: NMessage = case.clone().into();
let back: WireMessage = there.into();
assert_eq!(case, back, "round trip changed the message");
}
}
#[test]
fn the_payload_allocation_survives_both_directions() {
let binary = bytes::Bytes::from_static(b"shared binary");
let pointer = binary.as_ptr();
let NMessage::Binary(out) = NMessage::from(WireMessage::Binary(binary)) else {
panic!("binary message changed kind");
};
assert_eq!(out.as_ptr(), pointer);
let text = bytes::Bytes::from_static(b"shared text");
let pointer = text.as_ptr();
let WireMessage::Text(back) = WireMessage::from(NMessage::Text(text)) else {
panic!("text message changed kind");
};
assert_eq!(back.as_bytes().as_ptr(), pointer);
}
#[test]
fn the_close_code_survives_the_newtype() {
let NMessage::Close(Some(frame)) = NMessage::from(WireMessage::Close(Some(CloseFrame {
code: 1011,
reason: "internal".into(),
}))) else {
panic!("close message changed kind");
};
assert_eq!(u16::from(frame.code), 1011);
assert_eq!(frame.reason, bytes::Bytes::from_static(b"internal"));
let WireMessage::Close(Some(frame)) =
WireMessage::from(NMessage::Close(Some(NCloseFrame {
code: nago_wss::CloseCode(1011),
reason: bytes::Bytes::from_static(b"internal"),
})))
else {
panic!("close message changed kind");
};
assert_eq!(frame.code, 1011);
assert_eq!(frame.reason.as_str(), "internal");
}
}