Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify mode flags #116

Merged
merged 2 commits into from
May 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions sable_ircd/src/command/handlers/mode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ async fn handle_user_mode(
for c in mode_str.chars() {
if let Ok(d) = Direction::try_from(c) {
dir = d;
} else if let Some(flag) = UserModeSet::flag_for(c) {
} else if let Some(flag) = UserModeFlag::from_mode_char(c) {
if server.policy().can_set_umode(&source, flag).is_err() {
continue;
}
Expand Down Expand Up @@ -125,7 +125,7 @@ async fn handle_channel_mode(
for c in mode_str.chars() {
if let Ok(d) = Direction::try_from(c) {
dir = d;
} else if let Some(flag) = ChannelModeSet::flag_for(c) {
} else if let Some(flag) = ChannelModeFlag::from_mode_char(c) {
server.policy().can_change_mode(source, &chan, flag)?;
match dir {
Direction::Add => {
Expand All @@ -136,7 +136,7 @@ async fn handle_channel_mode(
}
_ => {}
}
} else if let Some(flag) = MembershipFlagSet::flag_for(c) {
} else if let Some(flag) = MembershipFlagFlag::from_mode_char(c) {
let target = args.next::<wrapper::User>()?;
let membership = target
.is_in_channel(chan.id())
Expand Down Expand Up @@ -166,7 +166,7 @@ async fn handle_channel_mode(
removed: perm_removed,
};
cmd.new_event_with_response(membership.id(), detail).await;
} else if let Some(list_type) = ListModeType::from_char(c) {
} else if let Some(list_type) = ListModeType::from_mode_char(c) {
let list = chan.list(list_type);

if dir == Direction::Query || args.is_empty() {
Expand Down Expand Up @@ -202,7 +202,7 @@ async fn handle_channel_mode(
}
}
}
} else if let Some(_key_type) = KeyModeType::from_char(c) {
} else if let Some(_key_type) = KeyModeType::from_mode_char(c) {
match dir {
// Can't query keys
Direction::Query => (),
Expand Down
4 changes: 2 additions & 2 deletions sable_ircd/src/messages/send_history.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ impl SendHistoryItem for update::ChannelTopicChange {

impl SendHistoryItem for update::ListModeAdded {
fn send_to(&self, conn: impl MessageSink, from_entry: &HistoryLogEntry) -> HandleResult {
let text = format!("+{} {}", self.list_type.mode_letter(), self.pattern);
let text = format!("+{} {}", self.list_type.mode_char(), self.pattern);
let message =
message::Mode::new(&self.set_by, &self.channel, &text).with_tags_from(from_entry);
conn.send(message);
Expand All @@ -168,7 +168,7 @@ impl SendHistoryItem for update::ListModeAdded {

impl SendHistoryItem for update::ListModeRemoved {
fn send_to(&self, conn: impl MessageSink, from_entry: &HistoryLogEntry) -> HandleResult {
let text = format!("-{} {}", self.list_type.mode_letter(), self.pattern);
let text = format!("-{} {}", self.list_type.mode_char(), self.pattern);
let message =
message::Mode::new(&self.removed_by, &self.channel, &text).with_tags_from(from_entry);
conn.send(message);
Expand Down
32 changes: 22 additions & 10 deletions sable_ircd/src/server/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,12 +158,15 @@ impl ClientServer {
#[tracing::instrument]
fn build_myinfo() -> MyInfo {
MyInfo {
user_modes: UserModeSet::all().map(|m| m.1).iter().collect(),
chan_modes: ChannelModeSet::all().map(|m| m.1).iter().collect(),
user_modes: UserModeSet::all().map(|m| m.mode_char()).iter().collect(),
chan_modes: ChannelModeSet::all()
.map(|m| m.mode_char())
.iter()
.collect(),
chan_modes_with_a_parameter: ListModeType::iter()
.map(|t| t.mode_letter())
.chain(KeyModeType::iter().map(|t| t.mode_letter()))
.chain(MembershipFlagSet::all().map(|m| m.1).into_iter())
.map(|t| t.mode_char())
.chain(KeyModeType::iter().map(|t| t.mode_char()))
.chain(MembershipFlagSet::all().map(|m| m.mode_char()).into_iter())
.collect(),
}
}
Expand Down Expand Up @@ -195,10 +198,13 @@ impl ClientServer {
Username::LENGTH.try_into().unwrap(),
));

let list_modes: String = ListModeType::iter().map(|t| t.mode_letter()).collect();
let key_modes: String = KeyModeType::iter().map(|t| t.mode_letter()).collect();
let list_modes: String = ListModeType::iter().map(|t| t.mode_char()).collect();
let key_modes: String = KeyModeType::iter().map(|t| t.mode_char()).collect();
let param_modes = "";
let simple_modes: String = ChannelModeSet::all().map(|m| m.1).iter().collect();
let simple_modes: String = ChannelModeSet::all()
.map(|m| m.mode_char())
.iter()
.collect();
let chanmodes = format!(
"{},{},{},{}",
list_modes, key_modes, param_modes, simple_modes
Expand All @@ -210,8 +216,14 @@ impl ClientServer {
// 'msgid' not supported yet
ret.add(ISupportEntry::string("MSGREFTYPES", "timestamp"));

let prefix_modes: String = MembershipFlagSet::all().map(|m| m.1).iter().collect();
let prefix_chars: String = MembershipFlagSet::all().map(|m| m.2).iter().collect();
let prefix_modes: String = MembershipFlagSet::all()
.map(|m| m.mode_char())
.iter()
.collect();
let prefix_chars: String = MembershipFlagSet::all()
.map(|m| m.prefix_char())
.iter()
.collect();

let prefix = format!("({}){}", prefix_modes, prefix_chars);
ret.add(ISupportEntry::string("PREFIX", &prefix));
Expand Down
140 changes: 73 additions & 67 deletions sable_macros/src/modeflags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,9 @@ use syn::{

struct ModeDef {
name: Ident,
_paren: token::Paren,
flag: LitInt,
_comma: Token![,],
modechars: Punctuated<LitChar, Token![,]>,
modechar: LitChar,
prefixchar: Option<LitChar>,
}

struct ModeSet {
Expand All @@ -24,12 +23,20 @@ struct ModeSet {
impl Parse for ModeDef {
fn parse(input: ParseStream) -> Result<Self> {
let content;
let name = input.parse()?;
let _: token::Paren = parenthesized!(content in input);
let flag = content.parse()?;
content.parse::<Token![,]>()?;
let modechar = content.parse()?;
let prefixchar = match content.parse::<Token![,]>() {
Ok(_) => Some(content.parse()?),
Err(_) => None,
};
Ok(Self {
name: input.parse()?,
_paren: parenthesized!(content in input),
flag: content.parse()?,
_comma: content.parse()?,
modechars: content.parse_terminated(LitChar::parse)?,
name,
flag,
modechar,
prefixchar,
})
}
}
Expand All @@ -55,18 +62,14 @@ pub fn mode_flags(input: TokenStream) -> TokenStream {
let mut consts = Vec::new();
let mut const_names = Vec::new();
let mut mode_chars = Vec::new();
let mut prefix_chars = Vec::new();
let mut pairs = Vec::new();

let mut mode_char_types = proc_macro2::TokenStream::new();
let num_chartypes = modes.items[0].modechars.len();
for _c in 0..num_chartypes {
mode_char_types.extend(quote!(char,));
}

for item in modes.items {
let name = item.name;
let flag = item.flag;
let modechars = item.modechars;
let modechar = item.modechar;
let prefixchar = item.prefixchar;

consts.push(quote!(
#name = #flag
Expand All @@ -75,13 +78,25 @@ pub fn mode_flags(input: TokenStream) -> TokenStream {
#name
));
mode_chars.push(quote!(
#modechars
#modechar
));
if let Some(prefixchar) = prefixchar {
prefix_chars.push(quote!(
#prefixchar
));
}
pairs.push(quote!(
(#name_one::#flag, #modechars)
(#name_one::#flag, #modechar)
));
}

assert!(
prefix_chars.is_empty() || prefix_chars.len() == mode_chars.len(),
"Got {} prefix chars, but there are {} mode chars",
prefix_chars.len(),
mode_chars.len(),
);

let num_items = consts.len();

let mut output = quote!(
Expand All @@ -93,9 +108,23 @@ pub fn mode_flags(input: TokenStream) -> TokenStream {

impl #name_one
{
pub fn to_char(self) -> char
pub fn mode_char(self) -> char
{
#name_set::char_for(self)
match self {
#(
Self::#const_names => #mode_chars,
)*
}
}

pub fn from_mode_char(modechar: char) -> Option<#name_one>
{
match modechar {
#(
#mode_chars => Some(Self::#const_names),
)*
_ => None,
}
}
}

Expand All @@ -107,7 +136,7 @@ pub fn mode_flags(input: TokenStream) -> TokenStream {

impl #name_set
{
const ALL: [(#name_one, #mode_char_types); #num_items] = [ #( ( #name_one::#const_names, #mode_chars ) ),* ];
const ALL: [#name_one; #num_items] = [ #( #name_one::#const_names),* ];

pub fn is_set(&self, flag: #name_one) -> bool
{
Expand All @@ -124,35 +153,17 @@ pub fn mode_flags(input: TokenStream) -> TokenStream {
let mut s = String::new();
for v in Self::ALL
{
if (self.is_set(v.0))
if (self.is_set(v))
{
s.push(v.1);
s.push(v.mode_char());
}
}
return s;
}

pub fn new() -> Self { Self(0) }

pub fn all() -> [(#name_one, #mode_char_types); #num_items] { Self::ALL }

pub fn char_for(flag: #name_one) -> char
{
for v in Self::ALL
{
if v.0 == flag { return v.1; }
}
panic!("Invalid flag value?");
}

pub fn flag_for(modechar: char) -> Option<#name_one>
{
for v in Self::ALL
{
if v.1 == modechar { return Some(v.0); }
}
None
}
pub fn all() -> [#name_one; #num_items] { Self::ALL }
}

impl Default for #name_set
Expand Down Expand Up @@ -211,13 +222,27 @@ pub fn mode_flags(input: TokenStream) -> TokenStream {
}
);

if num_chartypes > 1 {
if !prefix_chars.is_empty() {
output.extend(quote!(
impl #name_one
{
pub fn to_prefix(self) -> char
pub fn prefix_char(self) -> char
{
match self {
#(
Self::#const_names => #prefix_chars,
)*
}
}

pub fn from_prefix_char(modechar: char) -> Option<#name_one>
{
#name_set::prefix_for(self)
match modechar {
#(
#prefix_chars => Some(Self::#const_names),
)*
_ => None,
}
}
}

Expand All @@ -228,9 +253,9 @@ pub fn mode_flags(input: TokenStream) -> TokenStream {
let mut s = String::new();
for v in Self::ALL
{
if (self.is_set(v.0))
if (self.is_set(v))
{
s.push(v.2);
s.push(v.prefix_char());
}
}
return s;
Expand All @@ -242,32 +267,13 @@ pub fn mode_flags(input: TokenStream) -> TokenStream {
{
for v in Self::ALL
{
if (self.is_set(v.0))
if (self.is_set(v))
{
return Some(v.2)
return Some(v.prefix_char())
}
}
return None;
}

pub fn prefix_for(flag: #name_one) -> char
{
for v in Self::ALL
{
if v.0 == flag { return v.2; }
}
panic!("Invalid flag value?");
}

pub fn flag_for_prefix(modechar: char) -> Option<#name_one>
{
for v in Self::ALL
{
if v.2 == modechar { return Some(v.0); }
}
None
}

}
));
}
Expand Down
4 changes: 2 additions & 2 deletions sable_network/src/modes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,14 @@ macro_rules! define_mode_type {

impl $typename
{
pub fn mode_letter(&self) -> char
pub fn mode_char(&self) -> char
{
match self {
$( Self:: $var => $val ),*
}
}

pub fn from_char(c: char) -> Option<Self>
pub fn from_mode_char(c: char) -> Option<Self>
{
match c {
$( $val => Some(Self::$var) ),+,
Expand Down
2 changes: 1 addition & 1 deletion sable_network/src/network/wrapper/channel_mode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ impl ChannelMode<'_> {
pub fn format(&self) -> String {
let mut ret = format!("+{}", self.data.modes.to_chars());
if self.data.key.is_some() {
ret.push(KeyModeType::Key.mode_letter());
ret.push(KeyModeType::Key.mode_char());
}
ret
}
Expand Down
Loading
Loading