missdemeanor/
lib.rs

1extern crate libc;
2extern crate serde_json;
3
4use std::collections::HashMap;
5use std::error::Error;
6use std::ffi::CString;
7use std::ptr;
8use std::str;
9
10use serde_json::{Map, Value};
11
12pub struct CRequest {
13    pub method: CString,
14    pub uri: CString,
15    pub headers: HashMap<CString, CString>,
16    pub body: CString,
17}
18
19impl CRequest {
20    pub fn get_method(&self) -> Result<&str, str::Utf8Error> {
21        self.method.to_str()
22    }
23
24    pub fn get_uri(&self) -> Result<&str, str::Utf8Error> {
25        self.uri.to_str()
26    }
27
28    pub fn get_header(&self, key: &str) -> Option<&str> {
29        let key_cstring = match CString::new(key.as_bytes()) {
30            Ok(cs) => cs,
31            Err(_) => return None,
32        };
33        self.headers.get(&key_cstring).and_then(|v| v.to_str().ok())
34    }
35
36    pub fn get_headers(&self) -> Result<String, Box<dyn Error>> {
37        let mut map = Map::<String, Value>::new();
38        for (key, value) in self.headers.iter() {
39            map.insert(
40                key.to_str()?.to_string(),
41                Value::from(value.to_str()?.to_string()),
42            );
43        }
44        Ok(serde_json::to_string(&map)?)
45    }
46
47    pub fn get_body(&self) -> Result<&str, str::Utf8Error> {
48        self.body.to_str()
49    }
50}
51
52/// # Safety
53///
54/// Safe when used with a request generated by Miss Demeanor only
55#[allow(dead_code)]
56#[no_mangle]
57pub unsafe extern "C" fn request_get_method(req: *const CRequest) -> *const libc::c_char {
58    let request = match req.as_ref() {
59        Some(r) => r,
60        None => {
61            return ptr::null();
62        }
63    };
64    request.method.as_ptr()
65}
66
67/// # Safety
68///
69/// Safe when used with a request generated by Miss Demeanor only
70#[allow(dead_code)]
71#[no_mangle]
72pub unsafe extern "C" fn request_get_uri(req: *const CRequest) -> *const libc::c_char {
73    let request = match req.as_ref() {
74        Some(r) => r,
75        None => {
76            return ptr::null();
77        }
78    };
79    request.uri.as_ptr()
80}
81
82/// # Safety
83///
84/// Safe when used with a request generated by Miss Demeanor and
85/// a null terminated string for `key` only
86#[allow(dead_code)]
87#[no_mangle]
88pub unsafe extern "C" fn request_get_header(
89    req: *const CRequest,
90    key: *mut libc::c_char,
91) -> *const libc::c_char {
92    let request = match req.as_ref() {
93        Some(r) => r,
94        None => {
95            return ptr::null();
96        }
97    };
98    let cstring = CString::from_raw(key);
99    let header = match request.headers.get(&cstring) {
100        Some(h) => h,
101        None => {
102            return ptr::null();
103        }
104    };
105    header.as_ptr()
106}
107
108/// # Safety
109///
110/// Safe when used with a request generated by Miss Demeanor only
111#[allow(dead_code)]
112#[no_mangle]
113pub unsafe extern "C" fn request_get_body(req: *const CRequest) -> *const libc::c_char {
114    let request = match req.as_ref() {
115        Some(r) => r,
116        None => {
117            return ptr::null();
118        }
119    };
120    request.body.as_ptr()
121}