Skip to content

Commit 13374e8

Browse files
committed
Add const functions for negation / union of AsciiSet
1 parent b9f44f6 commit 13374e8

File tree

1 file changed

+43
-9
lines changed

1 file changed

+43
-9
lines changed

percent_encoding/src/lib.rs

+43-9
Original file line numberDiff line numberDiff line change
@@ -106,26 +106,38 @@ impl AsciiSet {
106106
mask[byte as usize / BITS_PER_CHUNK] &= !(1 << (byte as usize % BITS_PER_CHUNK));
107107
AsciiSet { mask }
108108
}
109+
110+
/// Return the union of two sets.
111+
pub const fn union(&self, other: &Self) -> Self {
112+
let mask = [
113+
self.mask[0] | other.mask[0],
114+
self.mask[1] | other.mask[1],
115+
self.mask[2] | other.mask[2],
116+
self.mask[3] | other.mask[3],
117+
];
118+
AsciiSet { mask }
119+
}
120+
121+
/// Return the negation of the set.
122+
pub const fn complement(&self) -> Self {
123+
let mask = [!self.mask[0], !self.mask[1], !self.mask[2], !self.mask[3]];
124+
AsciiSet { mask }
125+
}
109126
}
110127

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

114131
fn add(self, other: Self) -> Self {
115-
let mut mask = self.mask.clone();
116-
for i in 0..mask.len() {
117-
mask[i] |= other.mask[i];
118-
}
119-
AsciiSet { mask }
132+
self.union(&other)
120133
}
121134
}
122135

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

126139
fn not(self) -> Self {
127-
let mask = self.mask.map(|chunk| !chunk);
128-
AsciiSet { mask }
140+
self.complement()
129141
}
130142
}
131143

@@ -511,18 +523,40 @@ mod tests {
511523
use super::*;
512524

513525
#[test]
514-
fn add() {
526+
fn add_op() {
515527
let left = AsciiSet::EMPTY.add(b'A');
516528
let right = AsciiSet::EMPTY.add(b'B');
517529
let expected = AsciiSet::EMPTY.add(b'A').add(b'B');
518530
assert_eq!(left + right, expected);
519531
}
520532

521533
#[test]
522-
fn not() {
534+
fn not_op() {
523535
let set = AsciiSet::EMPTY.add(b'A').add(b'B');
524536
let not_set = !set;
525537
assert!(!not_set.contains(b'A'));
526538
assert!(not_set.contains(b'C'));
527539
}
540+
541+
/// This test ensures that we can get the union of two sets as a constant value, which is
542+
/// useful for defining sets in a modular way.
543+
#[test]
544+
fn union() {
545+
const A: AsciiSet = AsciiSet::EMPTY.add(b'A');
546+
const B: AsciiSet = AsciiSet::EMPTY.add(b'B');
547+
const UNION: AsciiSet = A.union(&B);
548+
const EXPECTED: AsciiSet = AsciiSet::EMPTY.add(b'A').add(b'B');
549+
assert_eq!(UNION, EXPECTED);
550+
}
551+
552+
/// This test ensures that we can get the complement of a set as a constant value, which is
553+
/// useful for defining sets in a modular way.
554+
#[test]
555+
fn complement() {
556+
const BOTH: AsciiSet = AsciiSet::EMPTY.add(b'A').add(b'B');
557+
const COMPLEMENT: AsciiSet = BOTH.complement();
558+
assert!(!COMPLEMENT.contains(b'A'));
559+
assert!(!COMPLEMENT.contains(b'B'));
560+
assert!(COMPLEMENT.contains(b'C'));
561+
}
528562
}

0 commit comments

Comments
 (0)