1//! Bit level parsers 2//! 3 4use crate::error::{ErrorKind, ParseError}; 5use crate::internal::{Err, IResult, Needed}; 6use crate::lib::std::ops::{AddAssign, Div, RangeFrom, Shl, Shr}; 7use crate::traits::{InputIter, InputLength, Slice, ToUsize}; 8 9/// Generates a parser taking `count` bits 10pub fn take<I, O, C, E: ParseError<(I, usize)>>( 11 count: C, 12) -> impl Fn((I, usize)) -> IResult<(I, usize), O, E> 13where 14 I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength, 15 C: ToUsize, 16 O: From<u8> + AddAssign + Shl<usize, Output = O> + Shr<usize, Output = O>, 17{ 18 let count = count.to_usize(); 19 move |(input, bit_offset): (I, usize)| { 20 if count == 0 { 21 Ok(((input, bit_offset), 0u8.into())) 22 } else { 23 let cnt = (count + bit_offset).div(8); 24 if input.input_len() * 8 < count + bit_offset { 25 Err(Err::Incomplete(Needed::new(count as usize))) 26 } else { 27 let mut acc: O = 0_u8.into(); 28 let mut offset: usize = bit_offset; 29 let mut remaining: usize = count; 30 let mut end_offset: usize = 0; 31 32 for byte in input.iter_elements().take(cnt + 1) { 33 if remaining == 0 { 34 break; 35 } 36 let val: O = if offset == 0 { 37 byte.into() 38 } else { 39 ((byte << offset) as u8 >> offset).into() 40 }; 41 42 if remaining < 8 - offset { 43 acc += val >> (8 - offset - remaining); 44 end_offset = remaining + offset; 45 break; 46 } else { 47 acc += val << (remaining - (8 - offset)); 48 remaining -= 8 - offset; 49 offset = 0; 50 } 51 } 52 Ok(((input.slice(cnt..), end_offset), acc)) 53 } 54 } 55 } 56} 57 58/// Generates a parser taking `count` bits and comparing them to `pattern` 59pub fn tag<I, O, C, E: ParseError<(I, usize)>>( 60 pattern: O, 61 count: C, 62) -> impl Fn((I, usize)) -> IResult<(I, usize), O, E> 63where 64 I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + Clone, 65 C: ToUsize, 66 O: From<u8> + AddAssign + Shl<usize, Output = O> + Shr<usize, Output = O> + PartialEq, 67{ 68 let count = count.to_usize(); 69 move |input: (I, usize)| { 70 let inp = input.clone(); 71 72 take(count)(input).and_then(|(i, o)| { 73 if pattern == o { 74 Ok((i, o)) 75 } else { 76 Err(Err::Error(error_position!(inp, ErrorKind::TagBits))) 77 } 78 }) 79 } 80} 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/// ``` 97pub fn bool<I, E: ParseError<(I, usize)>>(input: (I, usize)) -> IResult<(I, usize), bool, E> 98where 99 I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength, 100{ 101 let (res, bit): (_, u32) = take(1usize)(input)?; 102 Ok((res, bit != 0)) 103} 104 105#[cfg(test)] 106mod 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} 171