use crate::{contexts::fields::Message, types::chat};
use serde::{Deserialize, Serialize};
use std::{
collections::hash_map::{self, Entry, HashMap, IntoIter},
iter::FromIterator,
ops::Index,
};
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
#[serde(transparent)]
pub struct Chats<S> {
chats: HashMap<chat::Id, S>,
}
impl<S> Chats<S> {
#[must_use]
pub fn new() -> Self {
Self {
chats: HashMap::new(),
}
}
#[must_use]
pub fn with_capacity(capacity: usize) -> Self {
Self {
chats: HashMap::with_capacity(capacity),
}
}
pub fn chats(&self) -> impl Iterator<Item = chat::Id> + '_ {
self.chats.keys().copied()
}
pub fn states(&self) -> impl Iterator<Item = &S> {
self.chats.values()
}
pub fn iter(&self) -> impl Iterator<Item = (chat::Id, &S)> {
Iter(self.chats.iter())
}
pub fn iter_mut(&mut self) -> impl Iterator<Item = (chat::Id, &mut S)> {
IterMut(self.chats.iter_mut())
}
#[must_use]
pub fn len(&self) -> usize {
self.chats.len()
}
#[must_use]
pub fn capacity(&self) -> usize {
self.chats.capacity()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.chats.is_empty()
}
#[must_use = "use `clear` if you don't need the iterator"]
pub fn drain(&mut self) -> impl Iterator<Item = (chat::Id, S)> + '_ {
self.chats.drain()
}
pub fn clear(&mut self) {
self.chats.clear()
}
pub fn reserve(&mut self, additional: usize) {
self.chats.reserve(additional)
}
pub fn shrink_to_fit(&mut self) {
self.chats.shrink_to_fit()
}
#[must_use]
pub fn get_by_id(&self, id: chat::Id) -> Option<&S> {
self.chats.get(&id)
}
#[must_use]
pub fn get<C>(&self, context: &C) -> Option<&S>
where
C: Message,
{
self.get_by_id(context.chat().id)
}
#[must_use]
pub fn get_mut_by_id(&mut self, id: chat::Id) -> Option<&mut S> {
self.chats.get_mut(&id)
}
#[must_use]
pub fn get_mut<C>(&mut self, context: &C) -> Option<&mut S>
where
C: Message,
{
self.get_mut_by_id(context.chat().id)
}
#[must_use]
pub fn entry_by_id(&mut self, id: chat::Id) -> Entry<chat::Id, S> {
self.chats.entry(id)
}
#[must_use]
pub fn entry<C>(&mut self, context: &C) -> Entry<chat::Id, S>
where
C: Message,
{
self.entry_by_id(context.chat().id)
}
#[must_use]
pub fn has_by_id(&self, id: chat::Id) -> bool {
self.chats.contains_key(&id)
}
#[must_use]
pub fn has<C>(&self, context: &C) -> bool
where
C: Message,
{
self.has_by_id(context.chat().id)
}
pub fn insert_by_id(&mut self, id: chat::Id, value: S) -> Option<S> {
self.chats.insert(id, value)
}
pub fn insert<C>(&mut self, context: &C, value: S) -> Option<S>
where
C: Message,
{
self.insert_by_id(context.chat().id, value)
}
pub fn remove_by_id(&mut self, id: chat::Id) -> Option<S> {
self.chats.remove(&id)
}
pub fn remove<C>(&mut self, context: &C) -> Option<S>
where
C: Message,
{
self.remove_by_id(context.chat().id)
}
pub fn retain<P>(&mut self, mut predicate: P)
where
P: FnMut(chat::Id, &mut S) -> bool,
{
self.chats.retain(|&id, state| predicate(id, state))
}
}
impl<S> IntoIterator for Chats<S> {
type Item = (chat::Id, S);
type IntoIter = IntoIter<chat::Id, S>;
fn into_iter(self) -> Self::IntoIter {
self.chats.into_iter()
}
}
pub struct Iter<'a, S>(hash_map::Iter<'a, chat::Id, S>);
impl<'a, S> Iterator for Iter<'a, S> {
type Item = (chat::Id, &'a S);
fn next(&mut self) -> Option<Self::Item> {
self.0.next().map(|(&id, state)| (id, state))
}
}
impl<'a, S> IntoIterator for &'a Chats<S> {
type Item = (chat::Id, &'a S);
type IntoIter = Iter<'a, S>;
fn into_iter(self) -> Self::IntoIter {
Iter(self.chats.iter())
}
}
pub struct IterMut<'a, S>(hash_map::IterMut<'a, chat::Id, S>);
impl<'a, S> Iterator for IterMut<'a, S> {
type Item = (chat::Id, &'a mut S);
fn next(&mut self) -> Option<Self::Item> {
self.0.next().map(|(&id, state)| (id, state))
}
}
impl<'a, S> IntoIterator for &'a mut Chats<S> {
type Item = (chat::Id, &'a mut S);
type IntoIter = IterMut<'a, S>;
fn into_iter(self) -> Self::IntoIter {
IterMut(self.chats.iter_mut())
}
}
impl<S> Extend<(chat::Id, S)> for Chats<S> {
fn extend<I: IntoIterator<Item = (chat::Id, S)>>(&mut self, iterator: I) {
self.chats.extend(iterator)
}
}
impl<'a, S: Copy> Extend<(chat::Id, &'a S)> for Chats<S> {
fn extend<I: IntoIterator<Item = (chat::Id, &'a S)>>(
&mut self,
iterator: I,
) {
self.extend(iterator.into_iter().map(|(id, &state)| (id, state)))
}
}
impl<S> FromIterator<(chat::Id, S)> for Chats<S> {
fn from_iter<I: IntoIterator<Item = (chat::Id, S)>>(iter: I) -> Self {
Self {
chats: HashMap::from_iter(iter),
}
}
}
impl<S> Index<chat::Id> for Chats<S> {
type Output = S;
fn index(&self, id: chat::Id) -> &S {
self.chats.index(&id)
}
}
impl<S> Default for Chats<S> {
fn default() -> Self {
Self::new()
}
}