#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum IrcCaseMapping {
Ascii,
Rfc1459,
Rfc1459Strict,
}
impl IrcCaseMapping {
#[must_use]
pub const fn is_equivalent(&self, first: &[u8], second: &[u8]) -> bool {
if first.len() != second.len() {return false;}
let mut index = 0;
while index < first.len() {
if first[index].is_ascii_alphabetic() && second[index].is_ascii_alphabetic() {
if first[index].to_ascii_uppercase() != second[index].to_ascii_uppercase() {return false;}
} else if first[index] != second[index] {
match self {
Self::Ascii => return false,
Self::Rfc1459 => if !IrcCaseMapping::rfc1459_is_equivalent(first[index], second[index], false) {
return false;
},
Self::Rfc1459Strict => if !IrcCaseMapping::rfc1459_is_equivalent(first[index], second[index], true) {
return false;
},
}
}
index += 1;
}
true
}
const fn rfc1459_is_equivalent(first: u8, second: u8, strict: bool) -> bool {
match (first, second) {
(b'{', b'[') | (b'[', b'{') | (b'}', b']') | (b']', b'}') | (b'|', b'\\') | (b'\\', b'|') => true,
(b'^', b'~') | (b'~', b'^') if !strict => true,
_ => false,
}
}
}
#[cfg(test)]
mod const_tests {
use crate::casemapping::IrcCaseMapping;
#[test]
const fn is_equal_ascii() {
let first = b"bob";
let second = b"BOB";
let casemapping = IrcCaseMapping::Ascii;
assert!(casemapping.is_equivalent(first, second));
}
#[test]
const fn is_equal_rfc1459() {
let first = b"^ob";
let second = b"~oB";
let casemapping = IrcCaseMapping::Rfc1459;
assert!(casemapping.is_equivalent(first, second));
}
#[test]
const fn is_equal_rfc1459_strict() {
let first = b"{ob";
let second = b"[oB";
let casemapping = IrcCaseMapping::Rfc1459Strict;
assert!(casemapping.is_equivalent(first, second));
}
#[test]
const fn bad_len() {
let first = b"bob";
let second = b"BOBBY";
let casemapping = IrcCaseMapping::Ascii;
assert!(!casemapping.is_equivalent(first, second));
}
#[test]
const fn not_equal_ascii() {
let first = b"bob";
let second = b"B0B";
let casemapping = IrcCaseMapping::Ascii;
assert!(!casemapping.is_equivalent(first, second));
}
#[test]
const fn not_equal_rfc1459() {
let first = b"^ob";
let second = b"#oB";
let casemapping = IrcCaseMapping::Rfc1459;
assert!(!casemapping.is_equivalent(first, second));
}
#[test]
const fn not_equal_rfc1459_strict() {
let first = b"^ob";
let second = b"~oB";
let casemapping = IrcCaseMapping::Rfc1459Strict;
assert!(!casemapping.is_equivalent(first, second));
}
}