Skip to main content

mtl_gpu/argument/
pointer_type.rs

1//! A pointer type for reflection.
2
3use std::ffi::c_void;
4use std::ptr::NonNull;
5
6use mtl_foundation::{Referencing, UInteger};
7use mtl_sys::{msg_send_0, sel};
8
9use crate::enums::{BindingAccess, DataType};
10
11use super::{ArrayType, StructType};
12
13/// A pointer type for reflection.
14///
15/// C++ equivalent: `MTL::PointerType`
16#[repr(transparent)]
17pub struct PointerType(pub(crate) NonNull<c_void>);
18
19impl PointerType {
20    /// Create from a raw pointer.
21    ///
22    /// # Safety
23    ///
24    /// The pointer must be a valid Metal PointerType.
25    #[inline]
26    pub unsafe fn from_raw(ptr: *mut c_void) -> Option<Self> {
27        NonNull::new(ptr).map(Self)
28    }
29
30    /// Get the raw pointer.
31    #[inline]
32    pub fn as_raw(&self) -> *mut c_void {
33        self.0.as_ptr()
34    }
35
36    /// Get the data type.
37    ///
38    /// C++ equivalent: `DataType dataType() const`
39    #[inline]
40    pub fn data_type(&self) -> DataType {
41        unsafe { msg_send_0(self.as_ptr(), sel!(dataType)) }
42    }
43
44    /// Get the access mode.
45    ///
46    /// C++ equivalent: `BindingAccess access() const`
47    #[inline]
48    pub fn access(&self) -> BindingAccess {
49        unsafe { msg_send_0(self.as_ptr(), sel!(access)) }
50    }
51
52    /// Get the alignment.
53    ///
54    /// C++ equivalent: `NS::UInteger alignment() const`
55    #[inline]
56    pub fn alignment(&self) -> UInteger {
57        unsafe { msg_send_0(self.as_ptr(), sel!(alignment)) }
58    }
59
60    /// Get the data size.
61    ///
62    /// C++ equivalent: `NS::UInteger dataSize() const`
63    #[inline]
64    pub fn data_size(&self) -> UInteger {
65        unsafe { msg_send_0(self.as_ptr(), sel!(dataSize)) }
66    }
67
68    /// Get the element type.
69    ///
70    /// C++ equivalent: `DataType elementType() const`
71    #[inline]
72    pub fn element_type(&self) -> DataType {
73        unsafe { msg_send_0(self.as_ptr(), sel!(elementType)) }
74    }
75
76    /// Check if the element is an argument buffer.
77    ///
78    /// C++ equivalent: `bool elementIsArgumentBuffer() const`
79    #[inline]
80    pub fn element_is_argument_buffer(&self) -> bool {
81        unsafe { msg_send_0(self.as_ptr(), sel!(elementIsArgumentBuffer)) }
82    }
83
84    /// Get the element array type (if element is an array).
85    ///
86    /// C++ equivalent: `ArrayType* elementArrayType()`
87    pub fn element_array_type(&self) -> Option<ArrayType> {
88        unsafe {
89            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(elementArrayType));
90            ArrayType::from_raw(ptr)
91        }
92    }
93
94    /// Get the element struct type (if element is a struct).
95    ///
96    /// C++ equivalent: `StructType* elementStructType()`
97    pub fn element_struct_type(&self) -> Option<StructType> {
98        unsafe {
99            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(elementStructType));
100            StructType::from_raw(ptr)
101        }
102    }
103}
104
105impl Clone for PointerType {
106    fn clone(&self) -> Self {
107        unsafe {
108            msg_send_0::<*mut c_void>(self.as_ptr(), sel!(retain));
109        }
110        Self(self.0)
111    }
112}
113
114impl Drop for PointerType {
115    fn drop(&mut self) {
116        unsafe {
117            msg_send_0::<()>(self.as_ptr(), sel!(release));
118        }
119    }
120}
121
122impl Referencing for PointerType {
123    #[inline]
124    fn as_ptr(&self) -> *const c_void {
125        self.0.as_ptr()
126    }
127}
128
129unsafe impl Send for PointerType {}
130unsafe impl Sync for PointerType {}