use super::Error;
use super::generated::*;
macro_rules! messages {
($($variant:ident($payload:ty),)*) => {
#[derive(Clone, Debug, PartialEq)]
pub enum Message {
$(
#[doc = concat!("A `", stringify!($payload), "` payload.")]
$variant($payload),
)*
}
impl Message {
fn type_name(&self) -> &'static str {
match self {
$(Self::$variant(_) => stringify!($payload),)*
}
}
}
$(
impl From<$payload> for Message {
fn from(message: $payload) -> Self {
Self::$variant(message)
}
}
impl TryFrom<Message> for $payload {
type Error = Error;
fn try_from(message: Message) -> Result<Self, Self::Error> {
match message {
Message::$variant(message) => Ok(message),
other => Err(Error::UnexpectedResponse {
expected: stringify!($payload),
received: other.type_name(),
}),
}
}
}
)*
};
}
macro_rules! contents {
($module:ident, $($field:ident => $variant:ident,)*) => {
impl From<$module::Content> for Message {
fn from(content: $module::Content) -> Self {
match content {
$($module::Content::$field(body) => Self::$variant(body),)*
}
}
}
impl TryFrom<Message> for $module::Content {
type Error = Error;
fn try_from(message: Message) -> Result<Self, Self::Error> {
match message {
$(Message::$variant(body) => Ok(Self::$field(body)),)*
other => Err(Error::WrongDirection(other.type_name())),
}
}
}
};
}
include!(concat!(env!("OUT_DIR"), "/message.rs"));
#[cfg(test)]
#[cfg_attr(coverage_nightly, coverage(off))]
mod tests {
use crate::protocol::{self, DeviceInfoRequest, DeviceInfoResponse, Error, Message};
#[test]
fn response_extraction_checks_the_variant() {
use prost::Message as _;
let other = protocol::OnboardingResponse {};
assert!(DeviceInfoResponse::decode(other.encode_to_vec().as_slice()).is_ok());
let message: Message = other.into();
assert!(matches!(
DeviceInfoResponse::try_from(message),
Err(Error::UnexpectedResponse {
expected: "DeviceInfoResponse",
received: "OnboardingResponse",
})
));
let message: Message = DeviceInfoRequest {}.into();
assert!(matches!(
DeviceInfoResponse::try_from(message),
Err(Error::UnexpectedResponse {
expected: "DeviceInfoResponse",
received: "DeviceInfoRequest",
})
));
let response = DeviceInfoResponse {
version_id: 7,
..Default::default()
};
let message: Message = response.clone().into();
assert_eq!(DeviceInfoResponse::try_from(message).unwrap(), response);
let message: Message = vec![1, 2, 3].into();
assert_eq!(Vec::<u8>::try_from(message).unwrap(), vec![1, 2, 3]);
}
}