2024-02-16 09:59:51 +01:00
|
|
|
use anyhow::{bail, Result};
|
|
|
|
|
use nix_c_raw as raw;
|
|
|
|
|
use std::ptr::null_mut;
|
|
|
|
|
use std::ptr::NonNull;
|
|
|
|
|
|
|
|
|
|
pub struct Context {
|
2024-05-09 12:29:32 -04:00
|
|
|
inner: NonNull<raw::c_context>,
|
2024-02-16 09:59:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Context {
|
|
|
|
|
pub fn new() -> Self {
|
2024-05-09 12:29:32 -04:00
|
|
|
let ctx = unsafe { raw::c_context_create() };
|
2024-02-16 09:59:51 +01:00
|
|
|
if ctx.is_null() {
|
2024-05-09 12:41:34 -04:00
|
|
|
// We've failed to allocate a (relatively small) Context struct.
|
|
|
|
|
// We're almost certainly going to crash anyways.
|
2024-02-16 09:59:51 +01:00
|
|
|
panic!("nix_c_context_create returned a null pointer");
|
|
|
|
|
}
|
|
|
|
|
let ctx = Context {
|
|
|
|
|
inner: NonNull::new(ctx).unwrap(),
|
|
|
|
|
};
|
|
|
|
|
ctx
|
|
|
|
|
}
|
2024-05-09 12:29:32 -04:00
|
|
|
pub fn ptr(&self) -> *mut raw::c_context {
|
2024-02-16 09:59:51 +01:00
|
|
|
self.inner.as_ptr()
|
|
|
|
|
}
|
|
|
|
|
pub fn check_err(&self) -> Result<()> {
|
2024-05-09 12:29:32 -04:00
|
|
|
let err = unsafe { raw::err_code(self.inner.as_ptr()) };
|
2024-02-16 09:59:51 +01:00
|
|
|
if err != raw::NIX_OK.try_into().unwrap() {
|
2024-05-09 12:41:34 -04:00
|
|
|
// msgp is a borrowed pointer (pointing into the context), so we don't need to free it
|
2024-05-09 12:29:32 -04:00
|
|
|
let msgp = unsafe { raw::err_msg(null_mut(), self.inner.as_ptr(), null_mut()) };
|
2024-02-16 09:59:51 +01:00
|
|
|
// Turn the i8 pointer into a Rust string by copying
|
|
|
|
|
let msg: &str = unsafe { core::ffi::CStr::from_ptr(msgp).to_str()? };
|
|
|
|
|
bail!("{}", msg);
|
|
|
|
|
}
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Drop for Context {
|
|
|
|
|
fn drop(&mut self) {
|
|
|
|
|
unsafe {
|
2024-05-09 12:29:32 -04:00
|
|
|
raw::c_context_free(self.inner.as_ptr());
|
2024-02-16 09:59:51 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
|
mod tests {
|
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn context_new_and_drop() {
|
|
|
|
|
// don't crash
|
|
|
|
|
let _c = Context::new();
|
|
|
|
|
}
|
|
|
|
|
}
|