diff options
Diffstat (limited to 'third_party/rust/metal/src/library.rs')
-rw-r--r-- | third_party/rust/metal/src/library.rs | 982 |
1 files changed, 982 insertions, 0 deletions
diff --git a/third_party/rust/metal/src/library.rs b/third_party/rust/metal/src/library.rs new file mode 100644 index 0000000000..9a5a36b62e --- /dev/null +++ b/third_party/rust/metal/src/library.rs @@ -0,0 +1,982 @@ +// Copyright 2017 GFX developers +// +// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or +// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or +// http://opensource.org/licenses/MIT>, at your option. This file may not be +// copied, modified, or distributed except according to those terms. + +use super::*; + +use foreign_types::ForeignType; +use objc::runtime::{Object, BOOL, NO, YES}; + +use std::ffi::CStr; +use std::os::raw::{c_char, c_void}; +use std::ptr; + +/// Only available on (macos(10.12), ios(10.0) +#[repr(u64)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] +pub enum MTLPatchType { + None = 0, + Triangle = 1, + Quad = 2, +} + +pub enum MTLVertexAttribute {} + +foreign_obj_type! { + type CType = MTLVertexAttribute; + pub struct VertexAttribute; + pub struct VertexAttributeRef; +} + +impl VertexAttributeRef { + pub fn name(&self) -> &str { + unsafe { + let name = msg_send![self, name]; + crate::nsstring_as_str(name) + } + } + + pub fn attribute_index(&self) -> u64 { + unsafe { msg_send![self, attributeIndex] } + } + + pub fn attribute_type(&self) -> MTLDataType { + unsafe { msg_send![self, attributeType] } + } + + pub fn is_active(&self) -> bool { + unsafe { + match msg_send![self, isActive] { + YES => true, + NO => false, + _ => unreachable!(), + } + } + } + + /// Only available on (macos(10.12), ios(10.0) + pub fn is_patch_data(&self) -> bool { + unsafe { + match msg_send![self, isPatchData] { + YES => true, + NO => false, + _ => unreachable!(), + } + } + } + + /// Only available on (macos(10.12), ios(10.0) + pub fn is_patch_control_point_data(&self) -> bool { + unsafe { + match msg_send![self, isPatchControlPointData] { + YES => true, + NO => false, + _ => unreachable!(), + } + } + } +} + +/// Only available on (macos(10.12), ios(10.0)) +pub enum MTLAttribute {} + +foreign_obj_type! { + type CType = MTLAttribute; + pub struct Attribute; + pub struct AttributeRef; +} + +impl AttributeRef { + pub fn name(&self) -> &str { + unsafe { + let name = msg_send![self, name]; + crate::nsstring_as_str(name) + } + } + + pub fn attribute_index(&self) -> u64 { + unsafe { msg_send![self, attributeIndex] } + } + + pub fn attribute_type(&self) -> MTLDataType { + unsafe { msg_send![self, attributeType] } + } + + pub fn is_active(&self) -> bool { + unsafe { + match msg_send![self, isActive] { + YES => true, + NO => false, + _ => unreachable!(), + } + } + } + + /// Only available on (macos(10.12), ios(10.0)) + pub fn is_patch_data(&self) -> bool { + unsafe { + match msg_send![self, isPatchData] { + YES => true, + NO => false, + _ => unreachable!(), + } + } + } + + /// Only available on (macos(10.12), ios(10.0)) + pub fn is_patch_control_point_data(&self) -> bool { + unsafe { + match msg_send![self, isPatchControlPointData] { + YES => true, + NO => false, + _ => unreachable!(), + } + } + } +} + +#[repr(u64)] +#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] +pub enum MTLFunctionType { + Vertex = 1, + Fragment = 2, + Kernel = 3, + /// Only available on (macos(11.0), ios(14.0)) + Visible = 5, + /// Only available on (macos(11.0), ios(14.0)) + Intersection = 6, +} + +/// Only available on (macos(10.12), ios(10.0)) +pub enum MTLFunctionConstant {} + +foreign_obj_type! { + type CType = MTLFunctionConstant; + pub struct FunctionConstant; + pub struct FunctionConstantRef; +} + +impl FunctionConstantRef { + pub fn name(&self) -> &str { + unsafe { + let name = msg_send![self, name]; + crate::nsstring_as_str(name) + } + } + + pub fn data_type(&self) -> MTLDataType { + unsafe { msg_send![self, type] } + } + + pub fn index(&self) -> NSUInteger { + unsafe { msg_send![self, index] } + } + + pub fn required(&self) -> bool { + unsafe { + match msg_send![self, required] { + YES => true, + NO => false, + _ => unreachable!(), + } + } + } +} + +bitflags! { + /// Only available on (macos(11.0), ios(14.0)) + pub struct MTLFunctionOptions: NSUInteger { + const None = 0; + const CompileToBinary = 1 << 0; + } +} + +/// Only available on (macos(11.0), ios(14.0)) +pub enum MTLFunctionDescriptor {} + +foreign_obj_type! { + type CType = MTLFunctionDescriptor; + pub struct FunctionDescriptor; + pub struct FunctionDescriptorRef; +} + +impl FunctionDescriptor { + pub fn new() -> Self { + unsafe { + let class = class!(MTLFunctionDescriptor); + msg_send![class, new] + } + } +} + +impl FunctionDescriptorRef { + pub fn name(&self) -> &str { + unsafe { + let name = msg_send![self, name]; + crate::nsstring_as_str(name) + } + } + + pub fn set_name(&self, name: &str) { + unsafe { + let ns_name = crate::nsstring_from_str(name); + let () = msg_send![self, setName: ns_name]; + } + } + + pub fn specialized_name(&self) -> &str { + unsafe { + let name = msg_send![self, specializedName]; + crate::nsstring_as_str(name) + } + } + + pub fn set_specialized_name(&self, name: &str) { + unsafe { + let ns_name = crate::nsstring_from_str(name); + let () = msg_send![self, setSpecializedName: ns_name]; + } + } + + pub fn constant_values(&self) -> &FunctionConstantValuesRef { + unsafe { msg_send![self, constantValues] } + } + + pub fn set_constant_values(&self, values: &FunctionConstantValuesRef) { + unsafe { msg_send![self, setConstantValues: values] } + } + + pub fn options(&self) -> MTLFunctionOptions { + unsafe { msg_send![self, options] } + } + + pub fn set_options(&self, options: MTLFunctionOptions) { + unsafe { msg_send![self, setOptions: options] } + } +} + +/// Only available on (macos(11.0), ios(14.0)) +pub enum MTLIntersectionFunctionDescriptor {} + +foreign_obj_type! { + type CType = MTLIntersectionFunctionDescriptor; + pub struct IntersectionFunctionDescriptor; + pub struct IntersectionFunctionDescriptorRef; + type ParentType = FunctionDescriptorRef; +} + +/// Only available on (macos(11.0), ios(14.0)) +pub enum MTLFunctionHandle {} + +foreign_obj_type! { + type CType = MTLFunctionHandle; + pub struct FunctionHandle; + pub struct FunctionHandleRef; +} + +impl FunctionHandleRef { + pub fn device(&self) -> &DeviceRef { + unsafe { msg_send![self, device] } + } + + pub fn name(&self) -> &str { + unsafe { + let ns_name = msg_send![self, name]; + crate::nsstring_as_str(ns_name) + } + } + + pub fn function_type(&self) -> MTLFunctionType { + unsafe { msg_send![self, functionType] } + } +} + +// TODO: +// MTLVisibleFunctionTableDescriptor +// MTLVisibleFunctionTable +// MTLIntersectionFunctionSignature +// MTLIntersectionFunctionTableDescriptor +// MTLIntersectionFunctionTable + +pub enum MTLFunction {} + +foreign_obj_type! { + type CType = MTLFunction; + pub struct Function; + pub struct FunctionRef; +} + +impl FunctionRef { + pub fn device(&self) -> &DeviceRef { + unsafe { msg_send![self, device] } + } + + /// Only available on (macos(10.12), ios(10.0)) + pub fn label(&self) -> &str { + unsafe { + let ns_label = msg_send![self, label]; + crate::nsstring_as_str(ns_label) + } + } + + /// Only available on (macos(10.12), ios(10.0)) + pub fn set_label(&self, label: &str) { + unsafe { + let ns_label = crate::nsstring_from_str(label); + let () = msg_send![self, setLabel: ns_label]; + } + } + + pub fn name(&self) -> &str { + unsafe { + let name = msg_send![self, name]; + crate::nsstring_as_str(name) + } + } + + pub fn function_type(&self) -> MTLFunctionType { + unsafe { msg_send![self, functionType] } + } + + /// Only available on (macos(10.12), ios(10.0)) + pub fn patch_type(&self) -> MTLPatchType { + unsafe { msg_send![self, patchType] } + } + + /// Only available on (macos(10.12), ios(10.0)) + pub fn patch_control_point_count(&self) -> NSUInteger { + unsafe { msg_send![self, patchControlPointCount] } + } + + /// Only available on (macos(10.12), ios(10.0)) + pub fn vertex_attributes(&self) -> &Array<VertexAttribute> { + unsafe { msg_send![self, vertexAttributes] } + } + + /// Only available on (macos(10.12), ios(10.0)) + pub fn stage_input_attributes(&self) -> &Array<Attribute> { + unsafe { msg_send![self, stageInputAttributes] } + } + + pub fn new_argument_encoder(&self, buffer_index: NSUInteger) -> ArgumentEncoder { + unsafe { + let ptr = msg_send![self, newArgumentEncoderWithBufferIndex: buffer_index]; + ArgumentEncoder::from_ptr(ptr) + } + } + + pub fn function_constants_dictionary(&self) -> *mut Object { + unsafe { msg_send![self, functionConstantsDictionary] } + } + + /// Only available on (macos(11.0), ios(14.0)) + pub fn options(&self) -> MTLFunctionOptions { + unsafe { msg_send![self, options] } + } +} + +#[repr(u64)] +#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)] +pub enum MTLLanguageVersion { + V1_0 = 0x10000, + V1_1 = 0x10001, + V1_2 = 0x10002, + V2_0 = 0x20000, + V2_1 = 0x20001, + V2_2 = 0x20002, + /// available on macOS 11.0+, iOS 14.0+ + V2_3 = 0x20003, + /// available on macOS 12.0+, iOS 15.0+ + V2_4 = 0x20004, +} + +pub enum MTLFunctionConstantValues {} + +foreign_obj_type! { + type CType = MTLFunctionConstantValues; + pub struct FunctionConstantValues; + pub struct FunctionConstantValuesRef; +} + +impl FunctionConstantValues { + pub fn new() -> Self { + unsafe { + let class = class!(MTLFunctionConstantValues); + msg_send![class, new] + } + } +} + +impl FunctionConstantValuesRef { + pub fn set_constant_value_at_index( + &self, + value: *const c_void, + ty: MTLDataType, + index: NSUInteger, + ) { + unsafe { msg_send![self, setConstantValue:value type:ty atIndex:index] } + } + + pub fn set_constant_values_with_range( + &self, + values: *const c_void, + ty: MTLDataType, + range: NSRange, + ) { + unsafe { msg_send![self, setConstantValues:values type:ty withRange:range] } + } + + pub fn set_constant_value_with_name(&self, value: *const c_void, ty: MTLDataType, name: &str) { + unsafe { + let ns_name = crate::nsstring_from_str(name); + msg_send![self, setConstantValue:value type:ty withName:ns_name] + } + } +} + +/// Only available on (macos(11.0), ios(14.0)) +#[repr(u64)] +#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] +pub enum MTLLibraryType { + Executable = 0, + Dynamic = 1, +} + +pub enum MTLCompileOptions {} + +foreign_obj_type! { + type CType = MTLCompileOptions; + pub struct CompileOptions; + pub struct CompileOptionsRef; +} + +impl CompileOptions { + pub fn new() -> Self { + unsafe { + let class = class!(MTLCompileOptions); + msg_send![class, new] + } + } +} + +impl CompileOptionsRef { + pub unsafe fn preprocessor_macros(&self) -> *mut Object { + msg_send![self, preprocessorMacros] + } + + pub unsafe fn set_preprocessor_macros(&self, defines: *mut Object) { + msg_send![self, setPreprocessorMacros: defines] + } + + pub fn is_fast_math_enabled(&self) -> bool { + unsafe { + match msg_send![self, fastMathEnabled] { + YES => true, + NO => false, + _ => unreachable!(), + } + } + } + + pub fn set_fast_math_enabled(&self, enabled: bool) { + unsafe { msg_send![self, setFastMathEnabled: enabled] } + } + + /// Only available on (macos(10.11), ios(9.0)) + pub fn language_version(&self) -> MTLLanguageVersion { + unsafe { msg_send![self, languageVersion] } + } + + /// Only available on (macos(10.11), ios(9.0)) + pub fn set_language_version(&self, version: MTLLanguageVersion) { + unsafe { msg_send![self, setLanguageVersion: version] } + } + + /// Only available on (macos(11.0), ios(14.0)) + pub fn library_type(&self) -> MTLLibraryType { + unsafe { msg_send![self, libraryType] } + } + + /// Only available on (macos(11.0), ios(14.0)) + pub fn set_library_type(&self, lib_type: MTLLibraryType) { + unsafe { msg_send![self, setLibraryType: lib_type] } + } + + /// Only available on (macos(11.0), ios(14.0)) + pub fn install_name(&self) -> &str { + unsafe { + let name = msg_send![self, installName]; + crate::nsstring_as_str(name) + } + } + + /// Only available on (macos(11.0), ios(14.0)) + pub fn set_install_name(&self, name: &str) { + unsafe { + let install_name = crate::nsstring_from_str(name); + let () = msg_send![self, setInstallName: install_name]; + } + } + + /// Only available on (macos(11.0), ios(14.0)) + /// + /// Marshal to Rust Vec + pub fn libraries(&self) -> Vec<DynamicLibrary> { + unsafe { + let libraries: *mut Object = msg_send![self, libraries]; + let count: NSUInteger = msg_send![libraries, count]; + let ret = (0..count) + .map(|i| { + let lib = msg_send![libraries, objectAtIndex: i]; + DynamicLibrary::from_ptr(lib) + }) + .collect(); + ret + } + } + + /// Only available on (macos(11.0), ios(14.0)) + /// + /// As raw NSArray + pub fn libraries_as_nsarray(&self) -> &ArrayRef<DynamicLibrary> { + unsafe { msg_send![self, libraries] } + } + + /// Only available on (macos(11.0), ios(14.0)) + /// + /// Marshal from Rust slice + pub fn set_libraries(&self, libraries: &[&DynamicLibraryRef]) { + let ns_array = Array::<DynamicLibrary>::from_slice(libraries); + unsafe { msg_send![self, setLibraries: ns_array] } + } + + /// Only available on (macos(11.0), ios(14.0)) + /// + /// From raw NSArray + pub fn set_libraries_nsarray(&self, libraries: &ArrayRef<DynamicLibrary>) { + unsafe { msg_send![self, setLibraries: libraries] } + } + + /// Only available on (macos(11.0), macCatalyst(14.0), ios(13.0)) + pub fn preserve_invariance(&self) -> bool { + unsafe { + match msg_send![self, preserveInvariance] { + YES => true, + NO => false, + _ => unreachable!(), + } + } + } + + /// Only available on (macos(11.0), macCatalyst(14.0), ios(13.0)) + pub fn set_preserve_invariance(&self, preserve: bool) { + unsafe { msg_send![self, setPreserveInvariance: preserve] } + } +} + +#[repr(u64)] +#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] +pub enum MTLLibraryError { + Unsupported = 1, + Internal = 2, + CompileFailure = 3, + CompileWarning = 4, + /// Only available on (macos(10.12), ios(10.0)) + FunctionNotFound = 5, + /// Only available on (macos(10.12), ios(10.0)) + FileNotFound = 6, +} + +pub enum MTLLibrary {} + +foreign_obj_type! { + type CType = MTLLibrary; + pub struct Library; + pub struct LibraryRef; +} + +impl LibraryRef { + pub fn device(&self) -> &DeviceRef { + unsafe { msg_send![self, device] } + } + + pub fn label(&self) -> &str { + unsafe { + let label = msg_send![self, label]; + crate::nsstring_as_str(label) + } + } + + pub fn set_label(&self, label: &str) { + unsafe { + let nslabel = crate::nsstring_from_str(label); + let () = msg_send![self, setLabel: nslabel]; + } + } + + // FIXME: should rename to new_function + pub fn get_function( + &self, + name: &str, + constants: Option<FunctionConstantValues>, + ) -> Result<Function, String> { + unsafe { + let nsname = crate::nsstring_from_str(name); + + let function: *mut MTLFunction = match constants { + Some(c) => try_objc! { err => msg_send![self, + newFunctionWithName: nsname.as_ref() + constantValues: c.as_ref() + error: &mut err + ]}, + None => msg_send![self, newFunctionWithName: nsname.as_ref()], + }; + + if !function.is_null() { + Ok(Function::from_ptr(function)) + } else { + Err(format!("Function '{}' does not exist", name)) + } + } + } + + // TODO: get_function_async with completion handler + + pub fn function_names(&self) -> Vec<String> { + unsafe { + let names: *mut Object = msg_send![self, functionNames]; + let count: NSUInteger = msg_send![names, count]; + let ret = (0..count) + .map(|i| { + let name = msg_send![names, objectAtIndex: i]; + nsstring_as_str(name).to_string() + }) + .collect(); + let () = msg_send![names, release]; + ret + } + } + + /// Only available on (macos(11.0), ios(14.0)) + pub fn library_type(&self) -> MTLLibraryType { + unsafe { msg_send![self, type] } + } + + /// Only available on (macos(11.0), ios(14.0)) + pub fn install_name(&self) -> Option<&str> { + unsafe { + let maybe_name: *mut Object = msg_send![self, installName]; + maybe_name.as_ref().map(crate::nsstring_as_str) + } + } + + /// Only available on (macos(11.0), ios(14.0)) + pub fn new_function_with_descriptor( + &self, + descriptor: &FunctionDescriptorRef, + ) -> Result<Function, String> { + unsafe { + let function: *mut MTLFunction = try_objc! { + err => msg_send![self, + newFunctionWithDescriptor: descriptor + error: &mut err + ] + }; + + if !function.is_null() { + Ok(Function::from_ptr(function)) + } else { + Err(String::from("new_function_with_descriptor() failed")) + } + } + } + + /// Only available on (macos(11.0), ios(14.0)) + pub fn new_intersection_function_with_descriptor( + &self, + descriptor: &IntersectionFunctionDescriptorRef, + ) -> Result<Function, String> { + unsafe { + let function: *mut MTLFunction = try_objc! { + err => msg_send![self, + newIntersectionFunctionWithDescriptor: descriptor + error: &mut err + ] + }; + + if !function.is_null() { + Ok(Function::from_ptr(function)) + } else { + Err(String::from( + "new_intersection_function_with_descriptor() failed", + )) + } + } + } +} + +/// Only available on (macos(11.0), ios(14.0)) +#[repr(u64)] +#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] +pub enum MTLDynamicLibraryError { + None = 0, + InvalidFile = 1, + CompilationFailure = 2, + UnresolvedInstallName = 3, + DependencyLoadFailure = 4, + Unsupported = 5, +} + +pub enum MTLDynamicLibrary {} + +foreign_obj_type! { + type CType = MTLDynamicLibrary; + pub struct DynamicLibrary; + pub struct DynamicLibraryRef; +} + +impl DynamicLibraryRef { + pub fn device(&self) -> &DeviceRef { + unsafe { msg_send![self, device] } + } + + pub fn label(&self) -> &str { + unsafe { + let label = msg_send![self, label]; + crate::nsstring_as_str(label) + } + } + + pub fn set_label(&self, label: &str) { + unsafe { + let nslabel = crate::nsstring_from_str(label); + let () = msg_send![self, setLabel: nslabel]; + } + } + + pub fn install_name(&self) -> &str { + unsafe { + let name = msg_send![self, installName]; + crate::nsstring_as_str(name) + } + } + + pub fn serialize_to_url(&self, url: &URLRef) -> Result<bool, String> { + unsafe { + let mut err: *mut Object = ptr::null_mut(); + let result: BOOL = msg_send![self, serializeToURL:url + error:&mut err]; + if !err.is_null() { + // FIXME: copy pasta + let desc: *mut Object = msg_send![err, localizedDescription]; + let c_msg: *const c_char = msg_send![desc, UTF8String]; + let message = CStr::from_ptr(c_msg).to_string_lossy().into_owned(); + Err(message) + } else { + match result { + YES => Ok(true), + NO => Ok(false), + _ => unreachable!(), + } + } + } + } +} + +/// macOS 11.0+ iOS 14.0+ +pub enum MTLBinaryArchiveDescriptor {} + +foreign_obj_type! { + type CType = MTLBinaryArchiveDescriptor; + pub struct BinaryArchiveDescriptor; + pub struct BinaryArchiveDescriptorRef; +} + +impl BinaryArchiveDescriptor { + pub fn new() -> Self { + unsafe { + let class = class!(MTLBinaryArchiveDescriptor); + msg_send![class, new] + } + } +} + +impl BinaryArchiveDescriptorRef { + pub fn url(&self) -> &URLRef { + unsafe { msg_send![self, url] } + } + pub fn set_url(&self, url: &URLRef) { + unsafe { msg_send![self, setUrl: url] } + } +} + +/// macOS 11.0+ iOS 14.0+ +pub enum MTLBinaryArchive {} + +foreign_obj_type! { + type CType = MTLBinaryArchive; + pub struct BinaryArchive; + pub struct BinaryArchiveRef; +} + +impl BinaryArchiveRef { + pub fn device(&self) -> &DeviceRef { + unsafe { msg_send![self, device] } + } + + pub fn label(&self) -> &str { + unsafe { + let label = msg_send![self, label]; + crate::nsstring_as_str(label) + } + } + + pub fn set_label(&self, label: &str) { + unsafe { + let nslabel = crate::nsstring_from_str(label); + let () = msg_send![self, setLabel: nslabel]; + } + } + + pub fn add_compute_pipeline_functions_with_descriptor( + &self, + descriptor: &ComputePipelineDescriptorRef, + ) -> Result<bool, String> { + unsafe { + let mut err: *mut Object = ptr::null_mut(); + let result: BOOL = msg_send![self, addComputePipelineFunctionsWithDescriptor:descriptor + error:&mut err]; + if !err.is_null() { + // FIXME: copy pasta + let desc: *mut Object = msg_send![err, localizedDescription]; + let c_msg: *const c_char = msg_send![desc, UTF8String]; + let message = CStr::from_ptr(c_msg).to_string_lossy().into_owned(); + Err(message) + } else { + match result { + YES => Ok(true), + NO => Ok(false), + _ => unreachable!(), + } + } + } + } + + pub fn add_render_pipeline_functions_with_descriptor( + &self, + descriptor: &RenderPipelineDescriptorRef, + ) -> Result<bool, String> { + unsafe { + let mut err: *mut Object = ptr::null_mut(); + let result: BOOL = msg_send![self, addRenderPipelineFunctionsWithDescriptor:descriptor + error:&mut err]; + if !err.is_null() { + // FIXME: copy pasta + let desc: *mut Object = msg_send![err, localizedDescription]; + let c_msg: *const c_char = msg_send![desc, UTF8String]; + let message = CStr::from_ptr(c_msg).to_string_lossy().into_owned(); + Err(message) + } else { + match result { + YES => Ok(true), + NO => Ok(false), + _ => unreachable!(), + } + } + } + } + + // TODO: addTileRenderPipelineFunctionsWithDescriptor + // - (BOOL)addTileRenderPipelineFunctionsWithDescriptor:(MTLTileRenderPipelineDescriptor *)descriptor + // error:(NSError * _Nullable *)error; + + pub fn serialize_to_url(&self, url: &URLRef) -> Result<bool, String> { + unsafe { + let mut err: *mut Object = ptr::null_mut(); + let result: BOOL = msg_send![self, serializeToURL:url + error:&mut err]; + if !err.is_null() { + // FIXME: copy pasta + let desc: *mut Object = msg_send![err, localizedDescription]; + let c_msg: *const c_char = msg_send![desc, UTF8String]; + let message = CStr::from_ptr(c_msg).to_string_lossy().into_owned(); + Err(message) + } else { + match result { + YES => Ok(true), + NO => Ok(false), + _ => unreachable!(), + } + } + } + } +} + +/// macOS 11.0+ iOS 14.0+ +pub enum MTLLinkedFunctions {} + +foreign_obj_type! { + type CType = MTLLinkedFunctions; + pub struct LinkedFunctions; + pub struct LinkedFunctionsRef; +} + +impl LinkedFunctions { + pub fn new() -> Self { + unsafe { + let class = class!(MTLLinkedFunctions); + msg_send![class, new] + } + } +} + +impl LinkedFunctionsRef { + /// Marshal to Rust Vec + pub fn functions(&self) -> Vec<Function> { + unsafe { + let functions: *mut Object = msg_send![self, functions]; + let count: NSUInteger = msg_send![functions, count]; + let ret = (0..count) + .map(|i| { + let f = msg_send![functions, objectAtIndex: i]; + Function::from_ptr(f) + }) + .collect(); + ret + } + } + + /// Marshal from Rust slice + pub fn set_functions(&self, functions: &[&FunctionRef]) { + let ns_array = Array::<Function>::from_slice(functions); + unsafe { msg_send![self, setFunctions: ns_array] } + } + + /// Marshal to Rust Vec + pub fn binary_functions(&self) -> Vec<Function> { + unsafe { + let functions: *mut Object = msg_send![self, binaryFunctions]; + let count: NSUInteger = msg_send![functions, count]; + let ret = (0..count) + .map(|i| { + let f = msg_send![functions, objectAtIndex: i]; + Function::from_ptr(f) + }) + .collect(); + ret + } + } + + /// Marshal from Rust slice + pub fn set_binary_functions(&self, functions: &[&FunctionRef]) { + let ns_array = Array::<Function>::from_slice(functions); + unsafe { msg_send![self, setBinaryFunctions: ns_array] } + } + + // TODO: figure out NSDictionary wrapper + // TODO: groups + // @property (readwrite, nonatomic, copy, nullable) NSDictionary<NSString*, NSArray<id<MTLFunction>>*> *groups; +} |