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}