From 55a41414b87301e37d9dc35937694d5aa13d9d99 Mon Sep 17 00:00:00 2001 From: Andrew Clayton Date: Thu, 24 Aug 2023 20:03:25 +0100 Subject: Rust: Add a nicer wrapper around the libunit-wasm bindings This adds a nice wrapper (aka rusty) around the generated libunit-wasm bindings. This should provide a more native rust like experience with the following benefits - No casting. So no things like 'as *mut c_void' - Native rust strings. So no things like '.as_ptr() as *const c_char' - Better ctx initialisation. Filed initialisation is now hidden away - Great reduction in the amount of unsafe {} blocks required - Generally more compact There are also some new macros - C2S!() converts a CStr to a Str - S2C!() converts a formatted Str to a Cstr using format!() - uwr_write_str!() a wrapper around luw_mem_writep_data and format!() This wrapper uses a uwr (Unit Wasm Rust) prefix under a 'rusty' namespace. The luw_http_hdr_iter() function proved tricky to wrap and the callback function still takes C style arguments due to the fact that this function is called from the libunit-wasm C library. The provided wrapper simply means we can use this without having to use an unsafe {} block around it in application code. Similarly with other functions that technically didn't need to be wrapped, wrapping them means that the unsafe {} blocks are hidden away. Signed-off-by: Andrew Clayton --- src/rust/src/lib.rs | 1 + src/rust/src/rusty/mod.rs | 3 + src/rust/unit-wasm-sys/lib.rs | 2 + src/rust/unit-wasm-sys/macros.rs | 5 + src/rust/unit-wasm-sys/rusty.rs | 214 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 225 insertions(+) create mode 100644 src/rust/src/rusty/mod.rs create mode 100644 src/rust/unit-wasm-sys/rusty.rs (limited to 'src') diff --git a/src/rust/src/lib.rs b/src/rust/src/lib.rs index dface32..2b17728 100644 --- a/src/rust/src/lib.rs +++ b/src/rust/src/lib.rs @@ -6,3 +6,4 @@ */ pub mod ffi; +pub mod rusty; diff --git a/src/rust/src/rusty/mod.rs b/src/rust/src/rusty/mod.rs new file mode 100644 index 0000000..087148a --- /dev/null +++ b/src/rust/src/rusty/mod.rs @@ -0,0 +1,3 @@ +// @todo: Check if this is valid?! +extern crate unit_wasm_sys; +pub use self::unit_wasm_sys::*; diff --git a/src/rust/unit-wasm-sys/lib.rs b/src/rust/unit-wasm-sys/lib.rs index 42d5981..81cd464 100644 --- a/src/rust/unit-wasm-sys/lib.rs +++ b/src/rust/unit-wasm-sys/lib.rs @@ -9,9 +9,11 @@ mod bindings { #![allow(non_upper_case_globals)] #![allow(non_camel_case_types)] + #![allow(non_snake_case)] include!(concat!(env!("OUT_DIR"), "/bindings.rs")); include!("macros.rs"); + include!("rusty.rs"); } #[doc(no_inline)] diff --git a/src/rust/unit-wasm-sys/macros.rs b/src/rust/unit-wasm-sys/macros.rs index d7fde22..059fef3 100644 --- a/src/rust/unit-wasm-sys/macros.rs +++ b/src/rust/unit-wasm-sys/macros.rs @@ -13,3 +13,8 @@ pub const LUW_VERSION_NUMBER: i32 = (LUW_VERSION_MAJOR << 24) | (LUW_VERSION_MINOR << 16) | (LUW_VERSION_PATCH << 8); + +pub const LUW_SRB_NONE: u32 = luw_srb_flags_t_LUW_SRB_NONE; +pub const LUW_SRB_APPEND: u32 = luw_srb_flags_t_LUW_SRB_APPEND; +pub const LUW_SRB_ALLOC: u32 = luw_srb_flags_t_LUW_SRB_ALLOC; +pub const LUW_SRB_FULL_SIZE: u32 = luw_srb_flags_t_LUW_SRB_FLAGS_ALL; diff --git a/src/rust/unit-wasm-sys/rusty.rs b/src/rust/unit-wasm-sys/rusty.rs new file mode 100644 index 0000000..79c38f3 --- /dev/null +++ b/src/rust/unit-wasm-sys/rusty.rs @@ -0,0 +1,214 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +/* + * Copyright (C) Andrew Clayton + * Copyright (C) F5, Inc. + */ + +use std::ffi::c_char; +use std::ffi::c_void; +use std::ffi::CStr; +use std::ptr::null_mut; + +#[macro_export] +macro_rules! C2S { + ($a:expr) => {{ + unsafe { CStr::from_ptr($a).to_str().unwrap() } + }}; +} + +#[macro_export] +macro_rules! S2C { + ($a:expr) => {{ + format!("{}\0", $a) + }}; +} + +#[macro_export] +macro_rules! uwr_write_str{ + ($a:expr, $($arg:tt)*) => { + { + uwr_mem_write_str($a, &format!($($arg)*)) + } +}} + +pub const fn UWR_CTX_INITIALIZER() -> luw_ctx_t { + luw_ctx_t { + addr: null_mut(), + mem: null_mut(), + req: null_mut(), + resp: null_mut(), + resp_hdr: null_mut(), + resp_offset: 0, + req_buf: null_mut(), + hdrp: null_mut(), + reqp: null_mut(), + } +} + +pub fn uwr_init_ctx(ctx: *mut luw_ctx_t, addr: *mut u8, offset: usize) { + unsafe { + luw_init_ctx(ctx, addr, offset); + } +} + +pub fn uwr_set_req_buf( + ctx: *mut luw_ctx_t, + buf: *mut *mut u8, + flags: u32, +) -> i32 { + unsafe { luw_set_req_buf(ctx, buf, flags) } +} + +pub fn uwr_get_http_path(ctx: *mut luw_ctx_t) -> &'static str { + C2S!(luw_get_http_path(ctx)) +} + +pub fn uwr_get_http_method(ctx: *mut luw_ctx_t) -> &'static str { + C2S!(luw_get_http_method(ctx)) +} + +pub fn uwr_get_http_version(ctx: *mut luw_ctx_t) -> &'static str { + C2S!(luw_get_http_version(ctx)) +} + +pub fn uwr_get_http_query(ctx: *mut luw_ctx_t) -> &'static str { + C2S!(luw_get_http_query(ctx)) +} + +pub fn uwr_get_http_remote(ctx: *mut luw_ctx_t) -> &'static str { + C2S!(luw_get_http_remote(ctx)) +} + +pub fn uwr_get_http_local_addr(ctx: *mut luw_ctx_t) -> &'static str { + C2S!(luw_get_http_local_addr(ctx)) +} + +pub fn uwr_get_http_local_port(ctx: *mut luw_ctx_t) -> &'static str { + C2S!(luw_get_http_local_port(ctx)) +} + +pub fn uwr_get_http_server_name(ctx: *mut luw_ctx_t) -> &'static str { + C2S!(luw_get_http_server_name(ctx)) +} + +pub fn uwr_get_http_content(ctx: *const luw_ctx_t) -> *const u8 { + unsafe { luw_get_http_content(ctx) } +} + +pub fn uwr_get_http_content_len(ctx: *const luw_ctx_t) -> usize { + unsafe { luw_get_http_content_len(ctx) } +} + +pub fn uwr_get_http_content_sent(ctx: *const luw_ctx_t) -> usize { + unsafe { luw_get_http_content_sent(ctx) } +} + +pub fn uwr_http_is_tls(ctx: *const luw_ctx_t) -> bool { + unsafe { luw_http_is_tls(ctx) } +} + +pub fn uwr_http_hdr_iter( + ctx: *mut luw_ctx_t, + luw_http_hdr_iter_func: ::std::option::Option< + unsafe extern "C" fn( + ctx: *mut luw_ctx_t, + name: *const c_char, + value: *const c_char, + data: *mut c_void, + ) -> bool, + >, + user_data: *mut c_void, +) { + unsafe { luw_http_hdr_iter(ctx, luw_http_hdr_iter_func, user_data) } +} + +pub fn uwr_http_hdr_get_value(ctx: *mut luw_ctx_t, hdr: &str) -> &'static str { + C2S!(luw_http_hdr_get_value(ctx, S2C!(hdr).as_ptr() as *const i8)) +} + +pub fn uwr_get_response_data_size(ctx: *const luw_ctx_t) -> usize { + unsafe { luw_get_response_data_size(ctx) } +} + +pub fn uwr_mem_write_str(ctx: *mut luw_ctx_t, src: &str) -> usize { + unsafe { luw_mem_writep_data(ctx, src.as_ptr(), src.len()) } +} + +pub fn uwr_mem_write_buf( + ctx: *mut luw_ctx_t, + src: *const u8, + size: usize, +) -> usize { + unsafe { luw_mem_writep_data(ctx, src, size) } +} + +pub fn uwr_req_buf_append(ctx: *mut luw_ctx_t, src: *const u8) { + unsafe { + luw_req_buf_append(ctx, src); + } +} + +pub fn uwr_mem_fill_buf_from_req(ctx: *mut luw_ctx_t, from: usize) -> usize { + unsafe { luw_mem_fill_buf_from_req(ctx, from) } +} + +pub fn uwr_luw_mem_reset(ctx: *mut luw_ctx_t) { + unsafe { + luw_mem_reset(ctx); + } +} + +pub fn uwr_http_send_response(ctx: *const luw_ctx_t) { + unsafe { + luw_http_send_response(ctx); + } +} + +pub fn uwr_http_init_headers(ctx: *mut luw_ctx_t, nr: usize, offset: usize) { + unsafe { + luw_http_init_headers(ctx, nr, offset); + } +} + +pub fn uwr_http_add_header( + ctx: *mut luw_ctx_t, + idx: u16, + name: &str, + value: &str, +) { + unsafe { + luw_http_add_header( + ctx, + idx, + S2C!(name).as_ptr() as *const i8, + S2C!(value).as_ptr() as *const i8, + ); + } +} + +pub fn uwr_http_send_headers(ctx: *const luw_ctx_t) { + unsafe { + luw_http_send_headers(ctx); + } +} + +pub fn uwr_http_response_end() { + unsafe { + luw_http_response_end(); + } +} + +pub fn uwr_mem_get_init_size() -> u32 { + unsafe { luw_mem_get_init_size() } +} + +pub fn uwr_malloc(size: u32) -> *mut u8 { + unsafe { luw_malloc(size as usize) as *mut u8 } +} + +pub fn uwr_free(ptr: *mut u8) { + unsafe { + luw_free(ptr as *mut c_void); + } +} -- cgit