Skip to main content

libobs_wrapper\utils/
path.rs

1use std::{
2    env,
3    path::{Path, PathBuf},
4};
5
6use super::ObsString;
7
8/// Builds into an `ObsString` that represents a path used
9/// by libobs.
10///
11/// Note that only this path only supports UTF-8 for the
12/// entire absolute path because libobs only supports
13/// UTF-8.
14#[derive(Clone, Default, Debug, PartialEq, Eq, PartialOrd, Ord)]
15pub struct ObsPath {
16    path: PathBuf,
17}
18
19impl ObsPath {
20    /// Creates a new `ObsPath` strictly using the path
21    /// `path_str` without any modifications.
22    ///
23    /// If you want to create a relative path, use
24    /// `ObsPath::from_relative`.
25    pub fn new(path_str: &str) -> Self {
26        Self {
27            path: Path::new(path_str).into(),
28        }
29    }
30
31    /// Creates a new `ObsPath` with `path_str`
32    /// appended to the path of the directory which the
33    /// executable file is in.
34    ///
35    /// If you want to create an absolute path, use
36    /// `ObsPath::new`.
37    pub fn from_relative(path_str: &str) -> Self {
38        let relative_path = match env::current_exe() {
39            Ok(mut path) => {
40                path.pop();
41                path
42            }
43            Err(err) => {
44                log::warn!("Could not resolve current executable for relative OBS path: {err}");
45                env::current_dir().unwrap_or_else(|_| PathBuf::from("."))
46            }
47        };
48
49        let obs_path = Self {
50            path: relative_path,
51        };
52
53        let path_str = path_str.trim_matches('/');
54
55        obs_path.push(path_str)
56    }
57
58    /// Modifies the path to point to the path
59    /// `path_str` appended to the current path which
60    /// `ObsPath` is pointing to.
61    pub fn push(mut self, value: &str) -> Self {
62        let split = value.split(['/', '\\'].as_ref());
63
64        for item in split {
65            if !item.is_empty() {
66                self.path.push(item);
67            }
68        }
69
70        self
71    }
72
73    /// Modifies the path to point to its current
74    /// parent. This is analogous to `Obs::push(".")`.
75    pub fn pop(mut self) -> Self {
76        self.path.pop();
77        self
78    }
79
80    /// Consumes the `ObsPath` to create a new
81    /// immutable ObsString that encodes a UTF-8
82    /// C-type string which describes the path that
83    /// the `ObsPath` is pointing to.
84    ///
85    /// Note that this function is lossy in that
86    /// any non-Unicode data is completely removed
87    /// from the string. This is because libobs
88    /// does not support non-Unicode characters in
89    /// its path.
90    pub fn build(self) -> ObsString {
91        let mut bytes = self.path.display().to_string().replace("\\", "/");
92
93        if self.path.is_dir() {
94            bytes += "/";
95        }
96        let obs_string = ObsString::from(bytes.as_str());
97
98        drop(self);
99        obs_string
100    }
101}
102
103impl From<ObsPath> for ObsString {
104    fn from(val: ObsPath) -> Self {
105        val.build()
106    }
107}
108
109impl From<ObsPath> for PathBuf {
110    fn from(val: ObsPath) -> Self {
111        val.path
112    }
113}