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