/* Copyright (C) 2023 Open Information Security Foundation * * You can copy, redistribute or modify this Program under the terms of * the GNU General Public License version 2 as published by the Free * Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * version 2 along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. */ //! Utility library module for commonly used strings, hexadecimals and other elements. use crate::jsonbuilder::HEX; pub mod nom7 { use nom7::bytes::streaming::{tag, take_until}; use nom7::error::{Error, ParseError}; use nom7::ErrorConvert; use nom7::IResult; /// Reimplementation of `take_until_and_consume` for nom 7 /// /// `take_until` does not consume the matched tag, and /// `take_until_and_consume` was removed in nom 7. This function /// provides an implementation (specialized for `&[u8]`). pub fn take_until_and_consume<'a, E: ParseError<&'a [u8]>>( t: &'a [u8], ) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], &'a [u8], E> { move |i: &'a [u8]| { let (i, res) = take_until(t)(i)?; let (i, _) = tag(t)(i)?; Ok((i, res)) } } /// Specialized version of the nom 7 `bits` combinator /// /// The `bits combinator has trouble inferring the transient error type /// used by the tuple parser, because the function is generic and any /// error type would be valid. /// Use an explicit error type (as described in /// https://docs.rs/nom/7.1.0/nom/bits/fn.bits.html) to solve this problem, and /// specialize this function for `&[u8]`. pub fn bits<'a, O, E, P>(parser: P) -> impl FnMut(&'a [u8]) -> IResult<&'a [u8], O, E> where E: ParseError<&'a [u8]>, Error<(&'a [u8], usize)>: ErrorConvert, P: FnMut((&'a [u8], usize)) -> IResult<(&'a [u8], usize), O, Error<(&'a [u8], usize)>>, { // use full path to disambiguate nom `bits` from this current function name nom7::bits::bits(parser) } } pub mod nom8 { use nom8::bytes::streaming::{tag, take_until}; use nom8::error::{Error, ParseError}; use nom8::ErrorConvert; use nom8::{IResult, Parser}; /// Reimplementation of `take_until_and_consume` for nom 8 /// /// `take_until` does not consume the matched tag, and /// `take_until_and_consume` was removed in nom 7. This function /// provides an implementation (specialized for `&[u8]`). pub fn take_until_and_consume<'a, E: ParseError<&'a [u8]>>( t: &'a [u8], ) -> impl FnMut(&'a [u8]) -> IResult<&'a [u8], &'a [u8], E> { move |i: &'a [u8]| { let (i, res) = take_until(t).parse(i)?; let (i, _) = tag(t).parse(i)?; Ok((i, res)) } } /// Specialized version of the nom 8 `bits` combinator /// /// The `bits combinator has trouble inferring the transient error type /// used by the tuple parser, because the function is generic and any /// error type would be valid. /// Use an explicit error type (as described in /// https://docs.rs/nom/7.1.0/nom/bits/fn.bits.html) to solve this problem, and /// specialize this function for `&[u8]`. pub fn bits<'a, O, E, P>(parser: P) -> impl FnMut(&'a [u8]) -> IResult<&'a [u8], O, E> where E: ParseError<&'a [u8]>, Error<(&'a [u8], usize)>: ErrorConvert, P: FnMut((&'a [u8], usize)) -> IResult<(&'a [u8], usize), O, Error<(&'a [u8], usize)>>, { // use full path to disambiguate nom `bits` from this current function name nom8::bits::bits(parser) } } /// Convert an u8-array of data into a hexadecimal representation pub fn to_hex(input: &[u8]) -> String { return input .iter() .flat_map(|b| { vec![ char::from(HEX[(b >> 4) as usize]), char::from(HEX[(b & 0xf) as usize]), ] }) .collect(); } #[no_mangle] pub unsafe extern "C" fn SCToHex(output: *mut u8, out_len: usize, input: *const u8, in_len: usize) { if out_len < 2 * in_len + 1 { return; } let islice = build_slice!(input, in_len); let oslice = std::slice::from_raw_parts_mut(output, 2 * in_len + 1); // only used from C for i in 0..islice.len() { oslice[2 * i] = HEX[(islice[i] >> 4) as usize]; oslice[2 * i + 1] = HEX[(islice[i] & 0xf) as usize]; } oslice[2 * islice.len()] = 0; } #[no_mangle] pub unsafe extern "C" fn SCToHex_sep( output: *mut u8, out_len: usize, sep: u8, input: *const u8, in_len: usize, ) { if out_len < 3 * in_len { return; } let islice = build_slice!(input, in_len); let oslice = std::slice::from_raw_parts_mut(output, 3 * in_len); // only used from C for i in 0..islice.len() { oslice[3 * i] = HEX[(islice[i] >> 4) as usize]; oslice[3 * i + 1] = HEX[(islice[i] & 0xf) as usize]; oslice[3 * i + 2] = sep; } // overwrites last separator with final null char oslice[3 * islice.len() - 1] = 0; }