1use crate::error::parse::ParseDataError;
4
5pub(super) type Cursor<'a> = &'a [u8];
7
8pub(super) fn read_exact<'a>(cursor: &mut Cursor<'a>, count: usize) -> Result<&'a [u8], ParseDataError> {
10 match cursor.split_at_checked(count) {
11 Some((result, tail)) => {
12 *cursor = tail;
13 Ok(result)
14 }
15 None => Err(ParseDataError::UnexpectedEof),
16 }
17}
18
19pub(super) fn read_chunk_exact<'a, const N: usize>(cursor: &mut Cursor<'a>) -> Result<&'a [u8; N], ParseDataError> {
21 match cursor.split_first_chunk::<N>() {
22 Some((result, tail)) => {
23 *cursor = tail;
24 Ok(result)
25 }
26 None => Err(ParseDataError::UnexpectedEof),
27 }
28}
29
30pub(super) fn read_tag(cursor: &mut Cursor<'_>, tag: &[u8]) -> Result<(), ParseDataError> {
32 if read_exact(cursor, tag.len())? == tag {
33 Ok(())
34 } else {
35 Err(ParseDataError::InvalidData)
36 }
37}
38
39pub(super) fn read_optional_tag(cursor: &mut Cursor<'_>, tag: &[u8]) -> Result<bool, ParseDataError> {
41 if cursor.starts_with(tag) {
42 read_exact(cursor, tag.len())?;
43 Ok(true)
44 } else {
45 Ok(false)
46 }
47}
48
49pub(super) fn read_while<'a, F: Fn(&u8) -> bool>(cursor: &mut Cursor<'a>, f: F) -> Result<&'a [u8], ParseDataError> {
51 read_exact(cursor, cursor.iter().position(|x| !f(x)).unwrap_or(cursor.len()))
52}
53
54pub(super) fn read_until<'a, F: Fn(&u8) -> bool>(cursor: &mut Cursor<'a>, f: F) -> Result<&'a [u8], ParseDataError> {
56 read_exact(cursor, cursor.iter().position(f).unwrap_or(cursor.len()))
57}