Lines
100 %
Functions
Branches
#![cfg(test)]
use crate::char_stream::CharStream;
use crate::source_map::{BytePos, Pos};
#[test]
fn peek_should_return_eof_when_char_stream_is_empty() {
let mut char_stream = CharStream::with_text("");
assert_eq!(char_stream.peek(), CharStream::EOF_CHAR);
}
fn peek_should_return_first_char_from_stream_when_it_is_not_empty() {
let mut char_stream = CharStream::with_text("abc");
assert_eq!(char_stream.peek(), 'a');
fn multiple_calls_to_peek_should_return_the_same_char() {
fn lookahead_should_return_eof_when_char_stream_is_empty_no_matter_the_value_of_n() {
assert_eq!(char_stream.lookahead(0), CharStream::EOF_CHAR);
assert_eq!(char_stream.lookahead(1), CharStream::EOF_CHAR);
assert_eq!(char_stream.lookahead(2), CharStream::EOF_CHAR);
fn lookahead_should_return_eof_when_n_is_greater_or_equal_to_the_char_stream_length() {
assert_eq!(char_stream.lookahead(3), CharStream::EOF_CHAR);
assert_eq!(char_stream.lookahead(4), CharStream::EOF_CHAR);
assert_eq!(char_stream.lookahead(5), CharStream::EOF_CHAR);
fn lookahead_should_return_first_char_from_stream_when_n_is_zero() {
assert_eq!(char_stream.lookahead(0), 'a');
fn lookahead_should_return_nth_char_from_stream_when_n_is_nonzero() {
let mut char_stream = CharStream::with_text("abcdefg");
assert_eq!(char_stream.lookahead(1), 'b');
assert_eq!(char_stream.lookahead(4), 'e');
fn lookahead_can_look_at_most_8_chars_ahead() {
let mut char_stream = CharStream::with_text("the brown fox jumped over the lazy dog");
assert_eq!(char_stream.lookahead(8), 'n');
#[should_panic(expected = "cannot look further than 8 chars ahead")]
fn lookahead_cannot_look_further_than_8_chars_ahead() {
char_stream.lookahead(9);
fn lookahead_should_not_consume_the_char_stream() {
char_stream.lookahead(3);
fn consume_should_return_eof_when_char_stream_is_empty() {
assert_eq!(char_stream.consume(), CharStream::EOF_CHAR);
fn consume_should_return_the_then_peeked_char() {
assert_eq!(char_stream.consume(), 'a');
fn consume_should_advance_the_peeked_char_to_the_next_char() {
char_stream.consume();
assert_eq!(char_stream.peek(), 'b');
assert_eq!(char_stream.lookahead(0), 'b');
assert_eq!(char_stream.lookahead(1), 'c');
fn consume_should_return_eof_after_the_char_stream_is_completely_consumed() {
fn consume_should_return_eof_forever_after_encountering_a_null_char_in_the_middle_of_the_input() {
let mut char_stream = CharStream::with_text("abc\0def");
fn consume_should_turn_a_line_feed_and_carriage_return_into_line_feed_only() {
let mut char_stream = CharStream::with_text("\n\ra");
assert_eq!(char_stream.peek_byte_pos(), BytePos::from_usize(0));
assert_eq!(char_stream.peek(), '\n');
assert_eq!(char_stream.consume(), '\n');
assert_eq!(char_stream.peek_byte_pos(), BytePos::from_usize(2));
assert_eq!(char_stream.peek_byte_pos(), BytePos::from_usize(3));
fn consume_should_turn_a_carriage_return_and_line_feed_into_line_feed_only() {
let mut char_stream = CharStream::with_text("\r\na");
fn consume_should_not_deduplicate_line_feeds() {
let mut char_stream = CharStream::with_text("\n\na");
assert_eq!(char_stream.peek_byte_pos(), BytePos::from_usize(1));
fn consume_should_not_deduplicate_carriage_returns() {
let mut char_stream = CharStream::with_text("\r\ra");
assert_eq!(char_stream.peek(), '\r');
assert_eq!(char_stream.consume(), '\r');
fn try_consume_should_not_consume_char_stream_if_ch_is_not_equal_to_peek() {
char_stream.try_consume('b');
fn try_consume_should_return_false_if_ch_is_not_equal_to_peek() {
assert!(!char_stream.try_consume('b'));
fn try_consume_should_consume_char_stream_if_ch_is_equal_to_peek() {
char_stream.try_consume('a');
fn try_consume_should_return_true_if_ch_is_equal_to_peek() {
assert!(char_stream.try_consume('a'));
#[should_panic(expected = "cannot consume an EOF char")]
fn try_consume_should_panic_if_ch_is_eof() {
char_stream.try_consume(CharStream::EOF_CHAR);
fn peek_and_lookahead_should_return_eof_after_the_char_stream_is_completely_consumed() {
fn peek_byte_pos_should_return_zero_for_the_first_peeked_char_whether_char_stream_is_empty_or_not()
{
assert_eq!(
CharStream::with_text("").peek_byte_pos(),
BytePos::from_usize(0)
);
CharStream::with_text("abc").peek_byte_pos(),
fn peek_byte_pos_should_not_advance_after_peeking_a_char() {
let before_byte_pos = char_stream.peek_byte_pos();
let _ = char_stream.peek();
let after_byte_pos = char_stream.peek_byte_pos();
assert_eq!(before_byte_pos, after_byte_pos);
fn peek_byte_pos_should_not_advance_after_lookahead() {
let _ = char_stream.lookahead(2);
fn peek_byte_pos_should_not_advance_after_consuming_an_eof_char() {
let input_text = "abc";
let mut char_stream = CharStream::with_text(input_text);
let first_byte_pos = char_stream.peek_byte_pos();
for _ in 0..input_text.len() {
let last_byte_pos = char_stream.peek_byte_pos();
assert_ne!(first_byte_pos, last_byte_pos);
let eof_char = char_stream.consume();
assert_eq!(eof_char, CharStream::EOF_CHAR);
assert_eq!(char_stream.peek_byte_pos(), last_byte_pos);
fn peek_byte_pos_should_advance_by_one_after_consuming_an_ascii_char() {
let _ = char_stream.consume();
let second_byte_pos = char_stream.peek_byte_pos();
assert_eq!(second_byte_pos, first_byte_pos + BytePos::from_usize(1));
let third_byte_pos = char_stream.peek_byte_pos();
assert_eq!(third_byte_pos, first_byte_pos + BytePos::from_usize(2));
fn peek_byte_pos_should_advance_by_the_char_utf8_byte_length_after_consuming_a_utf8_char() {
let text_input_with_varying_char_lengths = "\u{80}\u{800}\u{10000}";
let mut char_stream = CharStream::with_text(text_input_with_varying_char_lengths);
let expected_peek_byte_poses = [
BytePos::from_usize(2), // 2-byte length
BytePos::from_usize(5), // 3-byte length
BytePos::from_usize(9), // 4-byte length
];
for expected_peek_byte_pos in expected_peek_byte_poses {
assert_eq!(char_stream.peek_byte_pos(), expected_peek_byte_pos);