use crate::types::User;
use is_macro::Is;
use serde::de::{
Deserialize, Deserializer, Error, IgnoredAny, MapAccess, Visitor,
};
#[derive(Debug, PartialEq, Eq, Clone, Hash, Is)]
#[non_exhaustive]
pub enum Status {
#[non_exhaustive]
Creator {
custom_title: Option<String>,
},
#[non_exhaustive]
Administrator {
custom_title: Option<String>,
can_be_edited: bool,
can_change_info: bool,
can_post_messages: Option<bool>,
can_edit_messages: Option<bool>,
can_delete_messages: bool,
can_invite_users: bool,
can_restrict_members: bool,
can_pin_messages: Option<bool>,
can_promote_members: bool,
},
Member,
#[non_exhaustive]
Restricted {
until_date: Option<i64>,
is_member: bool,
can_send_mesages: bool,
can_send_media_messages: bool,
can_send_other_messages: bool,
can_add_web_page_previews: bool,
can_send_polls: bool,
can_change_info: bool,
can_invite_users: bool,
can_pin_messages: bool,
},
Left,
#[non_exhaustive]
Kicked {
until_date: Option<i64>,
},
}
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
#[non_exhaustive]
pub struct Member {
pub user: User,
pub status: Status,
}
const USER: &str = "user";
const STATUS: &str = "status";
const CUSTOM_TITLE: &str = "custom_title";
const UNTIL_DATE: &str = "until_date";
const CAN_BE_EDITED: &str = "can_be_edited";
const CAN_CHANGE_INFO: &str = "can_change_info";
const CAN_POST_MESSAGES: &str = "can_post_messages";
const CAN_EDIT_MESSAGES: &str = "can_edit_messages";
const CAN_DELETE_MESSAGES: &str = "can_delete_messages";
const CAN_INVITE_USERS: &str = "can_invite_users";
const CAN_RESTRICT_MEMBERS: &str = "can_restrict_members";
const CAN_PIN_MESSAGES: &str = "can_pin_messages";
const CAN_PROMOTE_MEMBERS: &str = "can_promote_members";
const IS_MEMBER: &str = "is_member";
const CAN_SEND_MESSAGES: &str = "can_send_messages";
const CAN_SEND_MEDIA_MESSAGES: &str = "can_send_media_messages";
const CAN_SEND_OTHER_MESSAGES: &str = "can_send_other_messages";
const CAN_SEND_POLLS: &str = "can_send_polls";
const CAN_ADD_WEB_PAGE_PREVIEWS: &str = "can_add_web_page_previews";
const CREATOR: &str = "creator";
const ADMINISTRATOR: &str = "administrator";
const MEMBER: &str = "member";
const RESTRICTED: &str = "restricted";
const LEFT: &str = "left";
const KICKED: &str = "kicked";
struct MemberVisitor;
impl<'v> Visitor<'v> for MemberVisitor {
type Value = Member;
fn expecting(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(fmt, "struct Member")
}
#[allow(clippy::too_many_lines)] fn visit_map<V>(self, mut map: V) -> Result<Self::Value, V::Error>
where
V: MapAccess<'v>,
{
let mut user = None;
let mut status = None;
let mut custom_title = None;
let mut until_date = None;
let mut can_be_edited = None;
let mut can_change_info = None;
let mut can_post_messages = None;
let mut can_edit_messages = None;
let mut can_delete_messages = None;
let mut can_invite_users = None;
let mut can_restrict_members = None;
let mut can_pin_messages = None;
let mut can_promote_members = None;
let mut is_member = None;
let mut can_send_messages = None;
let mut can_send_media_messages = None;
let mut can_send_other_messages = None;
let mut can_send_polls = None;
let mut can_add_web_page_previews = None;
while let Some(key) = map.next_key()? {
match key {
USER => user = Some(map.next_value()?),
STATUS => status = Some(map.next_value()?),
CUSTOM_TITLE => custom_title = Some(map.next_value()?),
UNTIL_DATE => until_date = Some(map.next_value()?),
CAN_BE_EDITED => can_be_edited = Some(map.next_value()?),
CAN_CHANGE_INFO => can_change_info = Some(map.next_value()?),
CAN_POST_MESSAGES => {
can_post_messages = Some(map.next_value()?)
}
CAN_EDIT_MESSAGES => {
can_edit_messages = Some(map.next_value()?)
}
CAN_DELETE_MESSAGES => {
can_delete_messages = Some(map.next_value()?)
}
CAN_INVITE_USERS => can_invite_users = Some(map.next_value()?),
CAN_RESTRICT_MEMBERS => {
can_restrict_members = Some(map.next_value()?)
}
CAN_PIN_MESSAGES => can_pin_messages = Some(map.next_value()?),
CAN_PROMOTE_MEMBERS => {
can_promote_members = Some(map.next_value()?)
}
IS_MEMBER => is_member = Some(map.next_value()?),
CAN_SEND_MESSAGES => {
can_send_messages = Some(map.next_value()?)
}
CAN_SEND_MEDIA_MESSAGES => {
can_send_media_messages = Some(map.next_value()?)
}
CAN_SEND_OTHER_MESSAGES => {
can_send_other_messages = Some(map.next_value()?)
}
CAN_SEND_POLLS => can_send_polls = Some(map.next_value()?),
CAN_ADD_WEB_PAGE_PREVIEWS => {
can_add_web_page_previews = Some(map.next_value()?)
}
_ => {
let _ = map.next_value::<IgnoredAny>()?;
}
}
}
let status = match &status {
Some(CREATOR) => Status::Creator { custom_title },
Some(ADMINISTRATOR) => Status::Administrator {
custom_title,
can_be_edited: can_be_edited
.ok_or_else(|| Error::missing_field(CAN_BE_EDITED))?,
can_change_info: can_change_info
.ok_or_else(|| Error::missing_field(CAN_CHANGE_INFO))?,
can_post_messages,
can_edit_messages,
can_delete_messages: can_delete_messages
.ok_or_else(|| Error::missing_field(CAN_DELETE_MESSAGES))?,
can_invite_users: can_invite_users
.ok_or_else(|| Error::missing_field(CAN_INVITE_USERS))?,
can_restrict_members: can_restrict_members.ok_or_else(
|| Error::missing_field(CAN_RESTRICT_MEMBERS),
)?,
can_pin_messages,
can_promote_members: can_promote_members
.ok_or_else(|| Error::missing_field(CAN_PROMOTE_MEMBERS))?,
},
Some(MEMBER) => Status::Member,
Some(RESTRICTED) => Status::Restricted {
until_date,
is_member: is_member
.ok_or_else(|| Error::missing_field(IS_MEMBER))?,
can_send_mesages: can_send_messages
.ok_or_else(|| Error::missing_field(CAN_SEND_MESSAGES))?,
can_send_media_messages: can_send_media_messages.ok_or_else(
|| Error::missing_field(CAN_SEND_MEDIA_MESSAGES),
)?,
can_send_other_messages: can_send_other_messages.ok_or_else(
|| Error::missing_field(CAN_SEND_OTHER_MESSAGES),
)?,
can_send_polls: can_send_polls
.ok_or_else(|| Error::missing_field(CAN_SEND_POLLS))?,
can_add_web_page_previews: can_add_web_page_previews
.ok_or_else(|| {
Error::missing_field(CAN_ADD_WEB_PAGE_PREVIEWS)
})?,
can_change_info: can_change_info
.ok_or_else(|| Error::missing_field(CAN_CHANGE_INFO))?,
can_invite_users: can_invite_users
.ok_or_else(|| Error::missing_field(CAN_INVITE_USERS))?,
can_pin_messages: can_pin_messages
.ok_or_else(|| Error::missing_field(CAN_PIN_MESSAGES))?,
},
Some(LEFT) => Status::Left,
Some(KICKED) => Status::Kicked { until_date },
Some(unknown_status) => {
return Err(Error::unknown_variant(
unknown_status,
&[CREATOR, ADMINISTRATOR, MEMBER, RESTRICTED, LEFT, KICKED],
))
}
None => return Err(Error::missing_field(STATUS)),
};
Ok(Member {
user: user.ok_or_else(|| Error::missing_field(USER))?,
status,
})
}
}
impl<'de> Deserialize<'de> for Member {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_struct(
"Member",
&[
USER,
STATUS,
CUSTOM_TITLE,
UNTIL_DATE,
CAN_BE_EDITED,
CAN_CHANGE_INFO,
CAN_POST_MESSAGES,
CAN_EDIT_MESSAGES,
CAN_DELETE_MESSAGES,
CAN_INVITE_USERS,
CAN_RESTRICT_MEMBERS,
CAN_PIN_MESSAGES,
CAN_PROMOTE_MEMBERS,
IS_MEMBER,
CAN_SEND_MESSAGES,
CAN_SEND_MEDIA_MESSAGES,
CAN_SEND_OTHER_MESSAGES,
CAN_ADD_WEB_PAGE_PREVIEWS,
],
MemberVisitor,
)
}
}