use crate::{raw, AtmiCtx, NstdError, NstdResult};
use core::ffi::{c_char, c_int};
use std::{
ffi::{CStr, CString},
ptr,
};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct NdrxStdCfgStr {
pub key: String,
pub value: Option<String>,
}
impl AtmiCtx {
pub fn ndrx_stdcfgstr_parse(&self, input: &str) -> NstdResult<Vec<NdrxStdCfgStr>> {
let input_c =
CString::new(input).map_err(|_| NstdError::new(0, "input contains NUL byte"))?;
let mut parsed: *mut raw::ndrx_stdcfgstr_t = ptr::null_mut();
let rc = unsafe { raw::ndrx_stdcfgstr_parse(input_c.as_ptr(), &mut parsed) };
if rc != raw::EXSUCCEED as c_int {
return Err(self.nstd_last_error());
}
let result = unsafe { collect_entries(parsed) };
unsafe { raw::ndrx_stdcfgstr_free(parsed) };
Ok(result)
}
}
unsafe fn collect_entries(head: *mut raw::ndrx_stdcfgstr_t) -> Vec<NdrxStdCfgStr> {
let mut out = Vec::new();
let mut cur = head;
while !cur.is_null() {
let node = &*cur;
out.push(NdrxStdCfgStr {
key: c_array_to_string(&node.key),
value: c_ptr_to_string(node.value),
});
cur = node.next;
}
out
}
fn c_array_to_string(src: &[c_char]) -> String {
let len = src.iter().position(|&b| b == 0).unwrap_or(src.len());
let bytes = unsafe { std::slice::from_raw_parts(src.as_ptr() as *const u8, len) };
String::from_utf8_lossy(bytes).into_owned()
}
unsafe fn c_ptr_to_string(p: *const c_char) -> Option<String> {
if p.is_null() {
None
} else {
Some(CStr::from_ptr(p).to_string_lossy().into_owned())
}
}