]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
rust/conf: add getter for memval
authorShivani Bhardwaj <shivanib134@gmail.com>
Thu, 9 Sep 2021 02:36:51 +0000 (08:06 +0530)
committerVictor Julien <victor@inliniac.net>
Tue, 21 Sep 2021 05:21:04 +0000 (07:21 +0200)
Add a parser for memory values like 50kb, 20mb, etc on the Rust side.

rust/src/conf.rs

index dbb98fafe614f3ca278ea3393c177674cb53f662..e52e53a59140b8adeec454afe523224bd5482934 100644 (file)
@@ -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<u64, &'static str> {
+    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());
+    }
+}