Coverage Report

Created: 2025-07-23 06:03

/src/nom/src/bits/complete.rs
Line
Count
Source (jump to first uncovered line)
1
//! Bit level parsers
2
//!
3
4
use crate::error::{ErrorKind, ParseError};
5
use crate::internal::{Err, IResult};
6
use crate::lib::std::ops::{AddAssign, Div, Shl, Shr};
7
use crate::traits::{Input, ToUsize};
8
9
/// Generates a parser taking `count` bits
10
///
11
/// # Example
12
/// ```rust
13
/// # use nom::bits::complete::take;
14
/// # use nom::IResult;
15
/// # use nom::error::{Error, ErrorKind};
16
/// // Input is a tuple of (input: I, bit_offset: usize)
17
/// fn parser(input: (&[u8], usize), count: usize)-> IResult<(&[u8], usize), u8> {
18
///  take(count)(input)
19
/// }
20
///
21
/// // Consumes 0 bits, returns 0
22
/// assert_eq!(parser(([0b00010010].as_ref(), 0), 0), Ok((([0b00010010].as_ref(), 0), 0)));
23
///
24
/// // Consumes 4 bits, returns their values and increase offset to 4
25
/// assert_eq!(parser(([0b00010010].as_ref(), 0), 4), Ok((([0b00010010].as_ref(), 4), 0b00000001)));
26
///
27
/// // Consumes 4 bits, offset is 4, returns their values and increase offset to 0 of next byte
28
/// assert_eq!(parser(([0b00010010].as_ref(), 4), 4), Ok((([].as_ref(), 0), 0b00000010)));
29
///
30
/// // Tries to consume 12 bits but only 8 are available
31
/// assert_eq!(parser(([0b00010010].as_ref(), 0), 12), Err(nom::Err::Error(Error{input: ([0b00010010].as_ref(), 0), code: ErrorKind::Eof })));
32
/// ```
33
0
pub fn take<I, O, C, E: ParseError<(I, usize)>>(
34
0
  count: C,
35
0
) -> impl Fn((I, usize)) -> IResult<(I, usize), O, E>
36
0
where
37
0
  I: Input<Item = u8>,
38
0
  C: ToUsize,
39
0
  O: From<u8> + AddAssign + Shl<usize, Output = O> + Shr<usize, Output = O>,
40
0
{
41
0
  let count = count.to_usize();
42
0
  move |(input, bit_offset): (I, usize)| {
43
0
    if count == 0 {
44
0
      Ok(((input, bit_offset), 0u8.into()))
45
0
    } else if input.input_len() * 8 < count + bit_offset {
46
0
      Err(Err::Error(E::from_error_kind(
47
0
        (input, bit_offset),
48
0
        ErrorKind::Eof,
49
0
      )))
50
    } else {
51
0
      let cnt = (count + bit_offset).div(8);
52
0
      let mut acc: O = 0_u8.into();
53
0
      let mut offset: usize = bit_offset;
54
0
      let mut remaining: usize = count;
55
0
      let mut end_offset: usize = 0;
56
57
0
      for byte in input.iter_elements().take(cnt + 1) {
58
0
        if remaining == 0 {
59
0
          break;
60
0
        }
61
0
        let val: O = if offset == 0 {
62
0
          byte.into()
63
        } else {
64
0
          ((byte << offset) >> offset).into()
65
        };
66
67
0
        if remaining < 8 - offset {
68
0
          acc += val >> (8 - offset - remaining);
69
0
          end_offset = remaining + offset;
70
0
          break;
71
0
        } else {
72
0
          acc += val << (remaining - (8 - offset));
73
0
          remaining -= 8 - offset;
74
0
          offset = 0;
75
0
        }
76
      }
77
0
      Ok(((input.take_from(cnt), end_offset), acc))
78
    }
79
0
  }
80
0
}
81
82
/// Generates a parser taking `count` bits and comparing them to `pattern`
83
0
pub fn tag<I, O, C, E: ParseError<(I, usize)>>(
84
0
  pattern: O,
85
0
  count: C,
86
0
) -> impl Fn((I, usize)) -> IResult<(I, usize), O, E>
87
0
where
88
0
  I: Input<Item = u8> + Clone,
89
0
  C: ToUsize,
90
0
  O: From<u8> + AddAssign + Shl<usize, Output = O> + Shr<usize, Output = O> + PartialEq,
91
0
{
92
0
  let count = count.to_usize();
93
0
  move |input: (I, usize)| {
94
0
    let inp = input.clone();
95
0
96
0
    take(count)(input).and_then(|(i, o)| {
97
0
      if pattern == o {
98
0
        Ok((i, o))
99
      } else {
100
0
        Err(Err::Error(error_position!(inp, ErrorKind::TagBits)))
101
      }
102
0
    })
103
0
  }
104
0
}
105
106
/// Parses one specific bit as a bool.
107
///
108
/// # Example
109
/// ```rust
110
/// # use nom::bits::complete::bool;
111
/// # use nom::IResult;
112
/// # use nom::error::{Error, ErrorKind};
113
///
114
/// fn parse(input: (&[u8], usize)) -> IResult<(&[u8], usize), bool> {
115
///     bool(input)
116
/// }
117
///
118
/// assert_eq!(parse(([0b10000000].as_ref(), 0)), Ok((([0b10000000].as_ref(), 1), true)));
119
/// assert_eq!(parse(([0b10000000].as_ref(), 1)), Ok((([0b10000000].as_ref(), 2), false)));
120
/// ```
121
0
pub fn bool<I, E: ParseError<(I, usize)>>(input: (I, usize)) -> IResult<(I, usize), bool, E>
122
0
where
123
0
  I: Input<Item = u8>,
124
0
{
125
0
  let (res, bit): (_, u32) = take(1usize)(input)?;
126
0
  Ok((res, bit != 0))
127
0
}
128
129
#[cfg(test)]
130
mod test {
131
  use super::*;
132
133
  #[test]
134
  fn test_take_0() {
135
    let input = [0b00010010].as_ref();
136
    let count = 0usize;
137
    assert_eq!(count, 0usize);
138
    let offset = 0usize;
139
140
    let result: crate::IResult<(&[u8], usize), usize> = take(count)((input, offset));
141
142
    assert_eq!(result, Ok(((input, offset), 0)));
143
  }
144
145
  #[test]
146
  fn test_take_eof() {
147
    let input = [0b00010010].as_ref();
148
149
    let result: crate::IResult<(&[u8], usize), usize> = take(1usize)((input, 8));
150
151
    assert_eq!(
152
      result,
153
      Err(crate::Err::Error(crate::error::Error {
154
        input: (input, 8),
155
        code: ErrorKind::Eof
156
      }))
157
    )
158
  }
159
160
  #[test]
161
  fn test_take_span_over_multiple_bytes() {
162
    let input = [0b00010010, 0b00110100, 0b11111111, 0b11111111].as_ref();
163
164
    let result: crate::IResult<(&[u8], usize), usize> = take(24usize)((input, 4));
165
166
    assert_eq!(
167
      result,
168
      Ok((([0b11111111].as_ref(), 4), 0b1000110100111111111111))
169
    );
170
  }
171
172
  #[test]
173
  fn test_bool_0() {
174
    let input = [0b10000000].as_ref();
175
176
    let result: crate::IResult<(&[u8], usize), bool> = bool((input, 0));
177
178
    assert_eq!(result, Ok(((input, 1), true)));
179
  }
180
181
  #[test]
182
  fn test_bool_eof() {
183
    let input = [0b10000000].as_ref();
184
185
    let result: crate::IResult<(&[u8], usize), bool> = bool((input, 8));
186
187
    assert_eq!(
188
      result,
189
      Err(crate::Err::Error(crate::error::Error {
190
        input: (input, 8),
191
        code: ErrorKind::Eof
192
      }))
193
    );
194
  }
195
}