mod suffix;
#[cfg(test)]
mod tests;
pub use suffix::*;
use crate::string::{Builder, Nick};
use std::{error::Error, iter::FusedIterator};
type NickBuilder = Builder<Nick<'static>>;
#[derive(Clone, PartialEq, Eq, Hash, Debug, Default)]
#[cfg_attr(feature = "serde", derive(serde_derive::Serialize, serde_derive::Deserialize))]
pub struct Nicks<N> {
pub nicks: Vec<Nick<'static>>,
#[cfg_attr(feature = "serde", serde(default))]
pub skip_first: bool,
pub gen: std::sync::Arc<N>,
}
#[derive(Clone, Copy, Default, Debug)]
pub struct EndOfNicks;
impl std::fmt::Display for EndOfNicks {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "no more nicknames")
}
}
impl Error for EndOfNicks {}
pub trait NickGen: 'static + Send {
fn next_nick(self: Box<Self>) -> (Nick<'static>, Option<Box<dyn NickGen>>);
fn peek(&self) -> Nick<'static>;
fn handle_invalid(self: Box<Self>, nick: &Nick<'static>) -> Option<Box<dyn NickGen>>;
}
impl<G: NickGen + ?Sized> NickGen for Box<G> {
fn next_nick(self: Box<Self>) -> (Nick<'static>, Option<Box<dyn NickGen>>) {
G::next_nick(*self)
}
fn peek(&self) -> Nick<'static> {
G::peek(self)
}
fn handle_invalid(self: Box<Self>, nick: &Nick<'static>) -> Option<Box<dyn NickGen>> {
G::handle_invalid(*self, nick)
}
}
impl NickGen for Nick<'static> {
fn next_nick(self: Box<Self>) -> (Nick<'static>, Option<Box<dyn NickGen>>) {
(*self, None)
}
fn peek(&self) -> Nick<'static> {
self.clone()
}
fn handle_invalid(self: Box<Self>, nick: &Nick<'static>) -> Option<Box<dyn NickGen>> {
let eq = *nick == *self;
eq.then_some(self)
}
}
#[derive(Clone, Debug)]
pub struct FromIter<I> {
nick: Nick<'static>,
iter: I,
}
pub fn from_iter<I: IntoIterator<Item = Nick<'static>>>(iter: I) -> Option<FromIter<I::IntoIter>> {
let mut iter = iter.into_iter();
let nick = iter.next()?;
Some(FromIter { nick, iter })
}
pub fn from_iter_or<It: FusedIterator<Item = Nick<'static>>, I: IntoIterator<IntoIter = It>>(
default: Nick<'static>,
iter: I,
) -> FromIter<It> {
let mut iter = iter.into_iter();
let nick = iter.next().unwrap_or(default);
FromIter { nick, iter }
}
impl<I: Iterator<Item = Nick<'static>> + 'static + Send> NickGen for FromIter<I> {
fn next_nick(mut self: Box<Self>) -> (Nick<'static>, Option<Box<dyn NickGen>>) {
if let Some(mut next) = self.iter.next() {
std::mem::swap(&mut next, &mut self.nick);
(next, Some(self))
} else {
(self.nick, None)
}
}
fn peek(&self) -> Nick<'static> {
self.nick.clone()
}
fn handle_invalid(self: Box<Self>, _nick: &Nick<'static>) -> Option<Box<dyn NickGen>> {
let is_finite = self.iter.size_hint().1.is_some();
is_finite.then_some(self)
}
}
pub trait NickGenExt: NickGen + Sized {
fn chain(self: Box<Self>, ng: Box<dyn NickGen>) -> Box<Chain> {
Box::new(Chain { a: Some(self), b: Some(ng) })
}
fn chain_using(self: Box<Self>, nt: &impl NickTransformer) -> Box<Chain> {
let b = nt.transform(self.peek());
self.chain(b)
}
}
impl<T: NickGen> NickGenExt for T {}
pub struct Chain {
pub(self) a: Option<Box<dyn NickGen>>,
pub(self) b: Option<Box<dyn NickGen>>,
}
impl NickGen for Chain {
fn next_nick(mut self: Box<Self>) -> (Nick<'static>, Option<Box<dyn NickGen>>) {
if let Some(gen) = self.a.take() {
let (nick, next) = gen.next_nick();
self.a = next;
(nick, Some(self))
} else {
let (nick, next) = self.b.unwrap().next_nick();
(nick, next)
}
}
fn peek(&self) -> Nick<'static> {
let next = self.a.as_deref().unwrap_or(self.b.as_deref().unwrap());
next.peek()
}
fn handle_invalid(mut self: Box<Self>, nick: &Nick<'static>) -> Option<Box<dyn NickGen>> {
let Some(a) = self.a.take().and_then(|a| a.handle_invalid(nick)) else {
return self.b.unwrap().handle_invalid(nick);
};
let Some(b) = self.b.take().unwrap().handle_invalid(nick) else {
return Some(a);
};
self.a = Some(a);
self.b = Some(b);
Some(self)
}
}
pub trait NickTransformer {
fn transform(&self, nick: Nick<'static>) -> Box<dyn NickGen>;
}