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}