mod defaults;
mod handler;
#[cfg(test)]
mod tests;
use std::collections::BTreeSet;
use super::auth::SaslQueue;
pub use {defaults::*, handler::*};
use crate::{
client::{nick::NickGen, ClientMsgSink, MakeHandler},
ircmsg::ClientMsg,
string::{Arg, Key, Line, Nick, User},
};
#[derive(Clone)]
pub struct Register<O> {
pub password: fn(&O) -> Option<Line<'static>>,
pub username: fn(&O) -> User<'static>,
pub user_p1: fn(&O) -> Arg<'static>,
pub user_p2: fn(&O) -> Arg<'static>,
pub realname: fn(&O) -> Line<'static>,
pub nicks: fn(&O) -> Box<dyn crate::client::nick::NickGen>,
pub caps: fn(&O) -> Box<dyn CapFn>,
pub auth: fn(&O) -> (SaslQueue, bool),
}
impl<O> Register<O> {
pub fn register_msgs(
&self,
opts: &O,
mut sink: impl ClientMsgSink<'static>,
) -> (Nick<'static>, Option<Box<dyn NickGen>>) {
use crate::names::cmd::{CAP, NICK, PASS, USER};
if let Some(pass) = (self.password)(opts) {
let pass = pass;
let mut msg = ClientMsg::new(PASS);
msg.args.edit().add(pass);
sink.send(msg);
}
let mut msg = ClientMsg::new(CAP);
let mut args = msg.args.edit();
args.add_literal("LS");
args.add_literal("302");
sink.send(msg);
msg = ClientMsg::new(USER);
let mut args = msg.args.edit();
args.add_word((self.username)(opts));
args.add_word((self.user_p1)(opts));
args.add_word((self.user_p2)(opts));
args.add((self.realname)(opts));
sink.send(msg);
msg = ClientMsg::new(NICK);
let nicks = (self.nicks)(opts);
let (nick, nickgen) = nicks.next_nick();
msg.args.edit().add_word(nick.clone());
sink.send(msg);
(nick, nickgen)
}
}
impl<O> Register<O> {
pub fn handler(&self, opts: &O, sink: impl ClientMsgSink<'static>) -> Handler {
let nicks = self.register_msgs(opts, sink);
let caps = (self.caps)(opts);
let (auths, mut needs_auth) = (self.auth)(opts);
needs_auth &= auths.is_empty();
Handler::new(nicks, caps, needs_auth, auths)
}
}
impl<'a, O> MakeHandler<&'a O> for &'a Register<O> {
type Value = Result<(), HandlerError>;
type Error = std::convert::Infallible;
type Receiver<Spec: super::channel::ChannelSpec> = Spec::Oneshot<Self::Value>;
fn make_handler(
self,
_: &crate::client::ClientState,
mut queue: super::queue::QueueEditGuard<'_>,
opts: &'a O,
) -> Result<Box<dyn crate::client::Handler<Value = Self::Value>>, Self::Error> {
Ok(Box::new(self.handler(opts, &mut queue)))
}
fn make_channel<Spec: super::channel::ChannelSpec>(
spec: &Spec,
) -> (Box<dyn super::channel::Sender<Value = Self::Value> + Send>, Self::Receiver<Spec>) {
spec.new_oneshot()
}
}
pub trait CapFn: Send {
fn require(self: Box<Self>, caps: &BTreeSet<Key<'_>>) -> BTreeSet<Key<'static>>;
}
impl<F> CapFn for F
where
F: FnOnce(&BTreeSet<Key<'_>>) -> BTreeSet<Key<'static>> + Send,
{
fn require(self: Box<Self>, caps: &BTreeSet<Key<'_>>) -> BTreeSet<Key<'static>> {
(*self)(caps)
}
}