Coverage Report

Created: 2025-07-18 06:49

/rust/registry/src/index.crates.io-6f17d22bba15001f/nom-7.1.3/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, RangeFrom, Shl, Shr};
7
use crate::traits::{InputIter, InputLength, Slice, 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: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
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
    } else {
46
0
      let cnt = (count + bit_offset).div(8);
47
0
      if input.input_len() * 8 < count + bit_offset {
48
0
        Err(Err::Error(E::from_error_kind(
49
0
          (input, bit_offset),
50
0
          ErrorKind::Eof,
51
0
        )))
52
      } else {
53
0
        let mut acc: O = 0_u8.into();
54
0
        let mut offset: usize = bit_offset;
55
0
        let mut remaining: usize = count;
56
0
        let mut end_offset: usize = 0;
57
58
0
        for byte in input.iter_elements().take(cnt + 1) {
59
0
          if remaining == 0 {
60
0
            break;
61
0
          }
62
0
          let val: O = if offset == 0 {
63
0
            byte.into()
64
          } else {
65
0
            ((byte << offset) as u8 >> offset).into()
66
          };
67
68
0
          if remaining < 8 - offset {
69
0
            acc += val >> (8 - offset - remaining);
70
0
            end_offset = remaining + offset;
71
0
            break;
72
0
          } else {
73
0
            acc += val << (remaining - (8 - offset));
74
0
            remaining -= 8 - offset;
75
0
            offset = 0;
76
0
          }
77
        }
78
0
        Ok(((input.slice(cnt..), end_offset), acc))
79
      }
80
    }
81
0
  }
82
0
}
83
84
/// Generates a parser taking `count` bits and comparing them to `pattern`
85
0
pub fn tag<I, O, C, E: ParseError<(I, usize)>>(
86
0
  pattern: O,
87
0
  count: C,
88
0
) -> impl Fn((I, usize)) -> IResult<(I, usize), O, E>
89
0
where
90
0
  I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + Clone,
91
0
  C: ToUsize,
92
0
  O: From<u8> + AddAssign + Shl<usize, Output = O> + Shr<usize, Output = O> + PartialEq,
93
0
{
94
0
  let count = count.to_usize();
95
0
  move |input: (I, usize)| {
96
0
    let inp = input.clone();
97
0
98
0
    take(count)(input).and_then(|(i, o)| {
99
0
      if pattern == o {
100
0
        Ok((i, o))
101
      } else {
102
0
        Err(Err::Error(error_position!(inp, ErrorKind::TagBits)))
103
      }
104
0
    })
105
0
  }
106
0
}
107
108
/// Parses one specific bit as a bool.
109
///
110
/// # Example
111
/// ```rust
112
/// # use nom::bits::complete::bool;
113
/// # use nom::IResult;
114
/// # use nom::error::{Error, ErrorKind};
115
///
116
/// fn parse(input: (&[u8], usize)) -> IResult<(&[u8], usize), bool> {
117
///     bool(input)
118
/// }
119
///
120
/// assert_eq!(parse(([0b10000000].as_ref(), 0)), Ok((([0b10000000].as_ref(), 1), true)));
121
/// assert_eq!(parse(([0b10000000].as_ref(), 1)), Ok((([0b10000000].as_ref(), 2), false)));
122
/// ```
123
0
pub fn bool<I, E: ParseError<(I, usize)>>(input: (I, usize)) -> IResult<(I, usize), bool, E>
124
0
where
125
0
  I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
126
0
{
127
0
  let (res, bit): (_, u32) = take(1usize)(input)?;
128
0
  Ok((res, bit != 0))
129
0
}
130
131
#[cfg(test)]
132
mod test {
133
  use super::*;
134
135
  #[test]
136
  fn test_take_0() {
137
    let input = [0b00010010].as_ref();
138
    let count = 0usize;
139
    assert_eq!(count, 0usize);
140
    let offset = 0usize;
141
142
    let result: crate::IResult<(&[u8], usize), usize> = take(count)((input, offset));
143
144
    assert_eq!(result, Ok(((input, offset), 0)));
145
  }
146
147
  #[test]
148
  fn test_take_eof() {
149
    let input = [0b00010010].as_ref();
150
151
    let result: crate::IResult<(&[u8], usize), usize> = take(1usize)((input, 8));
152
153
    assert_eq!(
154
      result,
155
      Err(crate::Err::Error(crate::error::Error {
156
        input: (input, 8),
157
        code: ErrorKind::Eof
158
      }))
159
    )
160
  }
161
162
  #[test]
163
  fn test_take_span_over_multiple_bytes() {
164
    let input = [0b00010010, 0b00110100, 0b11111111, 0b11111111].as_ref();
165
166
    let result: crate::IResult<(&[u8], usize), usize> = take(24usize)((input, 4));
167
168
    assert_eq!(
169
      result,
170
      Ok((([0b11111111].as_ref(), 4), 0b1000110100111111111111))
171
    );
172
  }
173
174
  #[test]
175
  fn test_bool_0() {
176
    let input = [0b10000000].as_ref();
177
178
    let result: crate::IResult<(&[u8], usize), bool> = bool((input, 0));
179
180
    assert_eq!(result, Ok(((input, 1), true)));
181
  }
182
183
  #[test]
184
  fn test_bool_eof() {
185
    let input = [0b10000000].as_ref();
186
187
    let result: crate::IResult<(&[u8], usize), bool> = bool((input, 8));
188
189
    assert_eq!(
190
      result,
191
      Err(crate::Err::Error(crate::error::Error {
192
        input: (input, 8),
193
        code: ErrorKind::Eof
194
      }))
195
    );
196
  }
197
}