16855e09eSopenharmony_ci//! Bit level parsers
26855e09eSopenharmony_ci//!
36855e09eSopenharmony_ci
46855e09eSopenharmony_ciuse crate::error::{ErrorKind, ParseError};
56855e09eSopenharmony_ciuse crate::internal::{Err, IResult, Needed};
66855e09eSopenharmony_ciuse crate::lib::std::ops::{AddAssign, Div, RangeFrom, Shl, Shr};
76855e09eSopenharmony_ciuse crate::traits::{InputIter, InputLength, Slice, ToUsize};
86855e09eSopenharmony_ci
96855e09eSopenharmony_ci/// Generates a parser taking `count` bits
106855e09eSopenharmony_cipub fn take<I, O, C, E: ParseError<(I, usize)>>(
116855e09eSopenharmony_ci  count: C,
126855e09eSopenharmony_ci) -> impl Fn((I, usize)) -> IResult<(I, usize), O, E>
136855e09eSopenharmony_ciwhere
146855e09eSopenharmony_ci  I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
156855e09eSopenharmony_ci  C: ToUsize,
166855e09eSopenharmony_ci  O: From<u8> + AddAssign + Shl<usize, Output = O> + Shr<usize, Output = O>,
176855e09eSopenharmony_ci{
186855e09eSopenharmony_ci  let count = count.to_usize();
196855e09eSopenharmony_ci  move |(input, bit_offset): (I, usize)| {
206855e09eSopenharmony_ci    if count == 0 {
216855e09eSopenharmony_ci      Ok(((input, bit_offset), 0u8.into()))
226855e09eSopenharmony_ci    } else {
236855e09eSopenharmony_ci      let cnt = (count + bit_offset).div(8);
246855e09eSopenharmony_ci      if input.input_len() * 8 < count + bit_offset {
256855e09eSopenharmony_ci        Err(Err::Incomplete(Needed::new(count as usize)))
266855e09eSopenharmony_ci      } else {
276855e09eSopenharmony_ci        let mut acc: O = 0_u8.into();
286855e09eSopenharmony_ci        let mut offset: usize = bit_offset;
296855e09eSopenharmony_ci        let mut remaining: usize = count;
306855e09eSopenharmony_ci        let mut end_offset: usize = 0;
316855e09eSopenharmony_ci
326855e09eSopenharmony_ci        for byte in input.iter_elements().take(cnt + 1) {
336855e09eSopenharmony_ci          if remaining == 0 {
346855e09eSopenharmony_ci            break;
356855e09eSopenharmony_ci          }
366855e09eSopenharmony_ci          let val: O = if offset == 0 {
376855e09eSopenharmony_ci            byte.into()
386855e09eSopenharmony_ci          } else {
396855e09eSopenharmony_ci            ((byte << offset) as u8 >> offset).into()
406855e09eSopenharmony_ci          };
416855e09eSopenharmony_ci
426855e09eSopenharmony_ci          if remaining < 8 - offset {
436855e09eSopenharmony_ci            acc += val >> (8 - offset - remaining);
446855e09eSopenharmony_ci            end_offset = remaining + offset;
456855e09eSopenharmony_ci            break;
466855e09eSopenharmony_ci          } else {
476855e09eSopenharmony_ci            acc += val << (remaining - (8 - offset));
486855e09eSopenharmony_ci            remaining -= 8 - offset;
496855e09eSopenharmony_ci            offset = 0;
506855e09eSopenharmony_ci          }
516855e09eSopenharmony_ci        }
526855e09eSopenharmony_ci        Ok(((input.slice(cnt..), end_offset), acc))
536855e09eSopenharmony_ci      }
546855e09eSopenharmony_ci    }
556855e09eSopenharmony_ci  }
566855e09eSopenharmony_ci}
576855e09eSopenharmony_ci
586855e09eSopenharmony_ci/// Generates a parser taking `count` bits and comparing them to `pattern`
596855e09eSopenharmony_cipub fn tag<I, O, C, E: ParseError<(I, usize)>>(
606855e09eSopenharmony_ci  pattern: O,
616855e09eSopenharmony_ci  count: C,
626855e09eSopenharmony_ci) -> impl Fn((I, usize)) -> IResult<(I, usize), O, E>
636855e09eSopenharmony_ciwhere
646855e09eSopenharmony_ci  I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + Clone,
656855e09eSopenharmony_ci  C: ToUsize,
666855e09eSopenharmony_ci  O: From<u8> + AddAssign + Shl<usize, Output = O> + Shr<usize, Output = O> + PartialEq,
676855e09eSopenharmony_ci{
686855e09eSopenharmony_ci  let count = count.to_usize();
696855e09eSopenharmony_ci  move |input: (I, usize)| {
706855e09eSopenharmony_ci    let inp = input.clone();
716855e09eSopenharmony_ci
726855e09eSopenharmony_ci    take(count)(input).and_then(|(i, o)| {
736855e09eSopenharmony_ci      if pattern == o {
746855e09eSopenharmony_ci        Ok((i, o))
756855e09eSopenharmony_ci      } else {
766855e09eSopenharmony_ci        Err(Err::Error(error_position!(inp, ErrorKind::TagBits)))
776855e09eSopenharmony_ci      }
786855e09eSopenharmony_ci    })
796855e09eSopenharmony_ci  }
806855e09eSopenharmony_ci}
816855e09eSopenharmony_ci
826855e09eSopenharmony_ci/// Parses one specific bit as a bool.
836855e09eSopenharmony_ci///
846855e09eSopenharmony_ci/// # Example
856855e09eSopenharmony_ci/// ```rust
866855e09eSopenharmony_ci/// # use nom::bits::complete::bool;
876855e09eSopenharmony_ci/// # use nom::IResult;
886855e09eSopenharmony_ci/// # use nom::error::{Error, ErrorKind};
896855e09eSopenharmony_ci///
906855e09eSopenharmony_ci/// fn parse(input: (&[u8], usize)) -> IResult<(&[u8], usize), bool> {
916855e09eSopenharmony_ci///     bool(input)
926855e09eSopenharmony_ci/// }
936855e09eSopenharmony_ci///
946855e09eSopenharmony_ci/// assert_eq!(parse(([0b10000000].as_ref(), 0)), Ok((([0b10000000].as_ref(), 1), true)));
956855e09eSopenharmony_ci/// assert_eq!(parse(([0b10000000].as_ref(), 1)), Ok((([0b10000000].as_ref(), 2), false)));
966855e09eSopenharmony_ci/// ```
976855e09eSopenharmony_cipub fn bool<I, E: ParseError<(I, usize)>>(input: (I, usize)) -> IResult<(I, usize), bool, E>
986855e09eSopenharmony_ciwhere
996855e09eSopenharmony_ci  I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
1006855e09eSopenharmony_ci{
1016855e09eSopenharmony_ci  let (res, bit): (_, u32) = take(1usize)(input)?;
1026855e09eSopenharmony_ci  Ok((res, bit != 0))
1036855e09eSopenharmony_ci}
1046855e09eSopenharmony_ci
1056855e09eSopenharmony_ci#[cfg(test)]
1066855e09eSopenharmony_cimod test {
1076855e09eSopenharmony_ci  use super::*;
1086855e09eSopenharmony_ci
1096855e09eSopenharmony_ci  #[test]
1106855e09eSopenharmony_ci  fn test_take_0() {
1116855e09eSopenharmony_ci    let input = [].as_ref();
1126855e09eSopenharmony_ci    let count = 0usize;
1136855e09eSopenharmony_ci    assert_eq!(count, 0usize);
1146855e09eSopenharmony_ci    let offset = 0usize;
1156855e09eSopenharmony_ci
1166855e09eSopenharmony_ci    let result: crate::IResult<(&[u8], usize), usize> = take(count)((input, offset));
1176855e09eSopenharmony_ci
1186855e09eSopenharmony_ci    assert_eq!(result, Ok(((input, offset), 0)));
1196855e09eSopenharmony_ci  }
1206855e09eSopenharmony_ci
1216855e09eSopenharmony_ci  #[test]
1226855e09eSopenharmony_ci  fn test_tag_ok() {
1236855e09eSopenharmony_ci    let input = [0b00011111].as_ref();
1246855e09eSopenharmony_ci    let offset = 0usize;
1256855e09eSopenharmony_ci    let bits_to_take = 4usize;
1266855e09eSopenharmony_ci    let value_to_tag = 0b0001;
1276855e09eSopenharmony_ci
1286855e09eSopenharmony_ci    let result: crate::IResult<(&[u8], usize), usize> =
1296855e09eSopenharmony_ci      tag(value_to_tag, bits_to_take)((input, offset));
1306855e09eSopenharmony_ci
1316855e09eSopenharmony_ci    assert_eq!(result, Ok(((input, bits_to_take), value_to_tag)));
1326855e09eSopenharmony_ci  }
1336855e09eSopenharmony_ci
1346855e09eSopenharmony_ci  #[test]
1356855e09eSopenharmony_ci  fn test_tag_err() {
1366855e09eSopenharmony_ci    let input = [0b00011111].as_ref();
1376855e09eSopenharmony_ci    let offset = 0usize;
1386855e09eSopenharmony_ci    let bits_to_take = 4usize;
1396855e09eSopenharmony_ci    let value_to_tag = 0b1111;
1406855e09eSopenharmony_ci
1416855e09eSopenharmony_ci    let result: crate::IResult<(&[u8], usize), usize> =
1426855e09eSopenharmony_ci      tag(value_to_tag, bits_to_take)((input, offset));
1436855e09eSopenharmony_ci
1446855e09eSopenharmony_ci    assert_eq!(
1456855e09eSopenharmony_ci      result,
1466855e09eSopenharmony_ci      Err(crate::Err::Error(crate::error::Error {
1476855e09eSopenharmony_ci        input: (input, offset),
1486855e09eSopenharmony_ci        code: ErrorKind::TagBits
1496855e09eSopenharmony_ci      }))
1506855e09eSopenharmony_ci    );
1516855e09eSopenharmony_ci  }
1526855e09eSopenharmony_ci
1536855e09eSopenharmony_ci  #[test]
1546855e09eSopenharmony_ci  fn test_bool_0() {
1556855e09eSopenharmony_ci    let input = [0b10000000].as_ref();
1566855e09eSopenharmony_ci
1576855e09eSopenharmony_ci    let result: crate::IResult<(&[u8], usize), bool> = bool((input, 0));
1586855e09eSopenharmony_ci
1596855e09eSopenharmony_ci    assert_eq!(result, Ok(((input, 1), true)));
1606855e09eSopenharmony_ci  }
1616855e09eSopenharmony_ci
1626855e09eSopenharmony_ci  #[test]
1636855e09eSopenharmony_ci  fn test_bool_eof() {
1646855e09eSopenharmony_ci    let input = [0b10000000].as_ref();
1656855e09eSopenharmony_ci
1666855e09eSopenharmony_ci    let result: crate::IResult<(&[u8], usize), bool> = bool((input, 8));
1676855e09eSopenharmony_ci
1686855e09eSopenharmony_ci    assert_eq!(result, Err(crate::Err::Incomplete(Needed::new(1))));
1696855e09eSopenharmony_ci  }
1706855e09eSopenharmony_ci}
171