Coverage Report

Created: 2025-10-10 07:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/nom-7.1.3/src/bits/streaming.rs
Line
Count
Source
1
//! Bit level parsers
2
//!
3
4
use crate::error::{ErrorKind, ParseError};
5
use crate::internal::{Err, IResult, Needed};
6
use crate::lib::std::ops::{AddAssign, Div, RangeFrom, Shl, Shr};
7
use crate::traits::{InputIter, InputLength, Slice, ToUsize};
8
9
/// Generates a parser taking `count` bits
10
0
pub fn take<I, O, C, E: ParseError<(I, usize)>>(
11
0
  count: C,
12
0
) -> impl Fn((I, usize)) -> IResult<(I, usize), O, E>
13
0
where
14
0
  I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
15
0
  C: ToUsize,
16
0
  O: From<u8> + AddAssign + Shl<usize, Output = O> + Shr<usize, Output = O>,
17
{
18
0
  let count = count.to_usize();
19
0
  move |(input, bit_offset): (I, usize)| {
20
0
    if count == 0 {
21
0
      Ok(((input, bit_offset), 0u8.into()))
22
    } else {
23
0
      let cnt = (count + bit_offset).div(8);
24
0
      if input.input_len() * 8 < count + bit_offset {
25
0
        Err(Err::Incomplete(Needed::new(count as usize)))
26
      } else {
27
0
        let mut acc: O = 0_u8.into();
28
0
        let mut offset: usize = bit_offset;
29
0
        let mut remaining: usize = count;
30
0
        let mut end_offset: usize = 0;
31
32
0
        for byte in input.iter_elements().take(cnt + 1) {
33
0
          if remaining == 0 {
34
0
            break;
35
0
          }
36
0
          let val: O = if offset == 0 {
37
0
            byte.into()
38
          } else {
39
0
            ((byte << offset) as u8 >> offset).into()
40
          };
41
42
0
          if remaining < 8 - offset {
43
0
            acc += val >> (8 - offset - remaining);
44
0
            end_offset = remaining + offset;
45
0
            break;
46
0
          } else {
47
0
            acc += val << (remaining - (8 - offset));
48
0
            remaining -= 8 - offset;
49
0
            offset = 0;
50
0
          }
51
        }
52
0
        Ok(((input.slice(cnt..), end_offset), acc))
53
      }
54
    }
55
0
  }
56
0
}
57
58
/// Generates a parser taking `count` bits and comparing them to `pattern`
59
0
pub fn tag<I, O, C, E: ParseError<(I, usize)>>(
60
0
  pattern: O,
61
0
  count: C,
62
0
) -> impl Fn((I, usize)) -> IResult<(I, usize), O, E>
63
0
where
64
0
  I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + Clone,
65
0
  C: ToUsize,
66
0
  O: From<u8> + AddAssign + Shl<usize, Output = O> + Shr<usize, Output = O> + PartialEq,
67
{
68
0
  let count = count.to_usize();
69
0
  move |input: (I, usize)| {
70
0
    let inp = input.clone();
71
72
0
    take(count)(input).and_then(|(i, o)| {
73
0
      if pattern == o {
74
0
        Ok((i, o))
75
      } else {
76
0
        Err(Err::Error(error_position!(inp, ErrorKind::TagBits)))
77
      }
78
0
    })
79
0
  }
80
0
}
81
82
/// Parses one specific bit as a bool.
83
///
84
/// # Example
85
/// ```rust
86
/// # use nom::bits::complete::bool;
87
/// # use nom::IResult;
88
/// # use nom::error::{Error, ErrorKind};
89
///
90
/// fn parse(input: (&[u8], usize)) -> IResult<(&[u8], usize), bool> {
91
///     bool(input)
92
/// }
93
///
94
/// assert_eq!(parse(([0b10000000].as_ref(), 0)), Ok((([0b10000000].as_ref(), 1), true)));
95
/// assert_eq!(parse(([0b10000000].as_ref(), 1)), Ok((([0b10000000].as_ref(), 2), false)));
96
/// ```
97
0
pub fn bool<I, E: ParseError<(I, usize)>>(input: (I, usize)) -> IResult<(I, usize), bool, E>
98
0
where
99
0
  I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
100
{
101
0
  let (res, bit): (_, u32) = take(1usize)(input)?;
102
0
  Ok((res, bit != 0))
103
0
}
104
105
#[cfg(test)]
106
mod test {
107
  use super::*;
108
109
  #[test]
110
  fn test_take_0() {
111
    let input = [].as_ref();
112
    let count = 0usize;
113
    assert_eq!(count, 0usize);
114
    let offset = 0usize;
115
116
    let result: crate::IResult<(&[u8], usize), usize> = take(count)((input, offset));
117
118
    assert_eq!(result, Ok(((input, offset), 0)));
119
  }
120
121
  #[test]
122
  fn test_tag_ok() {
123
    let input = [0b00011111].as_ref();
124
    let offset = 0usize;
125
    let bits_to_take = 4usize;
126
    let value_to_tag = 0b0001;
127
128
    let result: crate::IResult<(&[u8], usize), usize> =
129
      tag(value_to_tag, bits_to_take)((input, offset));
130
131
    assert_eq!(result, Ok(((input, bits_to_take), value_to_tag)));
132
  }
133
134
  #[test]
135
  fn test_tag_err() {
136
    let input = [0b00011111].as_ref();
137
    let offset = 0usize;
138
    let bits_to_take = 4usize;
139
    let value_to_tag = 0b1111;
140
141
    let result: crate::IResult<(&[u8], usize), usize> =
142
      tag(value_to_tag, bits_to_take)((input, offset));
143
144
    assert_eq!(
145
      result,
146
      Err(crate::Err::Error(crate::error::Error {
147
        input: (input, offset),
148
        code: ErrorKind::TagBits
149
      }))
150
    );
151
  }
152
153
  #[test]
154
  fn test_bool_0() {
155
    let input = [0b10000000].as_ref();
156
157
    let result: crate::IResult<(&[u8], usize), bool> = bool((input, 0));
158
159
    assert_eq!(result, Ok(((input, 1), true)));
160
  }
161
162
  #[test]
163
  fn test_bool_eof() {
164
    let input = [0b10000000].as_ref();
165
166
    let result: crate::IResult<(&[u8], usize), bool> = bool((input, 8));
167
168
    assert_eq!(result, Err(crate::Err::Incomplete(Needed::new(1))));
169
  }
170
}