1#[derive(Debug, Clone, Copy, PartialEq, Eq)]
20pub enum CType {
21 Void,
23
24 Char, SChar, UChar, Short, UShort, Int, UInt, Long, ULong, LongLong, ULongLong, Float, Double, Size, SSize, PtrDiff, Int8,
50 Int16,
51 Int32,
52 Int64,
53 UInt8,
54 UInt16,
55 UInt32,
56 UInt64,
57}
58
59impl CType {
60 pub fn sigil_name(&self) -> &'static str {
62 match self {
63 CType::Void => "c_void",
64 CType::Char => "c_char",
65 CType::SChar => "c_schar",
66 CType::UChar => "c_uchar",
67 CType::Short => "c_short",
68 CType::UShort => "c_ushort",
69 CType::Int => "c_int",
70 CType::UInt => "c_uint",
71 CType::Long => "c_long",
72 CType::ULong => "c_ulong",
73 CType::LongLong => "c_longlong",
74 CType::ULongLong => "c_ulonglong",
75 CType::Float => "c_float",
76 CType::Double => "c_double",
77 CType::Size => "size_t",
78 CType::SSize => "ssize_t",
79 CType::PtrDiff => "ptrdiff_t",
80 CType::Int8 => "i8",
81 CType::Int16 => "i16",
82 CType::Int32 => "i32",
83 CType::Int64 => "i64",
84 CType::UInt8 => "u8",
85 CType::UInt16 => "u16",
86 CType::UInt32 => "u32",
87 CType::UInt64 => "u64",
88 }
89 }
90
91 pub fn size_bytes(&self) -> usize {
93 match self {
94 CType::Void => 0,
95 CType::Char | CType::SChar | CType::UChar => 1,
96 CType::Short | CType::UShort => 2,
97 CType::Int | CType::UInt => 4,
98 CType::Long | CType::ULong => 8, CType::LongLong | CType::ULongLong => 8,
100 CType::Float => 4,
101 CType::Double => 8,
102 CType::Size | CType::SSize | CType::PtrDiff => 8, CType::Int8 | CType::UInt8 => 1,
104 CType::Int16 | CType::UInt16 => 2,
105 CType::Int32 | CType::UInt32 => 4,
106 CType::Int64 | CType::UInt64 => 8,
107 }
108 }
109
110 pub fn is_signed(&self) -> bool {
112 matches!(
113 self,
114 CType::SChar | CType::Short | CType::Int | CType::Long | CType::LongLong |
115 CType::SSize | CType::PtrDiff |
116 CType::Int8 | CType::Int16 | CType::Int32 | CType::Int64
117 )
118 }
119
120 pub fn from_name(name: &str) -> Option<CType> {
122 match name {
123 "c_void" | "void" => Some(CType::Void),
124 "c_char" | "char" => Some(CType::Char),
125 "c_schar" => Some(CType::SChar),
126 "c_uchar" => Some(CType::UChar),
127 "c_short" | "short" => Some(CType::Short),
128 "c_ushort" => Some(CType::UShort),
129 "c_int" | "int" => Some(CType::Int),
130 "c_uint" => Some(CType::UInt),
131 "c_long" | "long" => Some(CType::Long),
132 "c_ulong" => Some(CType::ULong),
133 "c_longlong" => Some(CType::LongLong),
134 "c_ulonglong" => Some(CType::ULongLong),
135 "c_float" | "float" => Some(CType::Float),
136 "c_double" | "double" => Some(CType::Double),
137 "size_t" | "usize" => Some(CType::Size),
138 "ssize_t" | "isize" => Some(CType::SSize),
139 "ptrdiff_t" => Some(CType::PtrDiff),
140 "i8" | "int8_t" => Some(CType::Int8),
141 "i16" | "int16_t" => Some(CType::Int16),
142 "i32" | "int32_t" => Some(CType::Int32),
143 "i64" | "int64_t" => Some(CType::Int64),
144 "u8" | "uint8_t" => Some(CType::UInt8),
145 "u16" | "uint16_t" => Some(CType::UInt16),
146 "u32" | "uint32_t" => Some(CType::UInt32),
147 "u64" | "uint64_t" => Some(CType::UInt64),
148 _ => None,
149 }
150 }
151}
152
153pub const C_TYPE_ALIASES: &[(&str, &str)] = &[
155 ("c_void", "()"),
157
158 ("c_char", "i8"), ("c_schar", "i8"),
161 ("c_uchar", "u8"),
162
163 ("c_short", "i16"),
165 ("c_ushort", "u16"),
166 ("c_int", "i32"),
167 ("c_uint", "u32"),
168 ("c_long", "i64"), ("c_ulong", "u64"),
170 ("c_longlong", "i64"),
171 ("c_ulonglong", "u64"),
172
173 ("c_float", "f32"),
175 ("c_double", "f64"),
176
177 ("size_t", "usize"),
179 ("ssize_t", "isize"),
180 ("ptrdiff_t", "isize"),
181
182 ("int8_t", "i8"),
184 ("int16_t", "i16"),
185 ("int32_t", "i32"),
186 ("int64_t", "i64"),
187 ("uint8_t", "u8"),
188 ("uint16_t", "u16"),
189 ("uint32_t", "u32"),
190 ("uint64_t", "u64"),
191];
192
193pub fn is_c_type(name: &str) -> bool {
195 CType::from_name(name).is_some()
196}
197
198#[cfg(test)]
199mod tests {
200 use super::*;
201
202 #[test]
203 fn test_c_type_parsing() {
204 assert_eq!(CType::from_name("c_int"), Some(CType::Int));
205 assert_eq!(CType::from_name("c_void"), Some(CType::Void));
206 assert_eq!(CType::from_name("size_t"), Some(CType::Size));
207 assert_eq!(CType::from_name("unknown"), None);
208 }
209
210 #[test]
211 fn test_c_type_sizes() {
212 assert_eq!(CType::Int.size_bytes(), 4);
213 assert_eq!(CType::Long.size_bytes(), 8);
214 assert_eq!(CType::Char.size_bytes(), 1);
215 assert_eq!(CType::Double.size_bytes(), 8);
216 }
217
218 #[test]
219 fn test_c_type_signedness() {
220 assert!(CType::Int.is_signed());
221 assert!(!CType::UInt.is_signed());
222 assert!(CType::SSize.is_signed());
223 assert!(!CType::Size.is_signed());
224 }
225}