1use std::{ffi::CString, ptr::null};
2
3#[derive(Debug, Eq, PartialEq, Hash, Clone)]
4pub enum ObsString {
5 Static(&'static str),
6 Dynamic(CString),
7}
8
9impl ObsString {
10 pub const unsafe fn from_nul_terminted_str(string: &'static str) -> Self {
14 Self::Static(string)
15 }
16
17 pub fn as_str(&self) -> &str {
18 match self {
19 Self::Static(s) => s,
20 Self::Dynamic(s) => s.as_c_str().to_str().unwrap(),
21 }
22 }
23
24 pub fn as_ptr(&self) -> *const std::os::raw::c_char {
25 match self {
26 Self::Static(s) => (*s).as_ptr() as *const std::os::raw::c_char,
27 Self::Dynamic(s) => s.as_ptr(),
28 }
29 }
30
31 pub fn ptr_or_null(opt: &Option<Self>) -> *const std::os::raw::c_char {
32 opt.as_ref().map(|s| s.as_ptr()).unwrap_or(null())
33 }
34}
35
36impl<T: Into<Vec<u8>>> From<T> for ObsString {
37 fn from(s: T) -> Self {
38 Self::Dynamic(CString::new(s).expect("Failed to convert to CString"))
39 }
40}
41
42#[macro_export]
43macro_rules! obs_string {
44 ($e:expr) => {
45 unsafe { $crate::string::ObsString::from_nul_terminted_str(concat!($e, "\0")) }
46 };
47}