Skip to main content

mtl_gpu/argument/
binding.rs

1//! Information about a binding.
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, BindingType};
10
11/// Information about a binding.
12///
13/// C++ equivalent: `MTL::Binding`
14#[repr(transparent)]
15pub struct Binding(pub(crate) NonNull<c_void>);
16
17impl Binding {
18    /// Create from a raw pointer.
19    ///
20    /// # Safety
21    ///
22    /// The pointer must be a valid Metal Binding.
23    #[inline]
24    pub unsafe fn from_raw(ptr: *mut c_void) -> Option<Self> {
25        NonNull::new(ptr).map(Self)
26    }
27
28    /// Get the raw pointer.
29    #[inline]
30    pub fn as_raw(&self) -> *mut c_void {
31        self.0.as_ptr()
32    }
33
34    /// Get the access mode.
35    ///
36    /// C++ equivalent: `BindingAccess access() const`
37    #[inline]
38    pub fn access(&self) -> BindingAccess {
39        unsafe { msg_send_0(self.as_ptr(), sel!(access)) }
40    }
41
42    /// Get the index.
43    ///
44    /// C++ equivalent: `NS::UInteger index() const`
45    #[inline]
46    pub fn index(&self) -> UInteger {
47        unsafe { msg_send_0(self.as_ptr(), sel!(index)) }
48    }
49
50    /// Check if this is an argument.
51    ///
52    /// C++ equivalent: `bool isArgument() const`
53    #[inline]
54    pub fn is_argument(&self) -> bool {
55        unsafe { msg_send_0(self.as_ptr(), sel!(isArgument)) }
56    }
57
58    /// Check if this binding is used.
59    ///
60    /// C++ equivalent: `bool isUsed() const`
61    #[inline]
62    pub fn is_used(&self) -> bool {
63        unsafe { msg_send_0(self.as_ptr(), sel!(isUsed)) }
64    }
65
66    /// Get the name.
67    ///
68    /// C++ equivalent: `NS::String* name() const`
69    pub fn name(&self) -> Option<String> {
70        unsafe {
71            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(name));
72            if ptr.is_null() {
73                return None;
74            }
75            let utf8_ptr: *const std::ffi::c_char =
76                mtl_sys::msg_send_0(ptr as *const c_void, sel!(UTF8String));
77            if utf8_ptr.is_null() {
78                return None;
79            }
80            let c_str = std::ffi::CStr::from_ptr(utf8_ptr);
81            Some(c_str.to_string_lossy().into_owned())
82        }
83    }
84
85    /// Get the binding type.
86    ///
87    /// C++ equivalent: `BindingType type() const`
88    #[inline]
89    pub fn binding_type(&self) -> BindingType {
90        unsafe { msg_send_0(self.as_ptr(), sel!(type)) }
91    }
92
93    /// Check if this is an argument (deprecated).
94    ///
95    /// C++ equivalent: `bool argument() const`
96    #[deprecated(note = "Use is_argument instead")]
97    #[inline]
98    pub fn argument(&self) -> bool {
99        unsafe { msg_send_0(self.as_ptr(), sel!(argument)) }
100    }
101
102    /// Check if this binding is used (deprecated).
103    ///
104    /// C++ equivalent: `bool used() const`
105    #[deprecated(note = "Use is_used instead")]
106    #[inline]
107    pub fn used(&self) -> bool {
108        unsafe { msg_send_0(self.as_ptr(), sel!(used)) }
109    }
110}
111
112impl Clone for Binding {
113    fn clone(&self) -> Self {
114        unsafe {
115            msg_send_0::<*mut c_void>(self.as_ptr(), sel!(retain));
116        }
117        Self(self.0)
118    }
119}
120
121impl Drop for Binding {
122    fn drop(&mut self) {
123        unsafe {
124            msg_send_0::<()>(self.as_ptr(), sel!(release));
125        }
126    }
127}
128
129impl Referencing for Binding {
130    #[inline]
131    fn as_ptr(&self) -> *const c_void {
132        self.0.as_ptr()
133    }
134}
135
136unsafe impl Send for Binding {}
137unsafe impl Sync for Binding {}