use super::casing::CaseSensitivity;
use std::borrow::Cow;
use std::slice::{Iter, IterMut};
#[derive(Clone, Debug, Default)]
pub struct CommandParserConfig<'a> {
pub(crate) commands: Vec<CaseSensitivity>,
pub(crate) prefixes: Vec<Cow<'a, str>>,
}
impl<'a> CommandParserConfig<'a> {
pub const fn new() -> Self {
Self {
commands: Vec::new(),
prefixes: Vec::new(),
}
}
pub fn commands(&self) -> Commands<'_> {
Commands {
iter: self.commands.iter(),
}
}
pub fn commands_mut(&mut self) -> CommandsMut<'_> {
CommandsMut {
iter: self.commands.iter_mut(),
}
}
pub fn prefixes(&self) -> Prefixes<'_> {
Prefixes {
iter: self.prefixes.iter(),
}
}
pub fn prefixes_mut(&'a mut self) -> PrefixesMut<'a> {
PrefixesMut {
iter: self.prefixes.iter_mut(),
}
}
pub fn add_command(&mut self, name: impl Into<String>, case_sensitive: bool) -> bool {
self._add_command(name.into(), case_sensitive)
}
fn _add_command(&mut self, name: String, case_sensitive: bool) -> bool {
let command = if case_sensitive {
CaseSensitivity::Sensitive(name)
} else {
CaseSensitivity::Insensitive(name.into())
};
if self.commands.contains(&command) {
false
} else {
self.commands.push(command);
true
}
}
pub fn remove_command(&mut self, command: impl AsRef<str>) {
self.commands.retain(|c| c != command.as_ref());
}
pub fn add_prefix(&mut self, prefix: impl Into<Cow<'a, str>>) -> bool {
let prefix = prefix.into();
if self.prefixes.contains(&prefix) {
false
} else {
self.prefixes.push(prefix);
true
}
}
pub fn remove_prefix(&mut self, prefix: impl Into<Cow<'a, str>>) -> Option<Cow<'a, str>> {
let needle = prefix.into();
let pos = self.prefixes.iter().position(|e| *e == needle)?;
Some(self.prefixes.remove(pos))
}
}
pub struct Commands<'a> {
iter: Iter<'a, CaseSensitivity>,
}
impl<'a> Iterator for Commands<'a> {
type Item = (&'a str, bool);
fn next(&mut self) -> Option<Self::Item> {
self.iter
.next()
.map(|casing| (casing.as_ref(), casing.is_sensitive()))
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl<'a> ExactSizeIterator for Commands<'a> {}
pub struct CommandsMut<'a> {
iter: IterMut<'a, CaseSensitivity>,
}
impl<'a> Iterator for CommandsMut<'a> {
type Item = (&'a mut str, bool);
fn next(&mut self) -> Option<Self::Item> {
let casing = self.iter.next()?;
let is_sensitive = casing.is_sensitive();
Some((casing.as_mut(), is_sensitive))
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl<'a> ExactSizeIterator for CommandsMut<'a> {}
pub struct Prefixes<'a> {
iter: Iter<'a, Cow<'a, str>>,
}
impl<'a> Iterator for Prefixes<'a> {
type Item = &'a Cow<'a, str>;
fn next(&mut self) -> Option<Self::Item> {
self.iter.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl<'a> ExactSizeIterator for Prefixes<'a> {}
pub struct PrefixesMut<'a> {
iter: IterMut<'a, Cow<'a, str>>,
}
impl<'a> Iterator for PrefixesMut<'a> {
type Item = &'a mut Cow<'a, str>;
fn next(&mut self) -> Option<Self::Item> {
self.iter.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl<'a> ExactSizeIterator for PrefixesMut<'a> {}
#[cfg(test)]
mod tests {
use super::{CommandParserConfig, Commands, CommandsMut, Prefixes, PrefixesMut};
use static_assertions::assert_impl_all;
use std::fmt::Debug;
assert_impl_all!(CommandParserConfig<'_>: Clone, Debug, Default, Send, Sync);
assert_impl_all!(CommandsMut<'_>: ExactSizeIterator, Iterator, Send, Sync);
assert_impl_all!(Commands<'_>: ExactSizeIterator, Iterator, Send, Sync);
assert_impl_all!(PrefixesMut<'_>: ExactSizeIterator, Iterator, Send, Sync);
assert_impl_all!(Prefixes<'_>: ExactSizeIterator, Iterator, Send, Sync);
#[test]
fn test_getters() {
let mut config = CommandParserConfig::new();
assert!(config.commands().len() == 0);
assert!(config.commands_mut().len() == 0);
assert!(config.prefixes().len() == 0);
assert!(config.prefixes_mut().len() == 0);
}
}