#![allow(clippy::unit_cmp)]
#[macro_use]
mod common;
use common::*;
use std::any::Any;
#[test]
fn test_at_end_true() {
assert_eq!(
read_all_ok!(b"hello", |r| {
r.consume(b"hello")?;
Ok(r.at_end())
}),
true
);
}
#[test]
fn test_at_end_false() {
assert_eq!(
read_partial_ok!(b"hello", |r| {
r.consume(b"hell")?;
Ok(r.at_end())
}),
(false, input!(b"o"))
);
}
#[test]
fn test_context() {
let err = read_all_err!(b"hello", |r| { r.context("bob", |r| r.consume(b"world")) });
#[cfg(feature = "full-backtrace")]
assert_eq!(err.backtrace().count(), 3);
#[cfg(not(feature = "full-backtrace"))]
assert_eq!(err.backtrace().count(), 1);
err.backtrace().walk(&mut |i, c| {
let c = <dyn Any>::downcast_ref::<CoreOperation>(c.operation().as_any());
assert!(c.is_some());
assert!(i != 5);
true
});
}
#[test]
fn test_skip() {
assert_eq!(read_all_ok!(b"hello", |r| { r.skip(5) }), ());
}
#[test]
fn test_skip_opt_true() {
assert_eq!(
read_infallible!(b"hello", |r| { r.skip_opt(5) }),
(true, input!(b""))
);
}
#[test]
fn test_skip_opt_false() {
assert_eq!(
read_infallible!(b"hello", |r| { r.skip_opt(6) }),
(false, input!(b"hello"))
);
}
#[test]
fn test_skip_while() {
read_all_ok!(b"hello!", |r| {
r.skip_while(|c: u8| c.is_ascii_alphabetic());
r.skip(1)
});
}
#[test]
fn test_try_skip_while() {
read_all_ok!(b"hello!", |r| {
r.try_skip_while(|c| Ok(c.is_ascii_alphabetic()))?;
r.skip(1)
})
}
#[test]
fn test_take() {
assert_eq!(read_all_ok!(b"hello", |r| { r.take(5) }), b"hello"[..]);
}
#[test]
fn test_take_opt_true() {
assert_eq!(
read_infallible!(b"hello", |r| { r.take_opt(5) }),
(Some(input!(b"hello"[..])), input!(b""))
);
}
#[test]
fn test_take_opt_false() {
assert_eq!(
read_infallible!(b"hello", |r| { r.take_opt(6) }),
(None, input!(b"hello"))
);
}
#[test]
fn test_take_remaining() {
let remaining = read_all_ok!(b"hello", |r| { Ok(r.take_remaining()) });
assert_eq!(remaining, b"hello"[..]);
assert_eq!(remaining.bound(), Bound::Start);
}
#[test]
fn test_take_remaining_second() {
let remaining = read_all_ok!(b"hello", |r| {
let _ = r.take_remaining();
Ok(r.take_remaining())
});
assert_eq!(remaining, b""[..]);
assert_eq!(remaining.bound(), Bound::None);
}
#[test]
fn test_take_while_all() {
let input = read_all_ok!(b"hello", |r| {
Ok(r.take_while(|c: u8| c.is_ascii_alphabetic()))
});
assert_eq!(input, b"hello"[..]);
assert_eq!(input.bound(), Bound::Start);
}
#[test]
fn test_take_while_partial() {
let input = read_all_ok!(b"hello!", |r| {
let input = r.take_while(|c: u8| c.is_ascii_alphabetic());
r.skip(1)?;
Ok(input)
});
assert_eq!(input, b"hello"[..]);
assert_eq!(input.bound(), Bound::StartEnd);
}
#[test]
fn test_try_take_while_all() {
let input = read_all_ok!(b"hello", |r| {
r.try_take_while(|c| Ok(c.is_ascii_alphabetic()))
});
assert_eq!(input, b"hello"[..]);
assert_eq!(input.bound(), Bound::Start);
}
#[test]
fn test_try_take_while_partial() {
let input = read_all_ok!(b"hello!", |r| {
let v = r.try_take_while(|c| Ok(c.is_ascii_alphabetic()))?;
r.skip(1)?;
Ok(v)
});
assert_eq!(input, b"hello"[..]);
assert_eq!(input.bound(), Bound::StartEnd);
}
#[test]
fn test_take_consumed_all_unbound() {
let (_, consumed) = read_all_ok!(b"hello", |r| {
Ok(r.take_consumed(|r| {
let _ = r.take_remaining();
}))
});
assert_eq!(consumed, b"hello"[..]);
assert_eq!(consumed.bound(), Bound::Start);
}
#[test]
fn test_take_consumed_all_bound() {
let (_, consumed) = read_all_ok!(b"hello", |r| {
Ok(r.take_consumed(|r| {
let _ = r.consume(b"hello");
}))
});
assert_eq!(consumed, b"hello"[..]);
assert_eq!(consumed.bound(), Bound::StartEnd);
}
#[test]
fn test_take_consumed_partial_bound() {
let (_, consumed) = read_all_ok!(b"hello", |r| {
let consumed = r.take_consumed(|r| {
let _ = r.take(2);
let _ = r.take(1);
});
r.consume("lo")?;
Ok(consumed)
});
assert_eq!(consumed, b"hel"[..]);
assert_eq!(consumed.bound(), Bound::StartEnd);
}
#[test]
fn test_try_take_consumed_all_unbound() {
let (_, consumed) = read_all_ok!(b"hello", |r| {
r.try_take_consumed(|r| {
let _ = r.take_remaining();
Ok(())
})
});
assert_eq!(consumed, b"hello"[..]);
assert_eq!(consumed.bound(), Bound::Start);
}
#[test]
fn test_try_take_consumed_all_bound() {
let (_, consumed) = read_all_ok!(b"hello", |r| {
r.try_take_consumed(|r| {
r.consume(b"hello")?;
Ok(())
})
});
assert_eq!(consumed, b"hello"[..]);
assert_eq!(consumed.bound(), Bound::StartEnd);
}
#[test]
fn test_try_take_consumed_partial_bound() {
let (_, consumed) = read_all_ok!(b"hello", |r| {
let consumed = r.try_take_consumed(|r| {
let _ = r.take(2)?;
let _ = r.take(1)?;
Ok(())
})?;
r.consume("lo")?;
Ok(consumed)
});
assert_eq!(consumed, b"hel"[..]);
assert_eq!(consumed.bound(), Bound::StartEnd);
}
#[test]
fn test_peek_enough() {
assert_eq!(
read_all_ok!(b"hello", |r| {
let v = *r.peek(4)? == b"hell"[..];
r.skip(5)?;
Ok(v)
}),
true
);
}
#[test]
fn test_peek_too_much() {
let _ = read_all_err!(b"hello", |r| {
let _ = r.peek(6)?;
r.skip(5)
});
}
#[test]
fn test_peek_opt_enough() {
assert_eq!(
read_all_ok!(b"hello", |r| {
let v = r.peek_opt(4).map_or(false, |v| *v == b"hell"[..]);
r.skip(5)?;
Ok(v)
}),
true
);
}
#[test]
fn test_peek_opt_too_much() {
assert_eq!(
read_all_ok!(b"hello", |r| {
let v = r.peek_opt(10).map_or(false, |v| *v == b"hell"[..]);
r.skip(5)?;
Ok(v)
}),
false
);
}
#[test]
fn test_peek_eq_exact_same() {
let _ = read_partial_ok!(b"helloworld", |r| {
assert!(r.peek_eq(b"helloworld"));
Ok(())
});
}
#[test]
fn test_peek_eq_same_value_different_len() {
let _ = read_partial_ok!(b"helloworld", |r| {
assert!(r.peek_eq(b"hello"));
Ok(())
});
}
#[test]
fn test_peek_eq_shorter_and_different_value() {
let _ = read_partial_ok!(b"helloworld", |r| {
assert!(!r.peek_eq(b"no"));
Ok(())
});
}
#[test]
fn test_peek_eq_longer() {
let _ = read_partial_ok!(b"helloworld", |r| {
assert!(!r.peek_eq(b"helloworld!"));
Ok(())
});
}
#[test]
fn test_consume_exact_same() {
assert_eq!(read_all_ok!(b"hello", |r| { r.consume(b"hello") }), ());
}
#[test]
fn test_consume_same_value_different_len() {
assert_eq!(
read_all_err!(b"hell", |r| { r.consume(b"hello") }).to_retry_requirement(),
RetryRequirement::new(1)
);
}
#[test]
fn test_consume_different_len_and_value() {
assert_eq!(
read_all_err!(b"abc", |r| { r.consume(b"hello") }).to_retry_requirement(),
None
);
}
#[test]
fn test_consume_same_len_different_value() {
assert_eq!(
read_all_err!(b"abcde", |r| { r.consume(b"hello") }).to_retry_requirement(),
None
);
}
#[test]
fn test_consume_opt_true() {
assert!(read_all_ok!(b"hello", |r| { Ok(r.consume_opt(b"hello")) }));
}
#[test]
fn test_consume_opt_false() {
assert!(!read_all_ok!(b"abc", |r| {
let v = r.consume_opt(b"hello");
r.skip(3)?;
Ok(v)
}));
}
#[test]
fn test_verify_true() {
read_all_ok!(b"1", |r| { r.verify("value", |r| r.consume_opt(b"1")) });
}
#[test]
fn test_verify_false() {
let _ = read_all_err!(b"1", |r| { r.verify("value", |r| r.consume_opt(b"2")) });
}
#[test]
fn test_try_verify_ok_true() {
read_all_ok!(b"1", |r| {
r.try_verify("value", |r| Ok(r.consume_opt(b"1")))
})
}
#[test]
fn test_try_verify_ok_false() {
let _ = read_all_err!(b"1", |r| {
r.try_verify("value", |r| Ok(r.consume_opt(b"2")))
});
}
#[test]
fn test_try_verify_err() {
let _ = read_all_err!(b"1", |r| {
r.try_verify("value", |r| r.consume(b"2").map(|()| true))
});
}
#[test]
fn test_expect_some() {
read_all_ok!(b"1", |r| {
r.expect("value", |r| Some(r.consume_opt(b"1")))
});
}
#[test]
fn test_expect_none() {
let _ = read_all_err!(b"", |r| { r.expect("value", |_| Option::<()>::None) });
}
#[test]
fn test_try_expect_some() {
read_all_ok!(b"", |r| { r.try_expect("value", |_| Ok(Some(()))) });
}
#[test]
fn test_try_expect_none() {
let _ = read_all_err!(b"", |r| {
r.try_expect("value", |_| Ok(Option::<()>::None))
});
}
struct ExternalError(Option<RetryRequirement>);
impl<'i> External<'i> for ExternalError {
fn retry_requirement(&self) -> Option<RetryRequirement> {
self.0
}
}
#[test]
fn try_expect_external_ok() {
read_all_ok!(b"", |r| {
r.try_expect_external("value", |i| Result::<_, ExternalError>::Ok((i.len(), ())))
});
}
#[test]
fn try_expect_external_unconsumed() {
let _ = read_all_err!(b"abc", |r| {
r.try_expect_external("value", |i| {
Result::<_, ExternalError>::Ok((i.len() - 1, ()))
})
});
}
#[test]
fn try_expect_external_read_too_much() {
let _ = read_all_err!(b"abc", |r| {
r.try_expect_external("value", |i| {
Result::<_, ExternalError>::Ok((i.len() + 1, ()))
})
});
}
#[test]
fn try_expect_external_read_invalid_boundary() {
assert_eq!('♥'.len_utf8(), 3);
let _ = read_all_err!("♥", |r| {
r.try_expect_external("value", |i| {
Result::<_, ExternalError>::Ok((i.byte_len() - 1, ()))
})
});
}
#[test]
fn try_expect_external_err() {
let error = read_all_err!(b"", |r| {
r.try_expect_external("value", |_| {
Result::<(usize, ()), ExternalError>::Err(ExternalError(RetryRequirement::new(0)))
})
});
assert!(error.is_fatal());
}
#[test]
fn try_expect_external_err_retry() {
let error = read_all_err!(b"", |r| {
r.try_expect_external("value", |_| {
Result::<(usize, ()), ExternalError>::Err(ExternalError(RetryRequirement::new(1)))
})
});
assert!(!error.is_fatal());
assert_eq!(error.to_retry_requirement(), RetryRequirement::new(1));
}
#[test]
fn test_recover() {
read_all_ok!(b"", |r| {
r.recover(|r| r.take(1));
Ok(())
})
}
#[test]
fn test_recover_if_ok() {
read_all_ok!(b"1", |r| { r.recover_if(|r| { r.take(1) }, |_| false) });
}
#[test]
fn test_recover_if_true() {
read_all_ok!(b"", |r| { r.recover_if(|r| { r.take(1) }, |_| true) });
}
#[test]
fn test_recover_if_false() {
let _ = read_all_err!(b"", |r| { r.recover_if(|r| { r.take(1) }, |_| false) });
}
#[test]
fn test_error() {
let _: Result<_, Expected> = read_all!(b"", |r| {
let result = r.error(|r: &mut BytesReader<Fatal>| {
r.take(1)
});
assert_eq!(result, Err(Fatal));
Ok(())
});
}