aboutsummaryrefslogtreecommitdiff
path: root/rustables/src/expr/immediate.rs
diff options
context:
space:
mode:
Diffstat (limited to 'rustables/src/expr/immediate.rs')
-rw-r--r--rustables/src/expr/immediate.rs38
1 files changed, 37 insertions, 1 deletions
diff --git a/rustables/src/expr/immediate.rs b/rustables/src/expr/immediate.rs
index 15eb452..e8823b1 100644
--- a/rustables/src/expr/immediate.rs
+++ b/rustables/src/expr/immediate.rs
@@ -18,11 +18,47 @@ impl<T> Immediate<T> {
}
}
-impl<T> Expression for Immediate<T> {
+// The Copy requirement is present to allow us to dereference the newly created raw pointer in `from_expr`
+impl<T: Copy> Expression for Immediate<T> {
fn get_raw_name() -> *const c_char {
b"immediate\0" as *const _ as *const c_char
}
+ fn from_expr(expr: *const sys::nftnl_expr) -> Option<Self>
+ where
+ Self: Sized,
+ {
+ unsafe {
+ let ref_len = std::mem::size_of::<T>() as u32;
+ let mut data_len = 0;
+ let data = sys::nftnl_expr_get(
+ expr,
+ sys::NFTNL_EXPR_IMM_DATA as u16,
+ &mut data_len as *mut u32,
+ );
+
+ if data.is_null() {
+ return None;
+ } else if data_len != ref_len {
+ debug!("Invalid size requested for deserializing an 'immediate' expression: expected {} bytes, got {}", ref_len, data_len);
+ return None;
+ }
+
+ // Warning: this is *very* dangerous safety wise if the user supply us with
+ // a type that have the same size as T but a different memory layout.
+ // Is there a better way? And if there isn't, shouldn't we gate this behind
+ // an "unsafe" boundary?
+ let data = *(data as *const T);
+
+ let register = Register::from_raw(sys::nftnl_expr_get_u32(
+ expr,
+ sys::NFTNL_EXPR_IMM_DREG as u16,
+ ));
+
+ register.map(|register| Immediate { data, register })
+ }
+ }
+
fn to_expr(&self, _rule: &Rule) -> *mut sys::nftnl_expr {
unsafe {
let expr = try_alloc!(sys::nftnl_expr_alloc(Self::get_raw_name()));