use crate::ascii::{
command::Target,
response::{packet, AnyResponse, Header, Response, SpecificResponse, Status, Warning},
};
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Flag {
Ok,
Rj,
}
impl Flag {
pub(crate) const OK_STR: &'static str = "OK";
pub(crate) const RJ_STR: &'static str = "RJ";
}
impl std::fmt::Display for Flag {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Flag::Ok => write!(f, "{}", Flag::OK_STR),
Flag::Rj => write!(f, "{}", Flag::RJ_STR),
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub(crate) struct ReplyInner {
pub target: Target,
pub id: Option<u8>,
pub flag: Flag,
pub status: Status,
pub warning: Warning,
pub data: String,
}
#[derive(Debug, Clone, PartialEq)]
pub struct Reply(pub(super) Box<ReplyInner>);
impl Reply {
pub(crate) fn try_from_packet<T>(packet: &packet::Packet<T>) -> Result<Self, &packet::Packet<T>>
where
T: AsRef<[u8]>,
{
if packet.kind() != packet::PacketKind::Reply || packet.cont() {
return Err(packet);
}
Ok(ReplyInner {
target: packet.target(),
id: packet.id(),
flag: packet.flag().ok_or(packet)?,
status: packet.status().ok_or(packet)?,
warning: packet.warning().ok_or(packet)?,
data: packet.data().to_string(),
}
.into())
}
pub fn target(&self) -> Target {
self.0.target
}
pub fn id(&self) -> Option<u8> {
self.0.id
}
pub fn flag(&self) -> Flag {
self.0.flag
}
pub fn status(&self) -> Status {
self.0.status
}
pub fn warning(&self) -> Warning {
self.0.warning
}
pub fn data(&self) -> &str {
self.0.data.as_str()
}
}
impl From<ReplyInner> for Reply {
fn from(inner: ReplyInner) -> Self {
Reply(Box::new(inner))
}
}
impl std::convert::TryFrom<AnyResponse> for Reply {
type Error = AnyResponse;
fn try_from(response: AnyResponse) -> Result<Self, Self::Error> {
if let AnyResponse::Reply(reply) = response {
Ok(reply)
} else {
Err(response)
}
}
}
impl std::fmt::Display for Reply {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", char::from(packet::REPLY_MARKER))?;
Header {
address: self.target().device(),
axis: self.target().axis(),
id: self.id(),
}
.fmt(f)?;
write!(f, " ")?;
self.flag().fmt(f)?;
write!(f, " ")?;
self.status().fmt(f)?;
write!(f, " ")?;
self.warning().fmt(f)?;
if !self.data().is_empty() {
write!(f, " {}", self.data())?;
}
Ok(())
}
}
impl Response for Reply {
fn target(&self) -> Target {
self.target()
}
fn id(&self) -> Option<u8> {
self.id()
}
fn data(&self) -> &str {
self.data()
}
}
impl SpecificResponse for Reply {}