Skip to content

Commit

Permalink
Add const functions for negation / union of AsciiSet
Browse files Browse the repository at this point in the history
  • Loading branch information
joshka committed Sep 19, 2024
1 parent b9f44f6 commit 13374e8
Showing 1 changed file with 43 additions and 9 deletions.
52 changes: 43 additions & 9 deletions percent_encoding/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,26 +106,38 @@ impl AsciiSet {
mask[byte as usize / BITS_PER_CHUNK] &= !(1 << (byte as usize % BITS_PER_CHUNK));
AsciiSet { mask }
}

/// Return the union of two sets.
pub const fn union(&self, other: &Self) -> Self {
let mask = [
self.mask[0] | other.mask[0],
self.mask[1] | other.mask[1],
self.mask[2] | other.mask[2],
self.mask[3] | other.mask[3],
];
AsciiSet { mask }
}

/// Return the negation of the set.
pub const fn complement(&self) -> Self {
let mask = [!self.mask[0], !self.mask[1], !self.mask[2], !self.mask[3]];
AsciiSet { mask }
}
}

impl ops::Add for AsciiSet {
type Output = Self;

fn add(self, other: Self) -> Self {
let mut mask = self.mask.clone();
for i in 0..mask.len() {
mask[i] |= other.mask[i];
}
AsciiSet { mask }
self.union(&other)
}
}

impl ops::Not for AsciiSet {
type Output = Self;

fn not(self) -> Self {
let mask = self.mask.map(|chunk| !chunk);
AsciiSet { mask }
self.complement()
}
}

Expand Down Expand Up @@ -511,18 +523,40 @@ mod tests {
use super::*;

#[test]
fn add() {
fn add_op() {
let left = AsciiSet::EMPTY.add(b'A');
let right = AsciiSet::EMPTY.add(b'B');
let expected = AsciiSet::EMPTY.add(b'A').add(b'B');
assert_eq!(left + right, expected);
}

#[test]
fn not() {
fn not_op() {
let set = AsciiSet::EMPTY.add(b'A').add(b'B');
let not_set = !set;
assert!(!not_set.contains(b'A'));
assert!(not_set.contains(b'C'));
}

/// This test ensures that we can get the union of two sets as a constant value, which is
/// useful for defining sets in a modular way.
#[test]
fn union() {
const A: AsciiSet = AsciiSet::EMPTY.add(b'A');
const B: AsciiSet = AsciiSet::EMPTY.add(b'B');
const UNION: AsciiSet = A.union(&B);
const EXPECTED: AsciiSet = AsciiSet::EMPTY.add(b'A').add(b'B');
assert_eq!(UNION, EXPECTED);
}

/// This test ensures that we can get the complement of a set as a constant value, which is
/// useful for defining sets in a modular way.
#[test]
fn complement() {
const BOTH: AsciiSet = AsciiSet::EMPTY.add(b'A').add(b'B');
const COMPLEMENT: AsciiSet = BOTH.complement();
assert!(!COMPLEMENT.contains(b'A'));
assert!(!COMPLEMENT.contains(b'B'));
assert!(COMPLEMENT.contains(b'C'));
}
}

0 comments on commit 13374e8

Please sign in to comment.