1use std::num::TryFromIntError;
4
5use libc::{c_char, c_uchar};
6
7use crate::translate::*;
8
9#[derive(Debug, Copy, Clone, Eq, PartialEq)]
53pub struct Char(pub c_char);
54
55impl TryFrom<char> for Char {
56 type Error = TryFromIntError;
57
58 #[allow(clippy::unnecessary_cast)]
59 fn try_from(c: char) -> Result<Char, Self::Error> {
60 Ok(Self(u8::try_from(u32::from(c))? as c_char))
61 }
62}
63
64impl From<Char> for char {
65 fn from(c: Char) -> char {
66 c.0 as u8 as char
67 }
68}
69
70impl From<u8> for Char {
71 #[allow(clippy::unnecessary_cast)]
72 fn from(c: u8) -> Char {
73 Char(c as c_char)
74 }
75}
76
77impl From<Char> for u8 {
78 #[allow(clippy::unnecessary_cast)]
79 fn from(c: Char) -> u8 {
80 c.0 as u8
81 }
82}
83
84#[doc(hidden)]
85impl FromGlib<c_char> for Char {
86 #[inline]
87 unsafe fn from_glib(value: c_char) -> Self {
88 Self(value)
89 }
90}
91
92#[doc(hidden)]
93impl IntoGlib for Char {
94 type GlibType = c_char;
95
96 #[inline]
97 fn into_glib(self) -> c_char {
98 self.0
99 }
100}
101
102#[derive(Debug, Copy, Clone, Eq, PartialEq)]
128pub struct UChar(pub c_uchar);
129
130impl TryFrom<char> for UChar {
131 type Error = TryFromIntError;
132
133 #[allow(clippy::unnecessary_cast)]
134 fn try_from(c: char) -> Result<UChar, Self::Error> {
135 Ok(Self(u8::try_from(u32::from(c))? as c_uchar))
136 }
137}
138
139impl From<UChar> for char {
140 fn from(c: UChar) -> char {
141 c.0 as _
142 }
143}
144
145impl From<u8> for UChar {
146 #[allow(clippy::unnecessary_cast)]
147 fn from(c: u8) -> UChar {
148 UChar(c as _)
149 }
150}
151
152impl From<UChar> for u8 {
153 fn from(c: UChar) -> u8 {
154 c.0 as _
155 }
156}
157
158#[doc(hidden)]
159impl FromGlib<c_uchar> for UChar {
160 #[inline]
161 unsafe fn from_glib(value: c_uchar) -> Self {
162 Self(value)
163 }
164}
165
166#[doc(hidden)]
167impl IntoGlib for UChar {
168 type GlibType = c_uchar;
169
170 #[inline]
171 fn into_glib(self) -> c_uchar {
172 self.0
173 }
174}
175
176#[cfg(test)]
177mod tests {
178 use super::*;
179
180 #[test]
181 #[allow(clippy::unnecessary_cast)]
182 fn converts_single_byte_chars() {
183 assert_eq!(Char::try_from(0 as char), Ok(Char(0 as c_char)));
184 assert_eq!(UChar::try_from(0 as char), Ok(UChar(0 as c_uchar)));
185 assert_eq!(UChar::try_from(255 as char), Ok(UChar(255 as c_uchar)));
186 assert_eq!(UChar::try_from('ñ'), Ok(UChar(241 as c_uchar)));
187 }
188
189 #[test]
190 fn refuses_multibyte_chars() {
191 assert!(Char::try_from('☔').is_err()); assert!(UChar::try_from('☔').is_err());
193 }
194
195 #[test]
196 #[allow(clippy::unnecessary_cast)]
197 fn into_i8() {
198 assert_eq!(Char::from(b'A').into_glib(), 65 as c_char);
199 }
200
201 #[test]
202 #[allow(clippy::unnecessary_cast)]
203 fn into_u8() {
204 assert_eq!(UChar::from(b'A').into_glib(), 65 as c_uchar);
205 }
206
207 #[test]
208 #[allow(clippy::unnecessary_cast)]
209 fn into_char() {
210 assert_eq!(char::from(Char(65 as c_char)), 'A');
211 assert_eq!('ñ', UChar(241 as c_uchar).into());
212 }
213
214 #[test]
215 #[allow(clippy::unnecessary_cast)]
216 fn convert_from_glib() {
217 assert_eq!(Char(65 as c_char), unsafe { from_glib(65 as c_char) });
218 assert_eq!(UChar(241 as c_uchar), unsafe { from_glib(241 as c_uchar) });
219 }
220}