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