deno_libffi/middle/
types.rs1use libc;
10use std::fmt;
11use std::mem;
12use std::ptr;
13
14use crate::low;
15
16use super::util::Unique;
17
18type Type_ = *mut low::ffi_type;
23type TypeArray_ = *mut Type_;
24
25type Owned<T> = T;
28
29pub struct Type(Unique<low::ffi_type>);
54
55pub struct TypeArray(Unique<*mut low::ffi_type>);
60
61impl fmt::Debug for Type {
62 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
63 formatter.write_fmt(format_args!("Type({:?})", *self.0))
64 }
65}
66
67impl fmt::Debug for TypeArray {
68 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
69 formatter.write_fmt(format_args!("TypeArray({:?})", *self.0))
70 }
71}
72
73unsafe fn ffi_type_array_len(mut array: TypeArray_) -> usize {
76 let mut count = 0;
77 while !(*array).is_null() {
78 count += 1;
79 array = array.offset(1);
80 }
81 count
82}
83
84unsafe fn ffi_type_array_create_empty(len: usize) -> Owned<TypeArray_> {
86 let array = libc::malloc((len + 1) * mem::size_of::<Type_>()) as TypeArray_;
87 assert!(
88 !array.is_null(),
89 "ffi_type_array_create_empty: out of memory"
90 );
91 *array.add(len) = ptr::null_mut::<low::ffi_type>() as Type_;
92 array
93}
94
95unsafe fn ffi_type_array_create<I>(elements: I) -> Owned<TypeArray_>
98where
99 I: ExactSizeIterator<Item = Type>,
100{
101 let size = elements.len();
102 let new = ffi_type_array_create_empty(size);
103 for (i, element) in elements.enumerate() {
104 *new.add(i) = *element.0;
105 mem::forget(element);
106 }
107
108 new
109}
110
111unsafe fn ffi_type_struct_create_raw(elements: Owned<TypeArray_>) -> Owned<Type_> {
113 let new = libc::malloc(mem::size_of::<low::ffi_type>()) as Type_;
114 assert!(!new.is_null(), "ffi_type_struct_create_raw: out of memory");
115
116 (*new).size = 0;
117 (*new).alignment = 0;
118 (*new).type_ = low::type_tag::STRUCT;
119 (*new).elements = elements;
120
121 new
122}
123
124unsafe fn ffi_type_struct_create<I>(elements: I) -> Owned<Type_>
127where
128 I: ExactSizeIterator<Item = Type>,
129{
130 ffi_type_struct_create_raw(ffi_type_array_create(elements))
131}
132
133unsafe fn ffi_type_array_clone(old: TypeArray_) -> Owned<TypeArray_> {
135 let size = ffi_type_array_len(old);
136 let new = ffi_type_array_create_empty(size);
137
138 for i in 0..size {
139 *new.add(i) = ffi_type_clone(*old.add(i));
140 }
141
142 new
143}
144
145unsafe fn ffi_type_clone(old: Type_) -> Owned<Type_> {
147 if (*old).type_ == low::type_tag::STRUCT {
148 ffi_type_struct_create_raw(ffi_type_array_clone((*old).elements))
149 } else {
150 old
151 }
152}
153
154unsafe fn ffi_type_array_destroy(victim: Owned<TypeArray_>) {
156 let mut current = victim;
157 while !(*current).is_null() {
158 ffi_type_destroy(*current);
159 current = current.offset(1);
160 }
161
162 libc::free(victim as *mut libc::c_void);
163}
164
165unsafe fn ffi_type_destroy(victim: Owned<Type_>) {
167 if (*victim).type_ == low::type_tag::STRUCT {
168 ffi_type_array_destroy((*victim).elements);
169 libc::free(victim as *mut libc::c_void);
170 }
171}
172
173impl Drop for Type {
174 fn drop(&mut self) {
175 unsafe { ffi_type_destroy(*self.0) }
176 }
177}
178
179impl Drop for TypeArray {
180 fn drop(&mut self) {
181 unsafe { ffi_type_array_destroy(*self.0) }
182 }
183}
184
185impl Clone for Type {
186 fn clone(&self) -> Self {
187 Type(unsafe { Unique::new(ffi_type_clone(*self.0)) })
188 }
189}
190
191impl Clone for TypeArray {
192 fn clone(&self) -> Self {
193 TypeArray(unsafe { Unique::new(ffi_type_array_clone(*self.0)) })
194 }
195}
196
197macro_rules! match_size_signed {
198 ( $name:ident ) => {
199 match mem::size_of::<libc::$name>() {
200 1 => Self::i8(),
201 2 => Self::i16(),
202 4 => Self::i32(),
203 8 => Self::i64(),
204 _ => panic!("Strange size for C type"),
205 }
206 };
207}
208
209macro_rules! match_size_unsigned {
210 ( $name:ident ) => {
211 match mem::size_of::<libc::$name>() {
212 1 => Self::u8(),
213 2 => Self::u16(),
214 4 => Self::u32(),
215 8 => Self::u64(),
216 _ => panic!("Strange size for C type"),
217 }
218 };
219}
220
221impl Type {
222 pub fn void() -> Self {
227 Type(unsafe { Unique::new(&mut low::types::void) })
228 }
229
230 pub fn u8() -> Self {
232 Type(unsafe { Unique::new(&mut low::types::uint8) })
233 }
234
235 pub fn i8() -> Self {
237 Type(unsafe { Unique::new(&mut low::types::sint8) })
238 }
239
240 pub fn u16() -> Self {
242 Type(unsafe { Unique::new(&mut low::types::uint16) })
243 }
244
245 pub fn i16() -> Self {
247 Type(unsafe { Unique::new(&mut low::types::sint16) })
248 }
249
250 pub fn u32() -> Self {
252 Type(unsafe { Unique::new(&mut low::types::uint32) })
253 }
254
255 pub fn i32() -> Self {
257 Type(unsafe { Unique::new(&mut low::types::sint32) })
258 }
259
260 pub fn u64() -> Self {
262 Type(unsafe { Unique::new(&mut low::types::uint64) })
263 }
264
265 pub fn i64() -> Self {
267 Type(unsafe { Unique::new(&mut low::types::sint64) })
268 }
269
270 #[cfg(target_pointer_width = "16")]
271 pub fn usize() -> Self {
273 Self::u16()
274 }
275
276 #[cfg(target_pointer_width = "16")]
277 pub fn isize() -> Self {
279 Self::i16()
280 }
281
282 #[cfg(target_pointer_width = "32")]
283 pub fn usize() -> Self {
285 Self::u32()
286 }
287
288 #[cfg(target_pointer_width = "32")]
289 pub fn isize() -> Self {
291 Self::i32()
292 }
293
294 #[cfg(target_pointer_width = "64")]
295 pub fn usize() -> Self {
297 Self::u64()
298 }
299
300 #[cfg(target_pointer_width = "64")]
301 pub fn isize() -> Self {
303 Self::i64()
304 }
305
306 pub fn c_schar() -> Self {
308 match_size_signed!(c_schar)
309 }
310
311 pub fn c_uchar() -> Self {
313 match_size_unsigned!(c_uchar)
314 }
315
316 pub fn c_short() -> Self {
318 match_size_signed!(c_short)
319 }
320
321 pub fn c_ushort() -> Self {
323 match_size_unsigned!(c_ushort)
324 }
325
326 pub fn c_int() -> Self {
328 match_size_signed!(c_int)
329 }
330
331 pub fn c_uint() -> Self {
333 match_size_unsigned!(c_uint)
334 }
335
336 pub fn c_long() -> Self {
338 match_size_signed!(c_long)
339 }
340
341 pub fn c_ulong() -> Self {
343 match_size_unsigned!(c_ulong)
344 }
345
346 pub fn c_longlong() -> Self {
348 match_size_signed!(c_longlong)
349 }
350
351 pub fn c_ulonglong() -> Self {
353 match_size_unsigned!(c_ulonglong)
354 }
355
356 pub fn f32() -> Self {
358 Type(unsafe { Unique::new(&mut low::types::float) })
359 }
360
361 pub fn f64() -> Self {
363 Type(unsafe { Unique::new(&mut low::types::double) })
364 }
365
366 pub fn pointer() -> Self {
368 Type(unsafe { Unique::new(&mut low::types::pointer) })
369 }
370
371 #[cfg(not(all(target_arch = "arm")))]
373 pub fn longdouble() -> Self {
374 Type(unsafe { Unique::new(&mut low::types::longdouble) })
375 }
376
377 #[cfg(feature = "complex")]
381 pub fn c32() -> Self {
382 Type(unsafe { Unique::new(&mut low::types::complex_float) })
383 }
384
385 #[cfg(feature = "complex")]
389 pub fn c64() -> Self {
390 Type(unsafe { Unique::new(&mut low::types::complex_double) })
391 }
392
393 #[cfg(feature = "complex")]
397 #[cfg(not(all(target_arch = "arm")))]
398 pub fn complex_longdouble() -> Self {
399 Type(unsafe { Unique::new(&mut low::types::complex_longdouble) })
400 }
401
402 pub fn structure<I>(fields: I) -> Self
404 where
405 I: IntoIterator<Item = Type>,
406 I::IntoIter: ExactSizeIterator<Item = Type>,
407 {
408 Type(unsafe { Unique::new(ffi_type_struct_create(fields.into_iter())) })
409 }
410
411 pub fn as_raw_ptr(&self) -> *mut low::ffi_type {
418 *self.0
419 }
420}
421
422impl TypeArray {
423 pub fn new<I>(elements: I) -> Self
425 where
426 I: IntoIterator<Item = Type>,
427 I::IntoIter: ExactSizeIterator<Item = Type>,
428 {
429 TypeArray(unsafe { Unique::new(ffi_type_array_create(elements.into_iter())) })
430 }
431
432 pub fn as_raw_ptr(&self) -> *mut *mut low::ffi_type {
441 *self.0
442 }
443}
444
445#[cfg(test)]
446mod test {
447 use super::*;
448
449 #[test]
450 fn create_u64() {
451 Type::u64();
452 }
453
454 #[test]
455 fn clone_u64() {
456 let _ = Type::u64().clone().clone();
457 }
458
459 #[test]
460 fn create_struct() {
461 Type::structure(vec![Type::i64(), Type::i64(), Type::u64()]);
462 }
463
464 #[test]
465 fn clone_struct() {
466 let _ = Type::structure(vec![Type::i64(), Type::i64(), Type::u64()])
467 .clone()
468 .clone();
469 }
470}