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}