1use crate::{sys, SBStream};
8use std::ffi::CStr;
9use std::fmt;
10use std::path::Path;
11
12pub struct SBFileSpec {
18 pub raw: sys::SBFileSpecRef,
20}
21
22impl SBFileSpec {
23 pub(crate) fn wrap(raw: sys::SBFileSpecRef) -> SBFileSpec {
25 SBFileSpec { raw }
26 }
27
28 pub(crate) fn maybe_wrap(raw: sys::SBFileSpecRef) -> Option<SBFileSpec> {
30 if unsafe { sys::SBFileSpecIsValid(raw) } {
31 Some(SBFileSpec { raw })
32 } else {
33 None
34 }
35 }
36
37 pub fn from_path<P: AsRef<Path>>(path: P, resolve: bool) -> Self {
39 let path_cstring =
40 std::ffi::CString::new(path.as_ref().as_os_str().as_encoded_bytes()).unwrap();
41 Self::wrap(unsafe { sys::CreateSBFileSpec3(path_cstring.as_ptr(), resolve) })
42 }
43
44 pub fn is_valid(&self) -> bool {
46 unsafe { sys::SBFileSpecIsValid(self.raw) }
47 }
48
49 pub fn exists(&self) -> bool {
51 unsafe { sys::SBFileSpecExists(self.raw) }
52 }
53
54 pub fn filename(&self) -> &str {
56 unsafe {
57 match CStr::from_ptr(sys::SBFileSpecGetFilename(self.raw)).to_str() {
58 Ok(s) => s,
59 _ => panic!("Invalid string?"),
60 }
61 }
62 }
63
64 pub fn directory(&self) -> &str {
66 unsafe {
67 match CStr::from_ptr(sys::SBFileSpecGetDirectory(self.raw)).to_str() {
68 Ok(s) => s,
69 _ => panic!("Invalid string?"),
70 }
71 }
72 }
73}
74
75impl Clone for SBFileSpec {
76 fn clone(&self) -> SBFileSpec {
77 SBFileSpec {
78 raw: unsafe { sys::CloneSBFileSpec(self.raw) },
79 }
80 }
81}
82
83impl fmt::Debug for SBFileSpec {
84 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
85 let stream = SBStream::new();
86 unsafe { sys::SBFileSpecGetDescription(self.raw, stream.raw) };
87 write!(fmt, "SBFileSpec {{ {} }}", stream.data())
88 }
89}
90
91impl Drop for SBFileSpec {
92 fn drop(&mut self) {
93 unsafe { sys::DisposeSBFileSpec(self.raw) };
94 }
95}
96
97unsafe impl Send for SBFileSpec {}
98unsafe impl Sync for SBFileSpec {}
99
100#[cfg(feature = "graphql")]
101#[juniper::graphql_object]
102impl SBFileSpec {
103 fn exists() -> bool {
104 self.exists()
105 }
106
107 fn filename() -> &str {
108 self.filename()
109 }
110
111 fn directory() -> &str {
112 self.directory()
113 }
114}