From: Shivani Bhardwaj Date: Thu, 9 Sep 2021 02:36:51 +0000 (+0530) Subject: rust/conf: add getter for memval X-Git-Tag: suricata-7.0.0-beta1~1372 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0cfe512ef01038e9a088b1cafa17d57bd4331e75;p=thirdparty%2Fsuricata.git rust/conf: add getter for memval Add a parser for memory values like 50kb, 20mb, etc on the Rust side. --- diff --git a/rust/src/conf.rs b/rust/src/conf.rs index dbb98fafe6..e52e53a591 100644 --- a/rust/src/conf.rs +++ b/rust/src/conf.rs @@ -21,6 +21,12 @@ use std::os::raw::c_int; use std::ffi::{CString, CStr}; use std::ptr; use std::str; +use nom::{ + character::complete::{multispace0, not_line_ending}, + sequence::{preceded, tuple}, + number::complete::double, + combinator::verify, +}; extern { fn ConfGet(key: *const c_char, res: *mut *const c_char) -> i8; @@ -127,3 +133,176 @@ impl ConfNode { } } + +const BYTE: u64 = 1; +const KILOBYTE: u64 = 1024; +const MEGABYTE: u64 = 1_048_576; +const GIGABYTE: u64 = 1_073_741_824; + +/// Helper function to retrieve memory unit from a string slice +/// +/// Return value: u64 +/// +/// # Arguments +/// +/// * `unit` - A string slice possibly containing memory unit +fn get_memunit(unit: &str) -> u64 { + let unit = &unit.to_lowercase()[..]; + match unit { + "b" => { BYTE } + "kb" => { KILOBYTE } + "mb" => { MEGABYTE } + "gb" => { GIGABYTE } + _ => { 0 } + } +} + +/// Parses memory units from human readable form to machine readable +/// +/// Return value: +/// Result => Ok(u64) +/// => Err(error string) +/// +/// # Arguments +/// +/// * `arg` - A string slice that holds the value parsed from the config +pub fn get_memval(arg: &str) -> Result { + let arg = arg.trim(); + let val: f64; + let mut unit: &str; + let parser = tuple((preceded(multispace0, double), + preceded(multispace0, verify(not_line_ending, |c: &str| c.len() < 3)))); + let r: nom::IResult<&str, (f64, &str)> = parser(arg); + if let Ok(r) = r { + val = (r.1).0; + unit = (r.1).1; + } else { + return Err("Error parsing the memory value"); + } + if unit.is_empty() { + unit = "B"; + } + let unit = get_memunit(unit) as u64; + if unit == 0 { + return Err("Invalid memory unit"); + } + let res = val * unit as f64; + Ok(res as u64) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_memval_nospace() { + let s = "10"; + let res = 10 ; + assert_eq!(Ok(10), get_memval(s)); + + let s = "10kb"; + assert_eq!(Ok(res * KILOBYTE), get_memval(s)); + + let s = "10Kb"; + assert_eq!(Ok(res * KILOBYTE), get_memval(s)); + + let s = "10KB"; + assert_eq!(Ok(res * KILOBYTE), get_memval(s)); + + let s = "10mb"; + assert_eq!(Ok(res * MEGABYTE), get_memval(s)); + + let s = "10gb"; + assert_eq!(Ok(res * GIGABYTE), get_memval(s)); + } + + #[test] + fn test_memval_space_start() { + let s = " 10"; + let res = 10 ; + assert_eq!(Ok(res), get_memval(s)); + + let s = " 10Kb"; + assert_eq!(Ok(res * KILOBYTE), get_memval(s)); + + let s = " 10mb"; + assert_eq!(Ok(res * MEGABYTE), get_memval(s)); + + let s = " 10Gb"; + assert_eq!(Ok(res * GIGABYTE), get_memval(s)); + + let s = " 30b"; + assert_eq!(Ok(30), get_memval(s)); + } + + #[test] + fn test_memval_space_end() { + let s = " 10 "; + let res = 10 ; + assert_eq!(Ok(res), get_memval(s)); + + let s = "10Kb "; + assert_eq!(Ok(res * KILOBYTE), get_memval(s)); + + let s = "10mb "; + assert_eq!(Ok(res * MEGABYTE), get_memval(s)); + + let s = " 10Gb "; + assert_eq!(Ok(res * GIGABYTE), get_memval(s)); + + let s = " 30b "; + assert_eq!(Ok(30), get_memval(s)); + } + + #[test] + fn test_memval_space_in_bw() { + let s = " 10 "; + let res = 10 ; + assert_eq!(Ok(res), get_memval(s)); + + let s = "10 Kb "; + assert_eq!(Ok(res * KILOBYTE), get_memval(s)); + + let s = "10 mb"; + assert_eq!(Ok(res * MEGABYTE), get_memval(s)); + + let s = " 10 Gb "; + assert_eq!(Ok(res * GIGABYTE), get_memval(s)); + + let s = "30 b"; + assert_eq!(Ok(30), get_memval(s)); + } + + #[test] + fn test_memval_float_val() { + let s = " 10.5 "; + assert_eq!(Ok(10), get_memval(s)); + + let s = "10.8Kb "; + assert_eq!(Ok((10.8 * KILOBYTE as f64) as u64), get_memval(s)); + + let s = "10.4 mb "; + assert_eq!(Ok((10.4 * MEGABYTE as f64) as u64), get_memval(s)); + + let s = " 10.5Gb "; + assert_eq!(Ok((10.5 * GIGABYTE as f64) as u64), get_memval(s)); + + let s = " 30.0 b "; + assert_eq!(Ok(30), get_memval(s)); + } + + #[test] + fn test_memval_erroneous_val() { + let s = "5eb"; + assert_eq!(true, get_memval(s).is_err()); + + let s = "5 1kb"; + assert_eq!(true, get_memval(s).is_err()); + + let s = "61k b"; + assert_eq!(true, get_memval(s).is_err()); + + let s = "8 8 k b"; + assert_eq!(true, get_memval(s).is_err()); + } +}