aboutsummaryrefslogtreecommitdiff
path: root/src/expr/wrapper.rs
blob: 12ef60b4617ec4af14ac1ac97575172b7757057d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
use std::ffi::CStr;
use std::ffi::CString;
use std::fmt::Debug;
use std::rc::Rc;
use std::os::raw::c_char;

use super::{DeserializationError, Expression};
use crate::{sys, Rule};

pub struct ExpressionWrapper {
    pub(crate) expr: *const sys::nftnl_expr,
    // we also need the rule here to ensure that the rule lives as long as the `expr` pointer
    #[allow(dead_code)]
    pub(crate) rule: Rc<Rule>,
}

impl Debug for ExpressionWrapper {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{:?}", self.get_str())
    }
}

impl ExpressionWrapper {
    /// Retrieves a textual description of the expression.
    pub fn get_str(&self) -> CString {
        let mut descr_buf = vec![0i8; 4096];
        unsafe {
            sys::nftnl_expr_snprintf(
                descr_buf.as_mut_ptr() as *mut c_char,
                (descr_buf.len() - 1) as u64,
                self.expr,
                sys::NFTNL_OUTPUT_DEFAULT,
                0,
            );
            CStr::from_ptr(descr_buf.as_ptr() as *mut c_char).to_owned()
        }
    }

    /// Retrieves the type of expression ("log", "counter", ...).
    pub fn get_kind(&self) -> Option<&CStr> {
        unsafe {
            let ptr = sys::nftnl_expr_get_str(self.expr, sys::NFTNL_EXPR_NAME as u16);
            if !ptr.is_null() {
                Some(CStr::from_ptr(ptr))
            } else {
                None
            }
        }
    }

    /// Attempts to decode the expression as the type T.
    pub fn decode_expr<T: Expression>(&self) -> Result<T, DeserializationError> {
        if let Some(kind) = self.get_kind() {
            let raw_name = unsafe { CStr::from_ptr(T::get_raw_name()) };
            if kind == raw_name {
                return T::from_expr(self.expr);
            }
        }
        Err(DeserializationError::InvalidExpressionKind)
    }
}