1use std::ffi::c_void;
9use std::ptr::NonNull;
10
11use mtl_foundation::{Referencing, UInteger};
12use mtl_sys::{msg_send_0, msg_send_1, sel};
13
14#[repr(transparent)]
22#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Hash)]
23pub struct StitchedLibraryOptions(pub UInteger);
24
25impl StitchedLibraryOptions {
26 pub const NONE: Self = Self(0);
27 pub const FAIL_ON_BINARY_ARCHIVE_MISS: Self = Self(1);
28 pub const STORE_LIBRARY_IN_METAL_PIPELINES_SCRIPT: Self = Self(1 << 1);
29}
30
31impl std::ops::BitOr for StitchedLibraryOptions {
32 type Output = Self;
33 fn bitor(self, rhs: Self) -> Self {
34 Self(self.0 | rhs.0)
35 }
36}
37
38impl std::ops::BitAnd for StitchedLibraryOptions {
39 type Output = Self;
40 fn bitand(self, rhs: Self) -> Self {
41 Self(self.0 & rhs.0)
42 }
43}
44
45impl std::ops::BitOrAssign for StitchedLibraryOptions {
46 fn bitor_assign(&mut self, rhs: Self) {
47 self.0 |= rhs.0;
48 }
49}
50
51#[repr(transparent)]
59pub struct FunctionStitchingAttribute(pub(crate) NonNull<c_void>);
60
61impl FunctionStitchingAttribute {
62 #[inline]
68 pub unsafe fn from_raw(ptr: *mut c_void) -> Option<Self> {
69 NonNull::new(ptr).map(Self)
70 }
71
72 #[inline]
74 pub fn as_raw(&self) -> *mut c_void {
75 self.0.as_ptr()
76 }
77}
78
79impl Clone for FunctionStitchingAttribute {
80 fn clone(&self) -> Self {
81 unsafe {
82 msg_send_0::<*mut c_void>(self.as_ptr(), sel!(retain));
83 }
84 Self(self.0)
85 }
86}
87
88impl Drop for FunctionStitchingAttribute {
89 fn drop(&mut self) {
90 unsafe {
91 msg_send_0::<()>(self.as_ptr(), sel!(release));
92 }
93 }
94}
95
96impl Referencing for FunctionStitchingAttribute {
97 #[inline]
98 fn as_ptr(&self) -> *const c_void {
99 self.0.as_ptr()
100 }
101}
102
103unsafe impl Send for FunctionStitchingAttribute {}
104unsafe impl Sync for FunctionStitchingAttribute {}
105
106#[repr(transparent)]
114pub struct FunctionStitchingAttributeAlwaysInline(pub(crate) NonNull<c_void>);
115
116impl FunctionStitchingAttributeAlwaysInline {
117 pub fn new() -> Option<Self> {
121 unsafe {
122 let class = mtl_sys::Class::get("MTLFunctionStitchingAttributeAlwaysInline")?;
123 let ptr: *mut c_void = msg_send_0(class.as_ptr(), sel!(alloc));
124 if ptr.is_null() {
125 return None;
126 }
127 let ptr: *mut c_void = msg_send_0(ptr, sel!(init));
128 Self::from_raw(ptr)
129 }
130 }
131
132 #[inline]
138 pub unsafe fn from_raw(ptr: *mut c_void) -> Option<Self> {
139 NonNull::new(ptr).map(Self)
140 }
141
142 #[inline]
144 pub fn as_raw(&self) -> *mut c_void {
145 self.0.as_ptr()
146 }
147}
148
149impl Clone for FunctionStitchingAttributeAlwaysInline {
150 fn clone(&self) -> Self {
151 unsafe {
152 msg_send_0::<*mut c_void>(self.as_ptr(), sel!(retain));
153 }
154 Self(self.0)
155 }
156}
157
158impl Drop for FunctionStitchingAttributeAlwaysInline {
159 fn drop(&mut self) {
160 unsafe {
161 msg_send_0::<()>(self.as_ptr(), sel!(release));
162 }
163 }
164}
165
166impl Referencing for FunctionStitchingAttributeAlwaysInline {
167 #[inline]
168 fn as_ptr(&self) -> *const c_void {
169 self.0.as_ptr()
170 }
171}
172
173unsafe impl Send for FunctionStitchingAttributeAlwaysInline {}
174unsafe impl Sync for FunctionStitchingAttributeAlwaysInline {}
175
176#[repr(transparent)]
184pub struct FunctionStitchingNode(pub(crate) NonNull<c_void>);
185
186impl FunctionStitchingNode {
187 #[inline]
193 pub unsafe fn from_raw(ptr: *mut c_void) -> Option<Self> {
194 NonNull::new(ptr).map(Self)
195 }
196
197 #[inline]
199 pub fn as_raw(&self) -> *mut c_void {
200 self.0.as_ptr()
201 }
202}
203
204impl Clone for FunctionStitchingNode {
205 fn clone(&self) -> Self {
206 unsafe {
207 let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(copy));
208 Self::from_raw(ptr).expect("copy should succeed")
209 }
210 }
211}
212
213impl Drop for FunctionStitchingNode {
214 fn drop(&mut self) {
215 unsafe {
216 msg_send_0::<()>(self.as_ptr(), sel!(release));
217 }
218 }
219}
220
221impl Referencing for FunctionStitchingNode {
222 #[inline]
223 fn as_ptr(&self) -> *const c_void {
224 self.0.as_ptr()
225 }
226}
227
228unsafe impl Send for FunctionStitchingNode {}
229unsafe impl Sync for FunctionStitchingNode {}
230
231#[repr(transparent)]
239pub struct FunctionStitchingInputNode(pub(crate) NonNull<c_void>);
240
241impl FunctionStitchingInputNode {
242 pub fn new() -> Option<Self> {
246 unsafe {
247 let class = mtl_sys::Class::get("MTLFunctionStitchingInputNode")?;
248 let ptr: *mut c_void = msg_send_0(class.as_ptr(), sel!(alloc));
249 if ptr.is_null() {
250 return None;
251 }
252 let ptr: *mut c_void = msg_send_0(ptr, sel!(init));
253 Self::from_raw(ptr)
254 }
255 }
256
257 pub fn with_argument_index(argument_index: UInteger) -> Option<Self> {
261 unsafe {
262 let class = mtl_sys::Class::get("MTLFunctionStitchingInputNode")?;
263 let ptr: *mut c_void = msg_send_0(class.as_ptr(), sel!(alloc));
264 if ptr.is_null() {
265 return None;
266 }
267 let ptr: *mut c_void = msg_send_1(ptr, sel!(initWithArgumentIndex:), argument_index);
268 Self::from_raw(ptr)
269 }
270 }
271
272 #[inline]
278 pub unsafe fn from_raw(ptr: *mut c_void) -> Option<Self> {
279 NonNull::new(ptr).map(Self)
280 }
281
282 #[inline]
284 pub fn as_raw(&self) -> *mut c_void {
285 self.0.as_ptr()
286 }
287
288 #[inline]
292 pub fn argument_index(&self) -> UInteger {
293 unsafe { msg_send_0(self.as_ptr(), sel!(argumentIndex)) }
294 }
295
296 pub fn set_argument_index(&self, argument_index: UInteger) {
300 unsafe {
301 let _: () = msg_send_1(self.as_ptr(), sel!(setArgumentIndex:), argument_index);
302 }
303 }
304}
305
306impl Clone for FunctionStitchingInputNode {
307 fn clone(&self) -> Self {
308 unsafe {
309 msg_send_0::<*mut c_void>(self.as_ptr(), sel!(retain));
310 }
311 Self(self.0)
312 }
313}
314
315impl Drop for FunctionStitchingInputNode {
316 fn drop(&mut self) {
317 unsafe {
318 msg_send_0::<()>(self.as_ptr(), sel!(release));
319 }
320 }
321}
322
323impl Referencing for FunctionStitchingInputNode {
324 #[inline]
325 fn as_ptr(&self) -> *const c_void {
326 self.0.as_ptr()
327 }
328}
329
330unsafe impl Send for FunctionStitchingInputNode {}
331unsafe impl Sync for FunctionStitchingInputNode {}
332
333#[repr(transparent)]
341pub struct FunctionStitchingFunctionNode(pub(crate) NonNull<c_void>);
342
343impl FunctionStitchingFunctionNode {
344 pub fn new() -> Option<Self> {
348 unsafe {
349 let class = mtl_sys::Class::get("MTLFunctionStitchingFunctionNode")?;
350 let ptr: *mut c_void = msg_send_0(class.as_ptr(), sel!(alloc));
351 if ptr.is_null() {
352 return None;
353 }
354 let ptr: *mut c_void = msg_send_0(ptr, sel!(init));
355 Self::from_raw(ptr)
356 }
357 }
358
359 #[inline]
365 pub unsafe fn from_raw(ptr: *mut c_void) -> Option<Self> {
366 NonNull::new(ptr).map(Self)
367 }
368
369 #[inline]
371 pub fn as_raw(&self) -> *mut c_void {
372 self.0.as_ptr()
373 }
374
375 pub fn name(&self) -> Option<String> {
379 unsafe {
380 let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(name));
381 if ptr.is_null() {
382 return None;
383 }
384 let utf8_ptr: *const std::ffi::c_char =
385 mtl_sys::msg_send_0(ptr as *const c_void, sel!(UTF8String));
386 if utf8_ptr.is_null() {
387 return None;
388 }
389 let c_str = std::ffi::CStr::from_ptr(utf8_ptr);
390 Some(c_str.to_string_lossy().into_owned())
391 }
392 }
393
394 pub fn set_name(&self, name: &str) {
398 if let Some(ns_name) = mtl_foundation::String::from_str(name) {
399 unsafe {
400 let _: () = msg_send_1(self.as_ptr(), sel!(setName:), ns_name.as_ptr());
401 }
402 }
403 }
404
405 #[inline]
409 pub fn arguments_ptr(&self) -> *const c_void {
410 unsafe { msg_send_0(self.as_ptr(), sel!(arguments)) }
411 }
412
413 pub fn set_arguments_ptr(&self, arguments: *const c_void) {
417 unsafe {
418 let _: () = msg_send_1(self.as_ptr(), sel!(setArguments:), arguments);
419 }
420 }
421
422 #[inline]
426 pub fn control_dependencies_ptr(&self) -> *const c_void {
427 unsafe { msg_send_0(self.as_ptr(), sel!(controlDependencies)) }
428 }
429
430 pub fn set_control_dependencies_ptr(&self, control_dependencies: *const c_void) {
434 unsafe {
435 let _: () = msg_send_1(
436 self.as_ptr(),
437 sel!(setControlDependencies:),
438 control_dependencies,
439 );
440 }
441 }
442}
443
444impl Clone for FunctionStitchingFunctionNode {
445 fn clone(&self) -> Self {
446 unsafe {
447 msg_send_0::<*mut c_void>(self.as_ptr(), sel!(retain));
448 }
449 Self(self.0)
450 }
451}
452
453impl Drop for FunctionStitchingFunctionNode {
454 fn drop(&mut self) {
455 unsafe {
456 msg_send_0::<()>(self.as_ptr(), sel!(release));
457 }
458 }
459}
460
461impl Referencing for FunctionStitchingFunctionNode {
462 #[inline]
463 fn as_ptr(&self) -> *const c_void {
464 self.0.as_ptr()
465 }
466}
467
468unsafe impl Send for FunctionStitchingFunctionNode {}
469unsafe impl Sync for FunctionStitchingFunctionNode {}
470
471#[repr(transparent)]
479pub struct FunctionStitchingGraph(pub(crate) NonNull<c_void>);
480
481impl FunctionStitchingGraph {
482 pub fn new() -> Option<Self> {
486 unsafe {
487 let class = mtl_sys::Class::get("MTLFunctionStitchingGraph")?;
488 let ptr: *mut c_void = msg_send_0(class.as_ptr(), sel!(alloc));
489 if ptr.is_null() {
490 return None;
491 }
492 let ptr: *mut c_void = msg_send_0(ptr, sel!(init));
493 Self::from_raw(ptr)
494 }
495 }
496
497 #[inline]
503 pub unsafe fn from_raw(ptr: *mut c_void) -> Option<Self> {
504 NonNull::new(ptr).map(Self)
505 }
506
507 #[inline]
509 pub fn as_raw(&self) -> *mut c_void {
510 self.0.as_ptr()
511 }
512
513 pub fn function_name(&self) -> Option<String> {
517 unsafe {
518 let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(functionName));
519 if ptr.is_null() {
520 return None;
521 }
522 let utf8_ptr: *const std::ffi::c_char =
523 mtl_sys::msg_send_0(ptr as *const c_void, sel!(UTF8String));
524 if utf8_ptr.is_null() {
525 return None;
526 }
527 let c_str = std::ffi::CStr::from_ptr(utf8_ptr);
528 Some(c_str.to_string_lossy().into_owned())
529 }
530 }
531
532 pub fn set_function_name(&self, name: &str) {
536 if let Some(ns_name) = mtl_foundation::String::from_str(name) {
537 unsafe {
538 let _: () = msg_send_1(self.as_ptr(), sel!(setFunctionName:), ns_name.as_ptr());
539 }
540 }
541 }
542
543 #[inline]
547 pub fn nodes_ptr(&self) -> *const c_void {
548 unsafe { msg_send_0(self.as_ptr(), sel!(nodes)) }
549 }
550
551 pub fn set_nodes_ptr(&self, nodes: *const c_void) {
555 unsafe {
556 let _: () = msg_send_1(self.as_ptr(), sel!(setNodes:), nodes);
557 }
558 }
559
560 pub fn output_node(&self) -> Option<FunctionStitchingFunctionNode> {
564 unsafe {
565 let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(outputNode));
566 if ptr.is_null() {
567 return None;
568 }
569 msg_send_0::<*mut c_void>(ptr as *const c_void, sel!(retain));
571 FunctionStitchingFunctionNode::from_raw(ptr)
572 }
573 }
574
575 pub fn set_output_node(&self, output_node: &FunctionStitchingFunctionNode) {
579 unsafe {
580 let _: () = msg_send_1(self.as_ptr(), sel!(setOutputNode:), output_node.as_ptr());
581 }
582 }
583
584 #[inline]
588 pub fn attributes_ptr(&self) -> *const c_void {
589 unsafe { msg_send_0(self.as_ptr(), sel!(attributes)) }
590 }
591
592 pub fn set_attributes_ptr(&self, attributes: *const c_void) {
596 unsafe {
597 let _: () = msg_send_1(self.as_ptr(), sel!(setAttributes:), attributes);
598 }
599 }
600}
601
602impl Clone for FunctionStitchingGraph {
603 fn clone(&self) -> Self {
604 unsafe {
605 let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(copy));
606 Self::from_raw(ptr).expect("copy should succeed")
607 }
608 }
609}
610
611impl Drop for FunctionStitchingGraph {
612 fn drop(&mut self) {
613 unsafe {
614 msg_send_0::<()>(self.as_ptr(), sel!(release));
615 }
616 }
617}
618
619impl Referencing for FunctionStitchingGraph {
620 #[inline]
621 fn as_ptr(&self) -> *const c_void {
622 self.0.as_ptr()
623 }
624}
625
626unsafe impl Send for FunctionStitchingGraph {}
627unsafe impl Sync for FunctionStitchingGraph {}
628
629#[repr(transparent)]
637pub struct StitchedLibraryDescriptor(pub(crate) NonNull<c_void>);
638
639impl StitchedLibraryDescriptor {
640 pub fn new() -> Option<Self> {
644 unsafe {
645 let class = mtl_sys::Class::get("MTLStitchedLibraryDescriptor")?;
646 let ptr: *mut c_void = msg_send_0(class.as_ptr(), sel!(alloc));
647 if ptr.is_null() {
648 return None;
649 }
650 let ptr: *mut c_void = msg_send_0(ptr, sel!(init));
651 Self::from_raw(ptr)
652 }
653 }
654
655 #[inline]
661 pub unsafe fn from_raw(ptr: *mut c_void) -> Option<Self> {
662 NonNull::new(ptr).map(Self)
663 }
664
665 #[inline]
667 pub fn as_raw(&self) -> *mut c_void {
668 self.0.as_ptr()
669 }
670
671 #[inline]
675 pub fn function_graphs_ptr(&self) -> *const c_void {
676 unsafe { msg_send_0(self.as_ptr(), sel!(functionGraphs)) }
677 }
678
679 pub fn set_function_graphs_ptr(&self, function_graphs: *const c_void) {
683 unsafe {
684 let _: () = msg_send_1(self.as_ptr(), sel!(setFunctionGraphs:), function_graphs);
685 }
686 }
687
688 #[inline]
692 pub fn functions_ptr(&self) -> *const c_void {
693 unsafe { msg_send_0(self.as_ptr(), sel!(functions)) }
694 }
695
696 pub fn set_functions_ptr(&self, functions: *const c_void) {
700 unsafe {
701 let _: () = msg_send_1(self.as_ptr(), sel!(setFunctions:), functions);
702 }
703 }
704
705 #[inline]
709 pub fn binary_archives_ptr(&self) -> *const c_void {
710 unsafe { msg_send_0(self.as_ptr(), sel!(binaryArchives)) }
711 }
712
713 pub fn set_binary_archives_ptr(&self, binary_archives: *const c_void) {
717 unsafe {
718 let _: () = msg_send_1(self.as_ptr(), sel!(setBinaryArchives:), binary_archives);
719 }
720 }
721
722 #[inline]
726 pub fn options(&self) -> StitchedLibraryOptions {
727 unsafe { msg_send_0(self.as_ptr(), sel!(options)) }
728 }
729
730 pub fn set_options(&self, options: StitchedLibraryOptions) {
734 unsafe {
735 let _: () = msg_send_1(self.as_ptr(), sel!(setOptions:), options);
736 }
737 }
738}
739
740impl Default for StitchedLibraryDescriptor {
741 fn default() -> Self {
742 Self::new().expect("failed to create StitchedLibraryDescriptor")
743 }
744}
745
746impl Clone for StitchedLibraryDescriptor {
747 fn clone(&self) -> Self {
748 unsafe {
749 let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(copy));
750 Self::from_raw(ptr).expect("copy should succeed")
751 }
752 }
753}
754
755impl Drop for StitchedLibraryDescriptor {
756 fn drop(&mut self) {
757 unsafe {
758 msg_send_0::<()>(self.as_ptr(), sel!(release));
759 }
760 }
761}
762
763impl Referencing for StitchedLibraryDescriptor {
764 #[inline]
765 fn as_ptr(&self) -> *const c_void {
766 self.0.as_ptr()
767 }
768}
769
770unsafe impl Send for StitchedLibraryDescriptor {}
771unsafe impl Sync for StitchedLibraryDescriptor {}
772
773#[cfg(test)]
774mod tests {
775 use super::*;
776
777 #[test]
778 fn test_stitched_library_options_values() {
779 assert_eq!(StitchedLibraryOptions::NONE.0, 0);
780 assert_eq!(StitchedLibraryOptions::FAIL_ON_BINARY_ARCHIVE_MISS.0, 1);
781 assert_eq!(
782 StitchedLibraryOptions::STORE_LIBRARY_IN_METAL_PIPELINES_SCRIPT.0,
783 2
784 );
785 }
786
787 #[test]
788 fn test_stitched_library_options_bitor() {
789 let options = StitchedLibraryOptions::FAIL_ON_BINARY_ARCHIVE_MISS
790 | StitchedLibraryOptions::STORE_LIBRARY_IN_METAL_PIPELINES_SCRIPT;
791 assert_eq!(options.0, 3);
792 }
793
794 #[test]
795 fn test_function_stitching_attribute_size() {
796 assert_eq!(
797 std::mem::size_of::<FunctionStitchingAttribute>(),
798 std::mem::size_of::<*mut c_void>()
799 );
800 }
801
802 #[test]
803 fn test_function_stitching_input_node_creation() {
804 let node = FunctionStitchingInputNode::new();
805 assert!(node.is_some());
806 }
807
808 #[test]
809 fn test_function_stitching_input_node_with_index() {
810 let node = FunctionStitchingInputNode::with_argument_index(5);
811 assert!(node.is_some());
812 if let Some(n) = node {
813 assert_eq!(n.argument_index(), 5);
814 }
815 }
816
817 #[test]
818 fn test_function_stitching_function_node_creation() {
819 let node = FunctionStitchingFunctionNode::new();
820 assert!(node.is_some());
821 }
822
823 #[test]
824 fn test_function_stitching_graph_creation() {
825 let graph = FunctionStitchingGraph::new();
826 assert!(graph.is_some());
827 }
828
829 #[test]
830 fn test_stitched_library_descriptor_creation() {
831 let descriptor = StitchedLibraryDescriptor::new();
832 assert!(descriptor.is_some());
833 }
834
835 #[test]
836 fn test_stitched_library_descriptor_options() {
837 let descriptor = StitchedLibraryDescriptor::new().unwrap();
838 descriptor.set_options(StitchedLibraryOptions::FAIL_ON_BINARY_ARCHIVE_MISS);
839 assert_eq!(
840 descriptor.options(),
841 StitchedLibraryOptions::FAIL_ON_BINARY_ARCHIVE_MISS
842 );
843 }
844}