use crate::live::{BadSubscription, Subscription};
use crate::utils::Json;
use serde::Deserialize;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum Method {
Subscribe,
Unsubscribe,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Ack {
pub method: Method,
pub echo: Json,
}
impl Ack {
pub fn subscription(&self) -> Result<Subscription, BadSubscription> {
Subscription::parse(&self.echo)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Refusal {
pub message: String,
}
impl Refusal {
#[must_use]
pub fn post_id(&self) -> Option<u64> {
if let Some((_, digits)) = self.message.rsplit_once("id=")
&& !digits.is_empty()
&& digits.bytes().all(|byte| byte.is_ascii_digit())
{
return digits.parse().ok();
}
let quoted = self.quoted()?;
match quoted.get("method").and_then(Json::as_str) {
Some("post") => quoted.get("id").and_then(Json::as_u64),
_ => None,
}
}
#[must_use]
pub fn subscription(&self) -> Option<Subscription> {
let quoted = self.quoted()?;
let subscription = match quoted.get("subscription") {
Some(inside) => inside,
None if ["Already subscribed", "Already unsubscribed", "Invalid subscription"]
.iter()
.any(|start| self.message.starts_with(start)) =>
{
"ed
}
None => return None,
};
Subscription::parse(subscription).ok()
}
fn quoted(&self) -> Option<Json> {
let at = self.message.find('{')?;
Json::parse(self.message.get(at..)?).ok()
}
}
#[cfg(test)]
#[path = "tests/control.rs"]
mod tests;