Skip to main content

cue_rs/
ctx.rs

1//! CUE evaluation context, wrapping the `cue_ctx` handle from libcue.
2
3use crate::{drop, error::Error};
4
5/// Opaque handle to a libcue context (`cue_ctx` = `uintptr_t`).
6type CueCtxHandle = usize;
7
8unsafe extern "C" {
9    /// Creates a new CUE evaluation context and returns an opaque handle.
10    /// Returns 0 on failure.
11    fn cue_newctx() -> CueCtxHandle;
12}
13
14/// A CUE evaluation context backed by a libcue `cue_ctx` handle.
15///
16/// This is the entry point for all CUE operations. Obtain one via
17/// [`Ctx::new`]; the underlying context is freed automatically when this
18/// value is dropped.
19pub struct Ctx(CueCtxHandle);
20
21impl Drop for Ctx {
22    /// Frees the underlying libcue context via `cue_free`.
23    fn drop(&mut self) {
24        unsafe { drop::cue_free(self.0) }
25    }
26}
27
28impl Ctx {
29    /// Returns the raw libcue context handle.
30    pub(crate) fn handle(&self) -> usize {
31        self.0
32    }
33
34    /// Creates a new CUE evaluation context.
35    ///
36    /// Calls `cue_newctx` from libcue and wraps the returned handle.
37    ///
38    /// # Errors
39    ///
40    /// Returns [`Error::ContextCreationFailed`] if `cue_newctx` returns 0,
41    /// indicating that the libcue runtime could not allocate a context.
42    pub fn new() -> Result<Self, Error> {
43        let handle = unsafe { cue_newctx() };
44        if handle == 0 {
45            return Err(Error::ContextCreationFailed);
46        }
47        Ok(Self(handle))
48    }
49}
50
51#[cfg(test)]
52mod tests {
53    use super::Ctx;
54
55    #[test]
56    fn test_new_succeeds() {
57        assert!(Ctx::new().is_ok());
58    }
59}