blob: 06047dfd4c919b8f5d2d58111fe8ac5f37f39696 [file] [log] [blame]
#[cfg(feature = "std")]
use proptest::prelude::*;
use crate::error::ErrMode::Backtrack;
use crate::error::{ErrorKind, InputError};
use crate::token::tag;
use crate::{
combinator::{separated, separated_pair},
PResult, Parser,
};
use super::*;
#[cfg(feature = "std")]
#[test]
fn test_fxhashmap_compiles() {
let input = "a=b";
fn pair(i: &mut &str) -> PResult<(char, char)> {
let out = separated_pair('a', '=', 'b').parse_next(i)?;
Ok(out)
}
let _: rustc_hash::FxHashMap<char, char> = separated(0.., pair, ',').parse(input).unwrap();
}
#[test]
fn test_offset_u8() {
let s = b"abcd123";
let a = &s[..];
let b = &a[2..];
let c = &a[..4];
let d = &a[3..5];
assert_eq!(b.offset_from(&a), 2);
assert_eq!(c.offset_from(&a), 0);
assert_eq!(d.offset_from(&a), 3);
}
#[test]
fn test_offset_str() {
let a = "abcřèÂßÇd123";
let b = &a[7..];
let c = &a[..5];
let d = &a[5..9];
assert_eq!(b.offset_from(&a), 7);
assert_eq!(c.offset_from(&a), 0);
assert_eq!(d.offset_from(&a), 5);
}
#[test]
#[cfg(feature = "alloc")]
fn test_bit_stream_empty() {
let i = (&b""[..], 0);
let actual = i.iter_offsets().collect::<crate::lib::std::vec::Vec<_>>();
assert_eq!(actual, vec![]);
let actual = i.eof_offset();
assert_eq!(actual, 0);
let actual = i.peek_token();
assert_eq!(actual, None);
let actual = i.offset_for(|b| b);
assert_eq!(actual, None);
let actual = i.offset_at(1);
assert_eq!(actual, Err(Needed::new(1)));
let (actual_input, actual_slice) = i.peek_slice(0);
assert_eq!(actual_input, (&b""[..], 0));
assert_eq!(actual_slice, (&b""[..], 0, 0));
}
#[test]
#[cfg(feature = "alloc")]
fn test_bit_offset_empty() {
let i = (&b""[..], 0);
let actual = i.offset_from(&i);
assert_eq!(actual, 0);
}
#[cfg(feature = "std")]
proptest! {
#[test]
#[cfg_attr(miri, ignore)] // See https://github.com/AltSysrq/proptest/issues/253
fn bit_stream(byte_len in 0..20usize, start in 0..160usize) {
bit_stream_inner(byte_len, start);
}
}
#[cfg(feature = "std")]
fn bit_stream_inner(byte_len: usize, start: usize) {
let start = start.min(byte_len * 8);
let start_byte = start / 8;
let start_bit = start % 8;
let bytes = vec![0b1010_1010; byte_len];
let i = (&bytes[start_byte..], start_bit);
let mut curr_i = i;
let mut curr_offset = 0;
while let Some((next_i, _token)) = curr_i.peek_token() {
let to_offset = curr_i.offset_from(&i);
assert_eq!(curr_offset, to_offset);
let (slice_i, _) = i.peek_slice(curr_offset);
assert_eq!(curr_i, slice_i);
let at_offset = i.offset_at(curr_offset).unwrap();
assert_eq!(curr_offset, at_offset);
let eof_offset = curr_i.eof_offset();
let (next_eof_i, eof_slice) = curr_i.peek_slice(eof_offset);
assert_eq!(next_eof_i, (&b""[..], 0));
let eof_slice_i = (eof_slice.0, eof_slice.1);
assert_eq!(eof_slice_i, curr_i);
curr_offset += 1;
curr_i = next_i;
}
assert_eq!(i.eof_offset(), curr_offset);
}
#[test]
fn test_partial_complete() {
let mut i = Partial::new(&b""[..]);
assert!(Partial::<&[u8]>::is_partial_supported());
assert!(i.is_partial(), "incomplete by default");
let incomplete_state = i.complete();
assert!(!i.is_partial(), "the stream should be marked as complete");
i.restore_partial(incomplete_state);
assert!(i.is_partial(), "incomplete stream state should be restored");
}
#[test]
fn test_custom_slice() {
type Token = usize;
type TokenSlice<'i> = &'i [Token];
let mut tokens: TokenSlice<'_> = &[1, 2, 3, 4];
let input = &mut tokens;
let start = input.checkpoint();
let _ = input.next_token();
let _ = input.next_token();
let offset = input.offset_from(&start);
assert_eq!(offset, 2);
}
#[test]
fn test_tag_support_char() {
assert_eq!(
tag::<_, _, InputError<_>>('π').parse_peek("π"),
Ok(("", "π"))
);
assert_eq!(
tag::<_, _, InputError<_>>('π').parse_peek("π3.14"),
Ok(("3.14", "π"))
);
assert_eq!(
tag::<_, _, InputError<_>>("π").parse_peek("π3.14"),
Ok(("3.14", "π"))
);
assert_eq!(
tag::<_, _, InputError<_>>('-').parse_peek("π"),
Err(Backtrack(InputError::new("π", ErrorKind::Tag)))
);
assert_eq!(
tag::<_, Partial<&[u8]>, InputError<_>>('π').parse_peek(Partial::new(b"\xCF\x80")),
Ok((Partial::new(Default::default()), "π".as_bytes()))
);
assert_eq!(
tag::<_, &[u8], InputError<_>>('π').parse_peek(b"\xCF\x80"),
Ok((Default::default(), "π".as_bytes()))
);
assert_eq!(
tag::<_, Partial<&[u8]>, InputError<_>>('π').parse_peek(Partial::new(b"\xCF\x803.14")),
Ok((Partial::new(&b"3.14"[..]), "π".as_bytes()))
);
assert_eq!(
tag::<_, &[u8], InputError<_>>('π').parse_peek(b"\xCF\x80"),
Ok((Default::default(), "π".as_bytes()))
);
assert_eq!(
tag::<_, &[u8], InputError<_>>('π').parse_peek(b"\xCF\x803.14"),
Ok((&b"3.14"[..], "π".as_bytes()))
);
assert_eq!(
tag::<_, &[u8], InputError<_>>(AsciiCaseless('a')).parse_peek(b"ABCxyz"),
Ok((&b"BCxyz"[..], &b"A"[..]))
);
assert_eq!(
tag::<_, &[u8], InputError<_>>('a').parse_peek(b"ABCxyz"),
Err(Backtrack(InputError::new(&b"ABCxyz"[..], ErrorKind::Tag)))
);
assert_eq!(
tag::<_, &[u8], InputError<_>>(AsciiCaseless('π')).parse_peek(b"\xCF\x803.14"),
Ok((&b"3.14"[..], "π".as_bytes()))
);
assert_eq!(
tag::<_, _, InputError<_>>(AsciiCaseless('🧑')).parse_peek("🧑你好"),
Ok(("你好", "🧑"))
);
let mut buffer = [0; 4];
let input = '\u{241b}'.encode_utf8(&mut buffer);
assert_eq!(
tag::<_, &[u8], InputError<_>>(AsciiCaseless('␛')).parse_peek(input.as_bytes()),
Ok((&b""[..], [226, 144, 155].as_slice()))
);
assert_eq!(
tag::<_, &[u8], InputError<_>>('-').parse_peek(b"\xCF\x80"),
Err(Backtrack(InputError::new(&b"\xCF\x80"[..], ErrorKind::Tag)))
);
}