1use crate::{c::c_char, Ustr, Ustring};
2use std::{
3 ffi::{CStr, OsStr},
4 fmt,
5 fmt::{Debug, Display, Formatter},
6 ops::{Deref, DerefMut},
7 os::unix::ffi::OsStrExt,
8 path::Path,
9 str::Utf8Error,
10};
11
12#[repr(transparent)]
16#[derive(Eq, Ord, PartialOrd, PartialEq, Hash)]
17pub struct Bstr {
18 bytes: [u8],
19}
20
21impl Bstr {
22 pub fn empty() -> &'static Self {
24 static E: [u8; 0] = [];
25 Self::from_bytes(&E[..])
26 }
27
28 pub fn from_bytes(s: &[u8]) -> &Self {
30 unsafe { &*(s as *const _ as *const _) }
31 }
32
33 pub fn from_bytes_mut(s: &mut [u8]) -> &mut Self {
35 unsafe { &mut *(s as *mut _ as *mut _) }
36 }
37
38 #[allow(clippy::should_implement_trait)] pub fn from_str(s: &str) -> &Self {
41 Self::from_bytes(s.as_bytes())
42 }
43
44 pub fn from_os_str(s: &OsStr) -> &Self {
46 Self::from_bytes(s.as_bytes())
47 }
48
49 pub fn from_path(s: &Path) -> &Self {
51 Self::from_os_str(s.as_os_str())
52 }
53
54 pub fn as_bytes(&self) -> &[u8] {
56 &self.bytes
57 }
58
59 pub fn as_bytes_mut(&mut self) -> &mut [u8] {
61 &mut self.bytes
62 }
63
64 pub fn as_str(&self) -> Result<&str, Utf8Error> {
66 std::str::from_utf8(self.as_bytes())
67 }
68
69 pub fn as_os_str(&self) -> &OsStr {
71 OsStr::from_bytes(self.as_bytes())
72 }
73
74 pub fn as_path(&self) -> &Path {
76 Path::new(self.as_os_str())
77 }
78
79 pub fn as_ptr(&self) -> *const c_char {
81 self.as_bytes().as_ptr() as *const c_char
82 }
83
84 pub fn as_mut_ptr(&mut self) -> *mut c_char {
86 self.as_bytes_mut().as_mut_ptr() as *mut c_char
87 }
88
89 pub fn len(&self) -> usize {
91 self.bytes.len()
92 }
93
94 pub fn is_empty(&self) -> bool {
96 self.len() == 0
97 }
98
99 pub fn display(&self) -> impl Display + '_ {
101 self.as_path().display()
102 }
103
104 pub fn to_ustring(&self) -> Ustring {
106 let mut vec = Vec::with_capacity(self.len() + 1);
107 vec.extend_from_slice(self.as_bytes());
108 vec.push(0);
109 unsafe { Ustring::from_vec_with_nul_unchecked(vec) }
110 }
111}
112
113impl ToOwned for Bstr {
114 type Owned = Ustring;
115
116 fn to_owned(&self) -> Self::Owned {
117 self.to_ustring()
118 }
119}
120
121impl Deref for Bstr {
122 type Target = [u8];
123
124 fn deref(&self) -> &Self::Target {
125 self.as_bytes()
126 }
127}
128
129impl DerefMut for Bstr {
130 fn deref_mut(&mut self) -> &mut Self::Target {
131 self.as_bytes_mut()
132 }
133}
134
135impl AsRef<[u8]> for Bstr {
136 fn as_ref(&self) -> &[u8] {
137 self.as_bytes()
138 }
139}
140
141impl AsMut<[u8]> for Bstr {
142 fn as_mut(&mut self) -> &mut [u8] {
143 self.as_bytes_mut()
144 }
145}
146
147impl AsRef<Bstr> for CStr {
148 fn as_ref(&self) -> &Bstr {
149 Ustr::from_c_str(self).as_bstr()
150 }
151}
152
153impl AsRef<OsStr> for Bstr {
154 fn as_ref(&self) -> &OsStr {
155 self.as_os_str()
156 }
157}
158
159impl AsRef<Path> for Bstr {
160 fn as_ref(&self) -> &Path {
161 self.as_path()
162 }
163}
164
165impl Debug for Bstr {
166 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
167 Debug::fmt(self.as_os_str(), f)
168 }
169}