about summary refs log tree commit diff
path: root/parrot_module/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'parrot_module/src/lib.rs')
-rw-r--r--parrot_module/src/lib.rs57
1 files changed, 57 insertions, 0 deletions
diff --git a/parrot_module/src/lib.rs b/parrot_module/src/lib.rs
new file mode 100644
index 0000000..148f41d
--- /dev/null
+++ b/parrot_module/src/lib.rs
@@ -0,0 +1,57 @@
+use std::ffi::{self, CStr, CString};
+
+#[repr(C)]
+struct ModuleRequest<'req> {
+	headers_len: ffi::c_ulong,
+	headers: &'req [[*const ffi::c_char; 2]],
+	body_len: ffi::c_ulong,
+	body: *const u8,
+}
+
+#[repr(C)]
+struct ModuleResponse {
+	status: ffi::c_ushort,
+	headers_len: ffi::c_ulong,
+	headers: &'static [[*const ffi::c_char; 2]],
+	body_len: ffi::c_ulong,
+	body: *const u8,
+}
+
+const HEADERS: &'static [[*const ffi::c_char; 2]] =
+	&[[c"Content-Type".as_ptr(), c"text/plain".as_ptr()]];
+
+#[unsafe(no_mangle)]
+extern "C" fn handle(req: *const ModuleRequest) -> *const ModuleResponse {
+	let mut ret = String::new();
+
+	// unwrap is bad here
+	let reqref = unsafe { req.as_ref() }.unwrap();
+
+	for idx in 0..reqref.headers_len {
+		let kvarr = reqref.headers[idx as usize];
+		let k = unsafe { CStr::from_ptr(kvarr[0]) }.to_string_lossy();
+		let v = unsafe { CStr::from_ptr(kvarr[1]) }.to_string_lossy();
+		ret.push_str(&format!("{k}: {v}\n"));
+	}
+
+	let body = CString::new(ret).unwrap();
+
+	let resp = ModuleResponse {
+		status: 200,
+		headers_len: 1,
+		headers: HEADERS,
+		body_len: body.as_bytes().len() as u64,
+		body: body.into_raw() as *const u8,
+	};
+
+	let boxed = Box::new(resp);
+
+	Box::<ModuleResponse>::into_raw(boxed)
+}
+
+#[unsafe(no_mangle)]
+extern "C" fn free(req: *const ModuleResponse) {
+	// from_raw what we need to here so that these get dropped
+	let boxed = unsafe { Box::from_raw(req as *mut ModuleResponse) };
+	let body = unsafe { CString::from_raw(boxed.body as *mut i8) };
+}