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
115 | CType::Short
116 | CType::Int
117 | CType::Long
118 | CType::LongLong
119 | CType::SSize
120 | CType::PtrDiff
121 | CType::Int8
122 | CType::Int16
123 | CType::Int32
124 | CType::Int64
125 )
126 }
127
128 pub fn from_name(name: &str) -> Option<CType> {
130 match name {
131 "c_void" | "void" => Some(CType::Void),
132 "c_char" | "char" => Some(CType::Char),
133 "c_schar" => Some(CType::SChar),
134 "c_uchar" => Some(CType::UChar),
135 "c_short" | "short" => Some(CType::Short),
136 "c_ushort" => Some(CType::UShort),
137 "c_int" | "int" => Some(CType::Int),
138 "c_uint" => Some(CType::UInt),
139 "c_long" | "long" => Some(CType::Long),
140 "c_ulong" => Some(CType::ULong),
141 "c_longlong" => Some(CType::LongLong),
142 "c_ulonglong" => Some(CType::ULongLong),
143 "c_float" | "float" => Some(CType::Float),
144 "c_double" | "double" => Some(CType::Double),
145 "size_t" | "usize" => Some(CType::Size),
146 "ssize_t" | "isize" => Some(CType::SSize),
147 "ptrdiff_t" => Some(CType::PtrDiff),
148 "i8" | "int8_t" => Some(CType::Int8),
149 "i16" | "int16_t" => Some(CType::Int16),
150 "i32" | "int32_t" => Some(CType::Int32),
151 "i64" | "int64_t" => Some(CType::Int64),
152 "u8" | "uint8_t" => Some(CType::UInt8),
153 "u16" | "uint16_t" => Some(CType::UInt16),
154 "u32" | "uint32_t" => Some(CType::UInt32),
155 "u64" | "uint64_t" => Some(CType::UInt64),
156 _ => None,
157 }
158 }
159}
160
161pub const C_TYPE_ALIASES: &[(&str, &str)] = &[
163 ("c_void", "()"),
165 ("c_char", "i8"), ("c_schar", "i8"),
168 ("c_uchar", "u8"),
169 ("c_short", "i16"),
171 ("c_ushort", "u16"),
172 ("c_int", "i32"),
173 ("c_uint", "u32"),
174 ("c_long", "i64"), ("c_ulong", "u64"),
176 ("c_longlong", "i64"),
177 ("c_ulonglong", "u64"),
178 ("c_float", "f32"),
180 ("c_double", "f64"),
181 ("size_t", "usize"),
183 ("ssize_t", "isize"),
184 ("ptrdiff_t", "isize"),
185 ("int8_t", "i8"),
187 ("int16_t", "i16"),
188 ("int32_t", "i32"),
189 ("int64_t", "i64"),
190 ("uint8_t", "u8"),
191 ("uint16_t", "u16"),
192 ("uint32_t", "u32"),
193 ("uint64_t", "u64"),
194];
195
196pub fn is_c_type(name: &str) -> bool {
198 CType::from_name(name).is_some()
199}
200
201#[cfg(test)]
202mod tests {
203 use super::*;
204
205 #[test]
206 fn test_c_type_parsing() {
207 assert_eq!(CType::from_name("c_int"), Some(CType::Int));
208 assert_eq!(CType::from_name("c_void"), Some(CType::Void));
209 assert_eq!(CType::from_name("size_t"), Some(CType::Size));
210 assert_eq!(CType::from_name("unknown"), None);
211 }
212
213 #[test]
214 fn test_c_type_sizes() {
215 assert_eq!(CType::Int.size_bytes(), 4);
216 assert_eq!(CType::Long.size_bytes(), 8);
217 assert_eq!(CType::Char.size_bytes(), 1);
218 assert_eq!(CType::Double.size_bytes(), 8);
219 }
220
221 #[test]
222 fn test_c_type_signedness() {
223 assert!(CType::Int.is_signed());
224 assert!(!CType::UInt.is_signed());
225 assert!(CType::SSize.is_signed());
226 assert!(!CType::Size.is_signed());
227 }
228}