use core::{
fmt::{Display, Formatter, Result as FmtResult},
result::Result as StdResult,
};
use thiserror::Error as ThisError;
use crate::api_verb::ApiVerb;
pub(crate) struct Message {
pub(crate) verb: ApiVerb,
pub(crate) msg: String,
}
#[derive(Debug, ThisError)]
#[non_exhaustive]
pub enum Error {
#[error("failed to parse status: {0}")]
ParsingFailed(String),
}
impl From<Message> for String {
#[inline]
fn from(value: Message) -> Self {
Self::from(&value)
}
}
impl From<&Message> for String {
#[inline]
fn from(value: &Message) -> Self {
format!("{}:{}", value.verb, value.msg)
}
}
impl TryFrom<String> for Message {
type Error = Error;
fn try_from(value: String) -> StdResult<Self, Self::Error> {
Self::try_from(value.as_str())
}
}
impl TryFrom<&str> for Message {
type Error = Error;
fn try_from(value: &str) -> StdResult<Self, Self::Error> {
let parts = value.split_once(':');
let parts_converted = match parts {
None => (
ApiVerb::try_from(value)
.map_err(|err| Error::ParsingFailed(format!("invalid message: {err}")))?,
String::new(),
),
Some((verb, msg)) => (
ApiVerb::try_from(verb)
.map_err(|err| Error::ParsingFailed(format!("invalid message: {err}")))?,
msg.to_owned(),
),
};
Ok(Self {
verb: parts_converted.0,
msg: parts_converted.1,
})
}
}
impl Display for Message {
#[expect(clippy::min_ident_chars, reason = "defined by trait")]
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
write!(f, "{}", String::from(self))
}
}