use bytes::Buf;
use serde::Deserialize;
use crate::protocol::{BinaryMessage, BinaryPayload, ParseError};
mod message_data;
#[allow(unused_imports)]
pub use crate::protocol::common::server::advertise;
pub use crate::protocol::common::server::server_info;
pub use crate::protocol::common::server::{
Advertise, AdvertiseServices, ConnectionGraphUpdate, FetchAssetResponse, ParameterValues,
PlaybackState, RemoveStatus, ServerInfo, ServiceCallFailure, ServiceCallResponse, Status, Time,
Unadvertise, UnadvertiseServices,
};
pub use message_data::MessageData;
#[repr(u8)]
pub(crate) enum BinaryOpcode {
MessageData = 1,
Time = 2,
ServiceCallResponse = 3,
FetchAssetResponse = 4,
#[doc(hidden)]
PlaybackState = 5,
}
impl BinaryOpcode {
pub(crate) fn from_repr(value: u8) -> Option<Self> {
match value {
1 => Some(Self::MessageData),
2 => Some(Self::Time),
3 => Some(Self::ServiceCallResponse),
4 => Some(Self::FetchAssetResponse),
5 => Some(Self::PlaybackState),
_ => None,
}
}
}
impl<'a> BinaryMessage<'a> for MessageData<'a> {
const OPCODE: u8 = BinaryOpcode::MessageData as u8;
}
#[derive(Debug, Clone, PartialEq)]
#[allow(missing_docs)]
pub enum ServerMessage<'a> {
ServerInfo(ServerInfo),
Status(Status),
RemoveStatus(RemoveStatus),
Advertise(Advertise<'a>),
Unadvertise(Unadvertise),
MessageData(MessageData<'a>),
Time(Time),
ParameterValues(ParameterValues),
AdvertiseServices(AdvertiseServices<'a>),
UnadvertiseServices(UnadvertiseServices),
ServiceCallResponse(ServiceCallResponse<'a>),
ConnectionGraphUpdate(ConnectionGraphUpdate),
FetchAssetResponse(FetchAssetResponse<'a>),
ServiceCallFailure(ServiceCallFailure),
PlaybackState(PlaybackState),
}
impl<'a> ServerMessage<'a> {
pub fn parse_json(json: &'a str) -> Result<Self, ParseError> {
let msg = serde_json::from_str::<JsonMessage>(json)?;
Ok(msg.into())
}
pub fn parse_binary(mut data: &'a [u8]) -> Result<Self, ParseError> {
if data.is_empty() {
Err(ParseError::EmptyBinaryMessage)
} else {
let opcode = data.get_u8();
match BinaryOpcode::from_repr(opcode) {
Some(BinaryOpcode::MessageData) => {
MessageData::parse_payload(data).map(ServerMessage::MessageData)
}
Some(BinaryOpcode::Time) => Time::parse_payload(data).map(ServerMessage::Time),
Some(BinaryOpcode::ServiceCallResponse) => {
ServiceCallResponse::parse_payload(data).map(ServerMessage::ServiceCallResponse)
}
Some(BinaryOpcode::FetchAssetResponse) => {
FetchAssetResponse::parse_payload(data).map(ServerMessage::FetchAssetResponse)
}
Some(BinaryOpcode::PlaybackState) => {
PlaybackState::parse_payload(data).map(ServerMessage::PlaybackState)
}
None => Err(ParseError::InvalidOpcode(opcode)),
}
}
}
#[allow(dead_code)]
pub fn into_owned(self) -> ServerMessage<'static> {
match self {
ServerMessage::ServerInfo(m) => ServerMessage::ServerInfo(m),
ServerMessage::Status(m) => ServerMessage::Status(m),
ServerMessage::RemoveStatus(m) => ServerMessage::RemoveStatus(m),
ServerMessage::Advertise(m) => ServerMessage::Advertise(m.into_owned()),
ServerMessage::Unadvertise(m) => ServerMessage::Unadvertise(m),
ServerMessage::MessageData(m) => ServerMessage::MessageData(m.into_owned()),
ServerMessage::Time(m) => ServerMessage::Time(m),
ServerMessage::ParameterValues(m) => ServerMessage::ParameterValues(m),
ServerMessage::AdvertiseServices(m) => ServerMessage::AdvertiseServices(m.into_owned()),
ServerMessage::UnadvertiseServices(m) => ServerMessage::UnadvertiseServices(m),
ServerMessage::ServiceCallResponse(m) => {
ServerMessage::ServiceCallResponse(m.into_owned())
}
ServerMessage::ConnectionGraphUpdate(m) => ServerMessage::ConnectionGraphUpdate(m),
ServerMessage::FetchAssetResponse(m) => {
ServerMessage::FetchAssetResponse(m.into_owned())
}
ServerMessage::ServiceCallFailure(m) => ServerMessage::ServiceCallFailure(m),
ServerMessage::PlaybackState(m) => ServerMessage::PlaybackState(m),
}
}
}
#[derive(Deserialize)]
#[serde(tag = "op", rename_all = "camelCase")]
enum JsonMessage<'a> {
ServerInfo(ServerInfo),
Status(Status),
RemoveStatus(RemoveStatus),
#[serde(borrow)]
Advertise(Advertise<'a>),
Unadvertise(Unadvertise),
ParameterValues(ParameterValues),
#[serde(borrow)]
AdvertiseServices(AdvertiseServices<'a>),
UnadvertiseServices(UnadvertiseServices),
ConnectionGraphUpdate(ConnectionGraphUpdate),
ServiceCallFailure(ServiceCallFailure),
}
impl<'a> From<JsonMessage<'a>> for ServerMessage<'a> {
fn from(m: JsonMessage<'a>) -> Self {
match m {
JsonMessage::ServerInfo(m) => Self::ServerInfo(m),
JsonMessage::Status(m) => Self::Status(m),
JsonMessage::RemoveStatus(m) => Self::RemoveStatus(m),
JsonMessage::Advertise(m) => Self::Advertise(m),
JsonMessage::Unadvertise(m) => Self::Unadvertise(m),
JsonMessage::ParameterValues(m) => Self::ParameterValues(m),
JsonMessage::AdvertiseServices(m) => Self::AdvertiseServices(m),
JsonMessage::UnadvertiseServices(m) => Self::UnadvertiseServices(m),
JsonMessage::ConnectionGraphUpdate(m) => Self::ConnectionGraphUpdate(m),
JsonMessage::ServiceCallFailure(m) => Self::ServiceCallFailure(m),
}
}
}