2021-11-05 22:32:43 +00:00
|
|
|
|
use super::pattern::Searcher;
|
|
|
|
|
use super::*;
|
|
|
|
|
|
2022-03-24 10:53:25 +00:00
|
|
|
|
use alloc::vec::Vec;
|
|
|
|
|
use core::fmt::Debug;
|
2021-11-05 22:32:43 +00:00
|
|
|
|
|
|
|
|
|
macro_rules! bstr {
|
|
|
|
|
($str:literal) => {
|
|
|
|
|
WStr::from_units($str)
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
macro_rules! wstr {
|
|
|
|
|
($($char:literal)*) => {
|
|
|
|
|
WStr::from_units(&[$($char as u16),*])
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn roundtrip() {
|
|
|
|
|
fn test<'a>(units: impl Into<Units<&'a [u8], &'a [u16]>>) {
|
|
|
|
|
let units = units.into();
|
|
|
|
|
let s = WStr::from_units(units);
|
|
|
|
|
let conv = s.units();
|
|
|
|
|
let eq = match (units, conv) {
|
|
|
|
|
(Units::Bytes(a), Units::Bytes(b)) => a == b,
|
|
|
|
|
(Units::Wide(a), Units::Wide(b)) => a == b,
|
|
|
|
|
_ => false,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
assert!(eq, "expected {:?}, got {:?}", units, conv);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
test(b"");
|
|
|
|
|
test(<&[u16]>::default());
|
|
|
|
|
test(b"Hello!");
|
|
|
|
|
test(&[
|
|
|
|
|
'H' as u16, 'e' as u16, 'l' as u16, 'l' as u16, 'o' as u16, '!' as u16,
|
|
|
|
|
]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
#[rustfmt::skip]
|
|
|
|
|
#[allow(clippy::eq_op)]
|
|
|
|
|
fn eq() {
|
|
|
|
|
let a1 = bstr!(b"hello");
|
|
|
|
|
let b1 = bstr!(b"world");
|
|
|
|
|
let a2 = wstr!('h''e''l''l''o');
|
|
|
|
|
let b2 = wstr!('w''o''r''l''d');
|
|
|
|
|
|
|
|
|
|
assert_eq!(a1, a1); assert_eq!(a2, a1); assert_ne!(b1, a1); assert_ne!(b2, a1);
|
|
|
|
|
assert_eq!(a1, a2); assert_eq!(a2, a2); assert_ne!(b1, a2); assert_ne!(b2, a2);
|
|
|
|
|
assert_ne!(a1, b1); assert_ne!(a2, b1); assert_eq!(b1, b1); assert_eq!(b2, b1);
|
|
|
|
|
assert_ne!(a1, b2); assert_ne!(a2, b2); assert_eq!(b1, b2); assert_eq!(b2, b2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
#[rustfmt::skip]
|
|
|
|
|
#[allow(clippy::eq_op)]
|
|
|
|
|
fn cmp() {
|
|
|
|
|
let a1 = bstr!(b"hello");
|
|
|
|
|
let b1 = bstr!(b"world");
|
|
|
|
|
let a2 = wstr!('h''e''l''l''o');
|
|
|
|
|
let b2 = wstr!('w''o''r''l''d');
|
|
|
|
|
|
|
|
|
|
assert!(a1 == a1); assert!(a2 == a1); assert!(b1 > a1); assert!(b2 > a1);
|
|
|
|
|
assert!(a1 == a2); assert!(a2 == a2); assert!(b1 > a2); assert!(b2 > a2);
|
|
|
|
|
assert!(a1 < b1); assert!(a2 < b1); assert!(b1 == b1); assert!(b2 == b1);
|
|
|
|
|
assert!(a1 < b2); assert!(a2 < b2); assert!(b1 == b2); assert!(b2 == b2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn fmt() {
|
|
|
|
|
let a = bstr!(b"Hello world!");
|
|
|
|
|
let b = wstr!('H''e''l''l''o'' ''w''o''r''l''d''!');
|
|
|
|
|
let c = bstr!(b"\t\n\x03");
|
|
|
|
|
let d = wstr!(0x202d 0x202e);
|
|
|
|
|
|
|
|
|
|
assert_eq!(format!("{}", a), "Hello world!");
|
|
|
|
|
assert_eq!(format!("{}", b), "Hello world!");
|
|
|
|
|
assert_eq!(format!("{}", c), "\t\n\x03");
|
|
|
|
|
assert_eq!(format!("{}", d), "\u{202d}\u{202e}");
|
|
|
|
|
|
|
|
|
|
assert_eq!(format!("{:?}", a), "\"Hello world!\"");
|
|
|
|
|
assert_eq!(format!("{:?}", b), "\"Hello world!\"");
|
|
|
|
|
assert_eq!(format!("{:?}", c), "\"\\t\\n\\u{3}\"");
|
|
|
|
|
assert_eq!(format!("{:?}", d), "\"\\u{202d}\\u{202e}\"");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn buf_concat_bytes() {
|
|
|
|
|
let mut s = WString::new();
|
|
|
|
|
assert_eq!(s, bstr!(b""));
|
|
|
|
|
s.push_byte(b'a');
|
|
|
|
|
assert_eq!(s, bstr!(b"a"));
|
|
|
|
|
s.push(b'b'.into());
|
|
|
|
|
assert_eq!(s, bstr!(b"ab"));
|
|
|
|
|
s.push_utf8("cd");
|
|
|
|
|
assert_eq!(s, bstr!(b"abcd"));
|
|
|
|
|
s.push_str(bstr!(b"ef"));
|
|
|
|
|
assert_eq!(s, bstr!(b"abcdef"));
|
|
|
|
|
s.push_char('g');
|
|
|
|
|
assert_eq!(s, bstr!(b"abcdefg"));
|
|
|
|
|
assert!(matches!(s.units(), Units::Bytes(_)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn buf_concat_wide() {
|
|
|
|
|
let mut s = WString::new();
|
|
|
|
|
assert_eq!(s, bstr!(b""));
|
|
|
|
|
s.push_byte(b'a');
|
|
|
|
|
assert_eq!(s, bstr!(b"a"));
|
|
|
|
|
s.push('€' as u16);
|
|
|
|
|
assert_eq!(s, wstr!('a''€'));
|
|
|
|
|
s.push_utf8("😀");
|
|
|
|
|
assert_eq!(s, wstr!('a''€' 0xd83d 0xde00));
|
|
|
|
|
s.push_str(bstr!(b"!"));
|
|
|
|
|
assert_eq!(s, wstr!('a''€' 0xd83d 0xde00 '!'));
|
|
|
|
|
s.push_char('😀');
|
|
|
|
|
assert_eq!(s, wstr!('a''€' 0xd83d 0xde00 '!' 0xd83d 0xde00));
|
|
|
|
|
assert!(matches!(s.units(), Units::Wide(_)));
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-29 23:14:28 +00:00
|
|
|
|
#[test]
|
|
|
|
|
fn offset_in() {
|
|
|
|
|
let bstr = bstr!(b"abcdefghijk");
|
|
|
|
|
assert_eq!(bstr.offset_in(bstr), Some(0));
|
|
|
|
|
assert_eq!(bstr[3..6].offset_in(bstr), Some(3));
|
|
|
|
|
assert_eq!(bstr.offset_in(&bstr[3..6]), None);
|
|
|
|
|
assert_eq!(bstr[..3].offset_in(&bstr[6..]), None);
|
|
|
|
|
assert_eq!(bstr[6..].offset_in(&bstr[..3]), None);
|
|
|
|
|
|
|
|
|
|
let wstr = wstr!('a''b''c''d''e''f''g''h''i''j''k');
|
|
|
|
|
assert_eq!(wstr.offset_in(wstr), Some(0));
|
|
|
|
|
assert_eq!(wstr[3..6].offset_in(wstr), Some(3));
|
|
|
|
|
assert_eq!(wstr.offset_in(&wstr[3..6]), None);
|
|
|
|
|
assert_eq!(wstr[..3].offset_in(&wstr[6..]), None);
|
|
|
|
|
assert_eq!(wstr[6..].offset_in(&wstr[..3]), None);
|
|
|
|
|
|
|
|
|
|
assert_eq!(bstr.offset_in(wstr), None);
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-05 22:32:43 +00:00
|
|
|
|
fn test_pattern<'a, P: Pattern<'a> + Clone + Debug>(
|
|
|
|
|
haystack: &'a WStr,
|
|
|
|
|
pattern: P,
|
|
|
|
|
forwards: &[(usize, usize)],
|
|
|
|
|
backwards: Option<&[(usize, usize)]>,
|
|
|
|
|
) {
|
|
|
|
|
let mut searcher = pattern.clone().into_searcher(haystack);
|
2022-03-24 10:53:25 +00:00
|
|
|
|
let mut actual: Vec<_> = core::iter::from_fn(|| searcher.next_match()).collect();
|
2021-11-05 22:32:43 +00:00
|
|
|
|
assert_eq!(
|
|
|
|
|
actual, forwards,
|
|
|
|
|
"incorrect forwards matching: haystack={:?}; pattern={:?}",
|
|
|
|
|
haystack, pattern
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
searcher = pattern.clone().into_searcher(haystack);
|
2022-03-24 10:53:25 +00:00
|
|
|
|
actual = core::iter::from_fn(|| searcher.next_match_back()).collect();
|
2021-11-05 22:32:43 +00:00
|
|
|
|
actual.reverse();
|
|
|
|
|
assert_eq!(
|
|
|
|
|
actual,
|
|
|
|
|
backwards.unwrap_or(forwards),
|
|
|
|
|
"incorrect backwards matching: haystack={:?}; pattern={:?}",
|
|
|
|
|
haystack,
|
|
|
|
|
pattern
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn char_patterns() {
|
|
|
|
|
test_pattern(bstr!(b"a"), b'a', &[(0, 1)], None);
|
|
|
|
|
|
|
|
|
|
let bytes = bstr!(b"abaabbcab");
|
|
|
|
|
test_pattern(bytes, b'b', &[(1, 2), (4, 5), (5, 6), (8, 9)], None);
|
|
|
|
|
test_pattern(bytes, b'd', &[], None);
|
|
|
|
|
test_pattern(bytes, 'c' as u16, &[(6, 7)], None);
|
|
|
|
|
test_pattern(bytes, '↓' as u16, &[], None);
|
|
|
|
|
|
|
|
|
|
let wide = wstr!('↓''a''a''↓''a');
|
|
|
|
|
test_pattern(wide, b'c', &[], None);
|
|
|
|
|
test_pattern(wide, '↓' as u16, &[(0, 1), (3, 4)], None);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn multi_char_patterns() {
|
|
|
|
|
let bytes = bstr!(b"abcdabcd");
|
|
|
|
|
let matches = &[(0, 1), (2, 3), (4, 5), (6, 7)];
|
|
|
|
|
test_pattern(bytes, &[b'a', b'c'][..], matches, None);
|
|
|
|
|
test_pattern(bytes, &['a' as u16, 'c' as u16][..], matches, None);
|
|
|
|
|
|
|
|
|
|
let wide = wstr!('↓''a''b''↓''b''c');
|
|
|
|
|
test_pattern(wide, &[b'a', b'b'][..], &[(1, 2), (2, 3), (4, 5)], None);
|
|
|
|
|
test_pattern(wide, &['↓' as u16, '−' as u16][..], &[(0, 1), (3, 4)], None);
|
|
|
|
|
|
|
|
|
|
// Don't test `FnMut(u16) -> bool` because it isn't `Debug`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn str_patterns() {
|
|
|
|
|
test_pattern(bstr!(b"aa"), bstr!(b""), &[(0, 0), (1, 1), (2, 2)], None);
|
|
|
|
|
test_pattern(bstr!(b"abcde"), bstr!(b"abcde"), &[(0, 5)], None);
|
|
|
|
|
|
|
|
|
|
let bytes = bstr!(b"bbabbbabbbba");
|
|
|
|
|
let matches = &[(0, 2), (3, 5), (7, 9), (9, 11)];
|
|
|
|
|
let matches_rev = &[(0, 2), (4, 6), (7, 9), (9, 11)];
|
|
|
|
|
test_pattern(bytes, bstr!(b"bb"), matches, Some(matches_rev));
|
|
|
|
|
test_pattern(bytes, wstr!('b''b'), matches, Some(matches_rev));
|
|
|
|
|
|
|
|
|
|
let wide = wstr!('↓''↓''a''a''↓''↓''a''a''↓''↓');
|
|
|
|
|
test_pattern(wide, bstr!(b"aa"), &[(2, 4), (6, 8)], None);
|
|
|
|
|
test_pattern(wide, wstr!('↓''a'), &[(1, 3), (5, 7)], None);
|
|
|
|
|
}
|