use super::{
callback, poll::Answer, shipping, ChosenInlineResult, InlineQuery, Message,
Poll, PreCheckoutQuery,
};
use is_macro::Is;
use serde::{
de::{Deserializer, Error, IgnoredAny, MapAccess, Visitor},
Deserialize,
};
use std::fmt::{self, Formatter};
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, Deserialize)]
#[serde(transparent)]
pub struct Id(pub isize);
#[derive(Debug, PartialEq, Clone, Is)]
#[allow(clippy::large_enum_variant)]
#[non_exhaustive]
pub enum Kind {
Message(Message),
EditedMessage(Message),
ChannelPost(Message),
EditedChannelPost(Message),
InlineQuery(InlineQuery),
CallbackQuery(callback::Query),
Poll(Poll),
PollAnswer(Answer),
ChosenInlineResult(ChosenInlineResult),
ShippingQuery(shipping::Query),
PreCheckoutQuery(PreCheckoutQuery),
Unknown,
}
#[derive(Debug)]
#[non_exhaustive]
pub struct Update {
pub id: Id,
pub kind: Kind,
}
const UPDATE_ID: &str = "update_id";
const MESSAGE: &str = "message";
const EDITED_MESSAGE: &str = "edited_message";
const CHANNEL_POST: &str = "channel_post";
const EDITED_CHANNEL_POST: &str = "edited_channel_post";
const INLINE_QUERY: &str = "inline_query";
const CALLBACK_QUERY: &str = "callback_query";
const CHOSEN_INLINE_RESULT: &str = "chosen_inline_result";
const SHIPPING_QUERY: &str = "shipping_query";
const PRE_CHECKOUT_QUERY: &str = "pre_checkout_query";
const POLL: &str = "poll";
const POLL_ANSWER: &str = "poll_answer";
struct UpdateVisitor;
impl<'v> Visitor<'v> for UpdateVisitor {
type Value = Update;
fn expecting(&self, fmt: &mut Formatter) -> fmt::Result {
write!(fmt, "struct Update")
}
fn visit_map<V>(self, mut map: V) -> Result<Self::Value, V::Error>
where
V: MapAccess<'v>,
{
let mut id = None;
let mut kind = None;
while let Some(key) = map.next_key()? {
match key {
UPDATE_ID => id = Some(map.next_value()?),
MESSAGE => kind = Some(Kind::Message(map.next_value()?)),
EDITED_MESSAGE => {
kind = Some(Kind::EditedMessage(map.next_value()?))
}
CHANNEL_POST => {
kind = Some(Kind::ChannelPost(map.next_value()?))
}
EDITED_CHANNEL_POST => {
kind = Some(Kind::EditedChannelPost(map.next_value()?))
}
INLINE_QUERY => {
kind = Some(Kind::InlineQuery(map.next_value()?))
}
CALLBACK_QUERY => {
kind = Some(Kind::CallbackQuery(map.next_value()?))
}
CHOSEN_INLINE_RESULT => {
kind = Some(Kind::ChosenInlineResult(map.next_value()?))
}
SHIPPING_QUERY => {
kind = Some(Kind::ShippingQuery(map.next_value()?))
}
PRE_CHECKOUT_QUERY => {
kind = Some(Kind::PreCheckoutQuery(map.next_value()?))
}
POLL => kind = Some(Kind::Poll(map.next_value()?)),
POLL_ANSWER => kind = Some(Kind::PollAnswer(map.next_value()?)),
_ => {
let _ = map.next_value::<IgnoredAny>()?;
}
}
}
Ok(Update {
id: id.ok_or_else(|| Error::missing_field(UPDATE_ID))?,
kind: kind.unwrap_or(Kind::Unknown),
})
}
}
impl<'de> Deserialize<'de> for Update {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_struct(
"Update",
&[
UPDATE_ID,
MESSAGE,
EDITED_MESSAGE,
CHANNEL_POST,
EDITED_CHANNEL_POST,
INLINE_QUERY,
CHOSEN_INLINE_RESULT,
SHIPPING_QUERY,
PRE_CHECKOUT_QUERY,
POLL,
POLL_ANSWER,
],
UpdateVisitor,
)
}
}