1use super::*;
8
9
10pub type NonNullFREData = NonNull<c_void>;
11pub type NonNullHandle = NonNull<c_void>;
12
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15#[repr(transparent)]
16pub struct NonNegativeInt(i32);
17impl NonNegativeInt {
18 pub const MIN: Self = Self(0);
19 pub const MAX: Self = Self(i32::MAX);
20 pub fn new (value: i32) -> Option<Self> {
21 if value >= 0 {
22 Some(Self(value))
23 } else {
24 None
25 }
26 }
27 pub fn get (self) -> i32 {self.0}
28}
29impl Default for NonNegativeInt {
30 fn default() -> Self {Self::MIN}
31}
32
33
34#[derive(Debug, Clone, PartialEq, Eq)]
39pub struct UCStr(UCStrValue);
40#[derive(Debug, Clone, PartialEq, Eq)]
41enum UCStrValue {
42 Static(&'static CStr),
43 Heap(Arc<CStr>),
44}
45impl UCStr {
46 pub const fn from_literal (literal: &'static CStr) -> Result<Self, Utf8Error> {
47 match literal.to_str() {
48 Ok(_) => Ok(Self(UCStrValue::Static(literal))),
49 Err(e) => Err(e),
50 }
51 }
52 pub const unsafe fn from_literal_unchecked (literal: &'static CStr) -> Self {
53 debug_assert!(literal.to_str().is_ok());
54 Self(UCStrValue::Static(literal))
55 }
56 #[inline]
57 pub fn as_str (&self) -> &str {
58 let s = match self.0 {
59 UCStrValue::Static(s) => s.to_bytes(),
60 UCStrValue::Heap(ref s) => s.to_bytes(),
61 };
62 unsafe {str::from_utf8_unchecked(s)}
63 }
64 pub fn as_c_str (&self) -> &CStr {
65 match self.0 {
66 UCStrValue::Static(s) => s,
67 UCStrValue::Heap(ref s) => s.as_ref(),
68 }
69 }
70 pub fn as_ptr (&self) -> FREStr {
72 match self.0 {
73 UCStrValue::Static(s) => s.as_ptr() as FREStr,
74 UCStrValue::Heap(ref s) => s.as_ptr() as FREStr,
75 }
76 }
77 pub fn to_c_string (&self) -> CString {
78 match self.0 {
79 UCStrValue::Static(s) => s.to_owned(),
80 UCStrValue::Heap(ref s) => s.as_ref().to_owned(),
81 }
82 }
83}
84impl From<UCStr> for CString {
85 fn from(value: UCStr) -> Self {value.to_c_string()}
86}
87impl From<UCStr> for String {
88 fn from(value: UCStr) -> Self {value.to_string()}
89}
90impl TryFrom<String> for UCStr {
91 type Error = NulError;
92 fn try_from(value: String) -> Result<Self, NulError> {
93 CString::new(value).map(|s|{
94 let s = s.into();
95 Self(UCStrValue::Heap(s))
96 })
97 }
98}
99impl TryFrom<&str> for UCStr {
100 type Error = NulError;
101 fn try_from(value: &str) -> Result<Self, NulError> {
102 CString::new(value).map(|s|{
103 let s = s.into();
104 Self(UCStrValue::Heap(s))
105 })
106 }
107}
108impl TryFrom<CString> for UCStr {
109 type Error = Utf8Error;
110 fn try_from(value: CString) -> Result<Self, Utf8Error> {
111 value.to_str()?;
112 let s = value.into();
113 Ok(Self(UCStrValue::Heap(s)))
114 }
115}
116impl TryFrom<&CStr> for UCStr {
117 type Error = Utf8Error;
118 fn try_from(value: &CStr) -> Result<Self, Utf8Error> {
119 value.to_str().map(|_|{
120 let s = value.to_owned().into();
121 Self(UCStrValue::Heap(s))
122 })
123 }
124}
125impl PartialEq<str> for UCStr {
126 #[inline]
127 fn eq(&self, other: &str) -> bool { self.as_str() == other }
128}
129impl PartialEq<UCStr> for str {
130 #[inline]
131 fn eq(&self, other: &UCStr) -> bool { self == other.as_str() }
132}
133impl PartialOrd for UCStr {
134 #[inline]
135 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { self.as_str().partial_cmp(other.as_str()) }
136}
137impl Ord for UCStr {
138 #[inline]
139 fn cmp(&self, other: &Self) -> std::cmp::Ordering { self.as_str().cmp(other.as_str()) }
140}
141impl std::hash::Hash for UCStr {
142 #[inline]
143 fn hash<H: std::hash::Hasher>(&self, state: &mut H) { self.as_str().hash(state) }
144}
145impl AsRef<str> for UCStr {
146 fn as_ref(&self) -> &str { self.as_str() }
147}
148impl AsRef<CStr> for UCStr {
149 fn as_ref(&self) -> &CStr { self.as_c_str() }
150}
151impl std::borrow::Borrow<str> for UCStr {
152 #[inline]
153 fn borrow(&self) -> &str { self.as_str() }
154}
155impl Display for UCStr {
156 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { Display::fmt(self.as_str(), f) }
157}
158impl Default for UCStr {
159 fn default() -> Self {Self(UCStrValue::Static(c""))}
160}
161
162
163pub trait ToUcstrLossy {
164 fn to_ucstr_lossy(&self) -> UCStr;
165}
166impl<T: ?Sized> ToUcstrLossy for &T
167where T: ToUcstrLossy
168{fn to_ucstr_lossy(&self) -> UCStr {T::to_ucstr_lossy(self)}}
169impl<T: ?Sized> ToUcstrLossy for &mut T
170where for<'a> &'a T: ToUcstrLossy
171{fn to_ucstr_lossy(&self) -> UCStr {((*self) as &T).to_ucstr_lossy()}}
172impl ToUcstrLossy for UCStr {fn to_ucstr_lossy(&self) -> UCStr {self.clone()}}
175impl ToUcstrLossy for str {fn to_ucstr_lossy(&self) -> UCStr {
176 let buf = self.replace('\0', "�");
177 let buf = unsafe {CString::from_vec_unchecked(buf.into_bytes())};
178 UCStr(UCStrValue::Heap(buf.into()))
179}}
180impl ToUcstrLossy for String {fn to_ucstr_lossy(&self) -> UCStr {self.as_str().to_ucstr_lossy()}}
181impl ToUcstrLossy for CStr {fn to_ucstr_lossy(&self) -> UCStr {
182 let s = self.to_string_lossy();
183 let bytes = s.as_bytes();
184 let mut v = Vec::with_capacity(bytes.len()+1);
185 v.extend_from_slice(bytes);
186 v.push(0);
187 let s = unsafe {CString::from_vec_with_nul_unchecked(v)};
188 UCStr(UCStrValue::Heap(s.into()))
189}}
190impl ToUcstrLossy for CString {fn to_ucstr_lossy(&self) -> UCStr {self.as_c_str().to_ucstr_lossy()}}
191impl ToUcstrLossy for Object<'_> {fn to_ucstr_lossy(&self) -> UCStr {self.to_string().to_ucstr_lossy()}}
192impl ToUcstrLossy for NonNullObject<'_> {fn to_ucstr_lossy(&self) -> UCStr {self.as_object().to_ucstr_lossy()}}
193impl ToUcstrLossy for () {fn to_ucstr_lossy(&self) -> UCStr {crate::ucstringify!(())}}
195impl ToUcstrLossy for char {fn to_ucstr_lossy(&self) -> UCStr {
196 let buf = format!("'{}'(U+{:08X})\0", self.escape_default(),*self as u32);
197 let buf = unsafe {CString::from_vec_with_nul_unchecked(buf.into_bytes())};
198 UCStr(UCStrValue::Heap(buf.into()))
199}}
200impl ToUcstrLossy for bool {fn to_ucstr_lossy(&self) -> UCStr {
201 if *self {crate::ucstringify!(true)} else {crate::ucstringify!(false)}
202}}
203impl ToUcstrLossy for i8 {fn to_ucstr_lossy(&self) -> UCStr {
204 let buf = self.to_string().into_bytes();
205 let buf = unsafe {CString::from_vec_unchecked(buf)};
206 UCStr(UCStrValue::Heap(buf.into()))
207}}
208impl ToUcstrLossy for i16 {fn to_ucstr_lossy(&self) -> UCStr {
209 let buf = self.to_string().into_bytes();
210 let buf = unsafe {CString::from_vec_unchecked(buf)};
211 UCStr(UCStrValue::Heap(buf.into()))
212}}
213impl ToUcstrLossy for i32 {fn to_ucstr_lossy(&self) -> UCStr {
214 let buf = self.to_string().into_bytes();
215 let buf = unsafe {CString::from_vec_unchecked(buf)};
216 UCStr(UCStrValue::Heap(buf.into()))
217}}
218impl ToUcstrLossy for i64 {fn to_ucstr_lossy(&self) -> UCStr {
219 let buf = self.to_string().into_bytes();
220 let buf = unsafe {CString::from_vec_unchecked(buf)};
221 UCStr(UCStrValue::Heap(buf.into()))
222}}
223impl ToUcstrLossy for i128 {fn to_ucstr_lossy(&self) -> UCStr {
224 let buf = self.to_string().into_bytes();
225 let buf = unsafe {CString::from_vec_unchecked(buf)};
226 UCStr(UCStrValue::Heap(buf.into()))
227}}
228impl ToUcstrLossy for isize {fn to_ucstr_lossy(&self) -> UCStr {
229 let buf = self.to_string().into_bytes();
230 let buf = unsafe {CString::from_vec_unchecked(buf)};
231 UCStr(UCStrValue::Heap(buf.into()))
232}}
233impl ToUcstrLossy for u8 {fn to_ucstr_lossy(&self) -> UCStr {
234 let buf = self.to_string().into_bytes();
235 let buf = unsafe {CString::from_vec_unchecked(buf)};
236 UCStr(UCStrValue::Heap(buf.into()))
237}}
238impl ToUcstrLossy for u16 {fn to_ucstr_lossy(&self) -> UCStr {
239 let buf = self.to_string().into_bytes();
240 let buf = unsafe {CString::from_vec_unchecked(buf)};
241 UCStr(UCStrValue::Heap(buf.into()))
242}}
243impl ToUcstrLossy for u32 {fn to_ucstr_lossy(&self) -> UCStr {
244 let buf = self.to_string().into_bytes();
245 let buf = unsafe {CString::from_vec_unchecked(buf)};
246 UCStr(UCStrValue::Heap(buf.into()))
247}}
248impl ToUcstrLossy for u64 {fn to_ucstr_lossy(&self) -> UCStr {
249 let buf = self.to_string().into_bytes();
250 let buf = unsafe {CString::from_vec_unchecked(buf)};
251 UCStr(UCStrValue::Heap(buf.into()))
252}}
253impl ToUcstrLossy for u128 {fn to_ucstr_lossy(&self) -> UCStr {
254 let buf = self.to_string().into_bytes();
255 let buf = unsafe {CString::from_vec_unchecked(buf)};
256 UCStr(UCStrValue::Heap(buf.into()))
257}}
258impl ToUcstrLossy for usize {fn to_ucstr_lossy(&self) -> UCStr {
259 let buf = self.to_string().into_bytes();
260 let buf = unsafe {CString::from_vec_unchecked(buf)};
261 UCStr(UCStrValue::Heap(buf.into()))
262}}
263impl ToUcstrLossy for f32 {fn to_ucstr_lossy(&self) -> UCStr {
264 let buf = self.to_string().into_bytes();
265 let buf = unsafe {CString::from_vec_unchecked(buf)};
266 UCStr(UCStrValue::Heap(buf.into()))
267}}
268impl ToUcstrLossy for f64 {fn to_ucstr_lossy(&self) -> UCStr {
269 let buf = self.to_string().into_bytes();
270 let buf = unsafe {CString::from_vec_unchecked(buf)};
271 UCStr(UCStrValue::Heap(buf.into()))
272}}
273impl<T> ToUcstrLossy for *const T {fn to_ucstr_lossy(&self) -> UCStr {
274 let buf = format!("*const({:p})\0", self);
275 let buf = unsafe {CString::from_vec_with_nul_unchecked(buf.into_bytes())};
276 UCStr(UCStrValue::Heap(buf.into()))
277}}
278impl<T> ToUcstrLossy for *mut T {fn to_ucstr_lossy(&self) -> UCStr {
279 let buf = format!("*mut({:p})\0", self);
280 let buf = unsafe {CString::from_vec_with_nul_unchecked(buf.into_bytes())};
281 UCStr(UCStrValue::Heap(buf.into()))
282}}
283impl<T: ToUcstrLossy> ToUcstrLossy for Option<T> {fn to_ucstr_lossy(&self) -> UCStr {
286 if let Some(inner) = self {
287 let inner = inner.to_ucstr_lossy();
288 let mut buf = String::with_capacity(4 + 1 + inner.as_str().len() + 1 + 1);
289 buf.push_str("Some(");
290 buf.push_str(inner.as_str());
291 buf.push_str(")\0");
292 let buf = unsafe {CString::from_vec_with_nul_unchecked(buf.into_bytes())};
293 UCStr(UCStrValue::Heap(buf.into()))
294 } else {crate::ucstringify!(None)}
295}}
296impl<T: ToUcstrLossy> ToUcstrLossy for [T] {fn to_ucstr_lossy(&self) -> UCStr {
297 const SEPARATOR: &str = ", ";
298 let elems = self.iter()
299 .map(|i|i.to_ucstr_lossy())
300 .collect::<Box<[UCStr]>>();
301 let len = elems.iter()
302 .map(|s|s.as_str().len())
303 .sum::<usize>()
304 + (elems.len().saturating_sub(1))*SEPARATOR.len()
305 + 2
306 + 1;
307 let mut buf = String::with_capacity(len);
308 buf.push('[');
309 for (i, s) in elems.iter().enumerate() {
310 if i != 0 {buf.push_str(SEPARATOR);}
311 buf.push_str(s.as_str());
312 }
313 buf.push(']');
314 buf.push('\0');
315 let buf = unsafe {CString::from_vec_with_nul_unchecked(buf.into_bytes())};
316 UCStr(UCStrValue::Heap(buf.into()))
317}}
318impl<T: ToUcstrLossy, const LEN: usize> ToUcstrLossy for [T; LEN] {fn to_ucstr_lossy(&self) -> UCStr {self.as_slice().to_ucstr_lossy()}}
319impl<T: ToUcstrLossy> ToUcstrLossy for Vec<T> {fn to_ucstr_lossy(&self) -> UCStr {self.as_slice().to_ucstr_lossy()} }
320impl<T: ToUcstrLossy>
321ToUcstrLossy for (T,) {fn to_ucstr_lossy(&self) -> UCStr {
322 let s = self.0.to_ucstr_lossy();
323 let mut buf = String::with_capacity(s.as_str().len() + 3);
324 buf.push('(');
325 buf.push_str(s.as_str());
326 buf.push(')');
327 buf.push('\0');
328 let buf = unsafe {CString::from_vec_with_nul_unchecked(buf.into_bytes())};
329 UCStr(UCStrValue::Heap(buf.into()))
330}}
331macro_rules! tuple_to_ucstr {
332 ($elements:expr_2021) => {{
333 const SEPARATOR: &'static str = ", ";
334 let len = $elements.iter()
335 .map(|s|s.as_str().len())
336 .sum::<usize>()
337 + ($elements.len().saturating_sub(1))*SEPARATOR.len()
338 + 2
339 + 1;
340 let mut buf = String::with_capacity(len);
341 buf.push('(');
342 for (i, s) in $elements.iter().enumerate() {
343 if i != 0 {buf.push_str(SEPARATOR);}
344 buf.push_str(s.as_str());
345 }
346 buf.push(')');
347 buf.push('\0');
348 let buf = unsafe {CString::from_vec_with_nul_unchecked(buf.into_bytes())};
349 UCStr(UCStrValue::Heap(buf.into()))
350 }};
351}
352impl<T: ToUcstrLossy, U: ToUcstrLossy>
353ToUcstrLossy for (T, U) {fn to_ucstr_lossy(&self) -> UCStr {
354 let elements = [self.0.to_ucstr_lossy(), self.1.to_ucstr_lossy()];
355 tuple_to_ucstr! (elements)
356}}
357impl<T: ToUcstrLossy, U: ToUcstrLossy, V: ToUcstrLossy>
358ToUcstrLossy for (T, U, V) {fn to_ucstr_lossy(&self) -> UCStr {
359 let elements = [self.0.to_ucstr_lossy(), self.1.to_ucstr_lossy(), self.2.to_ucstr_lossy()];
360 tuple_to_ucstr! (elements)
361}}
362impl<T: ToUcstrLossy, U: ToUcstrLossy, V: ToUcstrLossy, W: ToUcstrLossy>
363ToUcstrLossy for (T, U, V, W) {fn to_ucstr_lossy(&self) -> UCStr {
364 let elements = [self.0.to_ucstr_lossy(), self.1.to_ucstr_lossy(), self.2.to_ucstr_lossy(), self.3.to_ucstr_lossy()];
365 tuple_to_ucstr! (elements)
366}}
367impl<T: ToUcstrLossy, U: ToUcstrLossy, V: ToUcstrLossy, W: ToUcstrLossy, X: ToUcstrLossy>
368ToUcstrLossy for (T, U, V, W, X) {fn to_ucstr_lossy(&self) -> UCStr {
369 let elements = [self.0.to_ucstr_lossy(), self.1.to_ucstr_lossy(), self.2.to_ucstr_lossy(), self.3.to_ucstr_lossy(), self.4.to_ucstr_lossy()];
370 tuple_to_ucstr! (elements)
371}}
372impl<T: ToUcstrLossy, U: ToUcstrLossy, V: ToUcstrLossy, W: ToUcstrLossy, X: ToUcstrLossy, Y: ToUcstrLossy>
373ToUcstrLossy for (T, U, V, W, X, Y) {fn to_ucstr_lossy(&self) -> UCStr {
374 let elements = [self.0.to_ucstr_lossy(), self.1.to_ucstr_lossy(), self.2.to_ucstr_lossy(), self.3.to_ucstr_lossy(), self.4.to_ucstr_lossy(), self.5.to_ucstr_lossy()];
375 tuple_to_ucstr! (elements)
376}}
377impl<T: ToUcstrLossy, U: ToUcstrLossy, V: ToUcstrLossy, W: ToUcstrLossy, X: ToUcstrLossy, Y: ToUcstrLossy, Z: ToUcstrLossy>
378ToUcstrLossy for (T, U, V, W, X, Y, Z) {fn to_ucstr_lossy(&self) -> UCStr {
379 let elements = [self.0.to_ucstr_lossy(), self.1.to_ucstr_lossy(), self.2.to_ucstr_lossy(), self.3.to_ucstr_lossy(), self.4.to_ucstr_lossy(), self.5.to_ucstr_lossy(), self.6.to_ucstr_lossy()];
380 tuple_to_ucstr! (elements)
381}}
382impl<T: ToUcstrLossy, U: ToUcstrLossy, V: ToUcstrLossy, W: ToUcstrLossy, X: ToUcstrLossy, Y: ToUcstrLossy, Z: ToUcstrLossy, A: ToUcstrLossy>
383ToUcstrLossy for (T, U, V, W, X, Y, Z, A) {fn to_ucstr_lossy(&self) -> UCStr {
384 let elements = [self.0.to_ucstr_lossy(), self.1.to_ucstr_lossy(), self.2.to_ucstr_lossy(), self.3.to_ucstr_lossy(), self.4.to_ucstr_lossy(), self.5.to_ucstr_lossy(), self.6.to_ucstr_lossy(), self.7.to_ucstr_lossy()];
385 tuple_to_ucstr! (elements)
386}}
387