Skip to main content

cpdb_sys/
common.rs

1//! Library-wide entry points: version query, one-shot initialisation,
2//! and the small set of path/config helpers cpdb-libs ships.
3
4use super::bindings as ffi;
5use super::util;
6use crate::error::{CpdbError, Result};
7use std::ffi::CString;
8
9/// Returns the version of the linked cpdb-libs C library.
10pub fn version() -> Result<String> {
11    // SAFETY: `cpdbGetVersion` returns a borrowed static `const char *`.
12    let raw = unsafe { ffi::cpdbGetVersion() };
13    if raw.is_null() {
14        return Err(CpdbError::NullPointer);
15    }
16    unsafe { util::cstr_to_string(raw) }
17}
18
19/// Initialises cpdb-libs.
20///
21/// Idempotent — safe to call multiple times. Call once at process startup
22/// before any other cpdb-rs API.
23pub fn init() {
24    // SAFETY: `cpdbInit` takes no arguments and is documented as
25    // idempotent.
26    unsafe { ffi::cpdbInit() };
27}
28
29// ─── Path / config helpers ───────────────────────────────────────────────────
30
31/// Returns the user-scope configuration directory cpdb-libs uses for
32/// persisted settings.
33pub fn user_config_dir() -> Result<String> {
34    // SAFETY: returns a `g_strdup`'d string we own.
35    unsafe { util::cstr_to_string_and_g_free(ffi::cpdbGetUserConfDir()) }
36}
37
38/// Returns the system-scope configuration directory cpdb-libs uses for
39/// shared settings.
40pub fn system_config_dir() -> Result<String> {
41    // SAFETY: returns a `g_strdup`'d string we own.
42    unsafe { util::cstr_to_string_and_g_free(ffi::cpdbGetSysConfDir()) }
43}
44
45/// Resolves `path` to an absolute path, expanding `~` and relative
46/// segments according to cpdb-libs' rules.
47pub fn absolute_path(path: &str) -> Result<String> {
48    let c_path = CString::new(path)?;
49    // SAFETY: returns a `g_strdup`'d string we own.
50    unsafe { util::cstr_to_string_and_g_free(ffi::cpdbGetAbsolutePath(c_path.as_ptr())) }
51}
52
53/// Concatenates two strings with a separator (cpdb-libs convention).
54pub fn concat_sep(left: &str, right: &str) -> Result<String> {
55    let l = CString::new(left)?;
56    let r = CString::new(right)?;
57    // SAFETY: returns a `g_strdup`'d string we own.
58    unsafe { util::cstr_to_string_and_g_free(ffi::cpdbConcatSep(l.as_ptr(), r.as_ptr())) }
59}
60
61/// Concatenates two path segments (cpdb-libs convention).
62pub fn concat_path(parent: &str, child: &str) -> Result<String> {
63    let p = CString::new(parent)?;
64    let c = CString::new(child)?;
65    // SAFETY: returns a `g_strdup`'d string we own.
66    unsafe { util::cstr_to_string_and_g_free(ffi::cpdbConcatPath(p.as_ptr(), c.as_ptr())) }
67}
68
69/// Returns the standard IPP group name for `option_name`, or `None` when
70/// the option is not in cpdb-libs' built-in mapping.
71pub fn option_group(option_name: &str) -> Result<Option<String>> {
72    let c_opt = CString::new(option_name)?;
73    // SAFETY: returns a `g_strdup`'d string we own; null indicates "not mapped".
74    let raw = unsafe { ffi::cpdbGetGroup(c_opt.as_ptr()) };
75    if raw.is_null() {
76        Ok(None)
77    } else {
78        unsafe { util::cstr_to_string_and_g_free(raw) }.map(Some)
79    }
80}