use crate::request::prelude::*;
use bytes::Bytes;
use serde::de::DeserializeSeed;
use std::{
error::Error,
fmt::{Display, Formatter, Result as FmtResult},
future::Future,
pin::Pin,
task::{Context, Poll},
};
use twilight_model::{
guild::member::{Member, MemberDeserializer},
id::{GuildId, UserId},
};
#[cfg(not(feature = "simd-json"))]
use serde_json::Value;
#[cfg(feature = "simd-json")]
use simd_json::value::OwnedValue as Value;
#[derive(Clone, Debug)]
#[non_exhaustive]
pub enum GetGuildMembersError {
LimitInvalid {
limit: u64,
},
}
impl Display for GetGuildMembersError {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
match self {
Self::LimitInvalid { .. } => f.write_str("the limit is invalid"),
}
}
}
impl Error for GetGuildMembersError {}
#[derive(Default)]
struct GetGuildMembersFields {
after: Option<UserId>,
limit: Option<u64>,
presences: Option<bool>,
}
pub struct GetGuildMembers<'a> {
fields: GetGuildMembersFields,
fut: Option<Pending<'a, Bytes>>,
guild_id: GuildId,
http: &'a Client,
}
impl<'a> GetGuildMembers<'a> {
pub(crate) fn new(http: &'a Client, guild_id: GuildId) -> Self {
Self {
fields: GetGuildMembersFields::default(),
fut: None,
guild_id,
http,
}
}
pub fn after(mut self, after: UserId) -> Self {
self.fields.after.replace(after);
self
}
pub fn limit(mut self, limit: u64) -> Result<Self, GetGuildMembersError> {
if !validate::get_guild_members_limit(limit) {
return Err(GetGuildMembersError::LimitInvalid { limit });
}
self.fields.limit.replace(limit);
Ok(self)
}
pub fn presences(mut self, presences: bool) -> Self {
self.fields.presences.replace(presences);
self
}
fn start(&mut self) -> Result<()> {
self.fut
.replace(Box::pin(self.http.request_bytes(Request::from(
Route::GetGuildMembers {
after: self.fields.after.map(|x| x.0),
guild_id: self.guild_id.0,
limit: self.fields.limit,
presences: self.fields.presences,
},
))));
Ok(())
}
}
impl Future for GetGuildMembers<'_> {
type Output = Result<Vec<Member>>;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
if self.fut.is_none() {
self.as_mut().start()?;
}
let fut = self.fut.as_mut().expect("future is created");
match fut.as_mut().poll(cx) {
Poll::Ready(res) => {
let bytes = res?;
let mut members = Vec::new();
let mut bytes = bytes.as_ref().to_vec();
let values = crate::json_from_slice::<Vec<Value>>(&mut bytes)?;
for value in values {
let member_deserializer = MemberDeserializer::new(self.guild_id);
members.push(member_deserializer.deserialize(value)?);
}
Poll::Ready(Ok(members))
}
Poll::Pending => Poll::Pending,
}
}
}