1use super::*;
8
9
10pub type NonNullFREData = NonNull<c_void>;
11pub type NonNullFREObject = 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)]
36pub struct UCStr(UCStrValue);
37#[derive(Debug, Clone, PartialEq, Eq)]
38enum UCStrValue {
39 Static(&'static CStr),
40 Heap(Arc<CStr>),
41}
42impl UCStr {
43 pub const fn from_literal (literal: &'static CStr) -> Result<Self, Utf8Error> {
44 match literal.to_str() {
45 Ok(_) => Ok(Self(UCStrValue::Static(literal))),
46 Err(e) => Err(e),
47 }
48 }
49 pub const unsafe fn from_literal_unchecked (literal: &'static CStr) -> Self {
50 debug_assert!(literal.to_str().is_ok());
51 Self(UCStrValue::Static(literal))
52 }
53 #[inline]
54 pub fn as_str (&self) -> &str {
55 let s = match self.0 {
56 UCStrValue::Static(s) => s.to_bytes(),
57 UCStrValue::Heap(ref s) => s.to_bytes(),
58 };
59 unsafe {str::from_utf8_unchecked(s)}
60 }
61 pub fn as_c_str (&self) -> &CStr {
62 match self.0 {
63 UCStrValue::Static(s) => s,
64 UCStrValue::Heap(ref s) => s.as_ref(),
65 }
66 }
67 pub fn as_ptr (&self) -> FREStr {
69 match self.0 {
70 UCStrValue::Static(s) => s.as_ptr() as FREStr,
71 UCStrValue::Heap(ref s) => s.as_ptr() as FREStr,
72 }
73 }
74 pub fn to_c_string (&self) -> CString {
75 match self.0 {
76 UCStrValue::Static(s) => s.to_owned(),
77 UCStrValue::Heap(ref s) => s.as_ref().to_owned(),
78 }
79 }
80}
81impl From<UCStr> for CString {
82 fn from(value: UCStr) -> Self {value.to_c_string()}
83}
84impl From<UCStr> for String {
85 fn from(value: UCStr) -> Self {value.to_string()}
86}
87impl TryFrom<String> for UCStr {
88 type Error = NulError;
89 fn try_from(value: String) -> Result<Self, NulError> {
90 CString::new(value).map(|s|{
91 let s = s.into();
92 Self(UCStrValue::Heap(s))
93 })
94 }
95}
96impl TryFrom<&str> for UCStr {
97 type Error = NulError;
98 fn try_from(value: &str) -> Result<Self, NulError> {
99 CString::new(value).map(|s|{
100 let s = s.into();
101 Self(UCStrValue::Heap(s))
102 })
103 }
104}
105impl TryFrom<CString> for UCStr {
106 type Error = Utf8Error;
107 fn try_from(value: CString) -> Result<Self, Utf8Error> {
108 value.to_str()?;
109 let s = value.into();
110 Ok(Self(UCStrValue::Heap(s)))
111 }
112}
113impl TryFrom<&CStr> for UCStr {
114 type Error = Utf8Error;
115 fn try_from(value: &CStr) -> Result<Self, Utf8Error> {
116 value.to_str().map(|_|{
117 let s = value.to_owned().into();
118 Self(UCStrValue::Heap(s))
119 })
120 }
121}
122impl PartialEq<str> for UCStr {
123 #[inline]
124 fn eq(&self, other: &str) -> bool { self.as_str() == other }
125}
126impl PartialEq<UCStr> for str {
127 #[inline]
128 fn eq(&self, other: &UCStr) -> bool { self == other.as_str() }
129}
130impl PartialOrd for UCStr {
131 #[inline]
132 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { self.as_str().partial_cmp(other.as_str()) }
133}
134impl Ord for UCStr {
135 #[inline]
136 fn cmp(&self, other: &Self) -> std::cmp::Ordering { self.as_str().cmp(other.as_str()) }
137}
138impl std::hash::Hash for UCStr {
139 #[inline]
140 fn hash<H: std::hash::Hasher>(&self, state: &mut H) { self.as_str().hash(state) }
141}
142impl AsRef<str> for UCStr {
143 fn as_ref(&self) -> &str { self.as_str() }
144}
145impl AsRef<CStr> for UCStr {
146 fn as_ref(&self) -> &CStr { self.as_c_str() }
147}
148impl std::borrow::Borrow<str> for UCStr {
149 #[inline]
150 fn borrow(&self) -> &str { self.as_str() }
151}
152impl Display for UCStr {
153 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { Display::fmt(self.as_str(), f) }
154}
155impl Default for UCStr {
156 fn default() -> Self {unsafe {Self::from_literal_unchecked(c"")}}
157}
158
159
160pub trait ToUcstrLossy {
161 fn to_ucstr_lossy(&self) -> UCStr;
162}
163impl ToUcstrLossy for UCStr {
164 fn to_ucstr_lossy(&self) -> UCStr {self.clone()}
165}
166impl<'a, O: AsObject<'a>> ToUcstrLossy for O {
167 fn to_ucstr_lossy(&self) -> UCStr {
168 self.to_string()
169 .as_str()
170 .to_ucstr_lossy()
171 }
172}
173impl<'a, O: AsObject<'a>> ToUcstrLossy for &[O] {
174 fn to_ucstr_lossy(&self) -> UCStr {
175 self.iter()
176 .map(|o|{o.to_string()})
177 .collect::<Vec<_>>()
178 .join(", ")
179 .as_str()
180 .to_ucstr_lossy()
181 }
182}
183impl ToUcstrLossy for &str {
184 fn to_ucstr_lossy(&self) -> UCStr {
185 self.replace('\0', "�")
186 .try_into()
187 .unwrap()
188 }
189}
190impl ToUcstrLossy for String {
191 fn to_ucstr_lossy(&self) -> UCStr {
192 self.as_str()
193 .to_ucstr_lossy()
194 }
195}
196