use std::{ops::Deref, vec};
use ruma_common::OwnedEventId;
use ruma_macros::EventContent;
use serde::{Deserialize, Serialize};
use super::{start::PollContentBlock, validate_selections, PollResponseData};
use crate::relation::Reference;
#[derive(Clone, Debug, Serialize, Deserialize, EventContent)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[ruma_event(type = "m.poll.response", kind = MessageLike)]
pub struct PollResponseEventContent {
#[serde(rename = "m.selections")]
pub selections: SelectionsContentBlock,
#[cfg(feature = "unstable-msc3955")]
#[serde(
default,
skip_serializing_if = "ruma_common::serde::is_default",
rename = "org.matrix.msc1767.automated"
)]
pub automated: bool,
#[serde(rename = "m.relates_to")]
pub relates_to: Reference,
}
impl PollResponseEventContent {
pub fn new(selections: SelectionsContentBlock, poll_start_id: OwnedEventId) -> Self {
Self {
selections,
#[cfg(feature = "unstable-msc3955")]
automated: false,
relates_to: Reference::new(poll_start_id),
}
}
}
impl OriginalSyncPollResponseEvent {
pub fn data(&self) -> PollResponseData<'_> {
PollResponseData {
sender: &self.sender,
origin_server_ts: self.origin_server_ts,
selections: &self.content.selections,
}
}
}
impl OriginalPollResponseEvent {
pub fn data(&self) -> PollResponseData<'_> {
PollResponseData {
sender: &self.sender,
origin_server_ts: self.origin_server_ts,
selections: &self.content.selections,
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub struct SelectionsContentBlock(Vec<String>);
impl SelectionsContentBlock {
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn validate<'a>(
&'a self,
poll: &PollContentBlock,
) -> Option<impl Iterator<Item = &'a str>> {
let answer_ids = poll.answers.iter().map(|a| a.id.as_str()).collect();
validate_selections(&answer_ids, poll.max_selections, &self.0)
}
}
impl From<Vec<String>> for SelectionsContentBlock {
fn from(value: Vec<String>) -> Self {
Self(value)
}
}
impl IntoIterator for SelectionsContentBlock {
type Item = String;
type IntoIter = vec::IntoIter<String>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
impl FromIterator<String> for SelectionsContentBlock {
fn from_iter<T: IntoIterator<Item = String>>(iter: T) -> Self {
Self(Vec::from_iter(iter))
}
}
impl Deref for SelectionsContentBlock {
type Target = [String];
fn deref(&self) -> &Self::Target {
&self.0
}
}