//! Raw FFI bindings to Apple frameworks: Metal, CoreFoundation, libobjc

#![allow(
    non_camel_case_types,
    non_upper_case_globals,
    non_snake_case,
    dead_code,
    clippy::not_unsafe_ptr_arg_deref,
    clippy::missing_safety_doc
)]

mod selectors;
mod trampoline;

pub use selectors::*;
pub use trampoline::*;

use std::ffi::{c_char, c_void, CStr};

// โ”€โ”€ Type aliases โ”€โ”€

pub type ObjcClass = *const c_void;
pub type ObjcSel = *const c_void;
pub type ObjcId = *mut c_void;
pub type CFTypeRef = *const c_void;
pub type CFStringRef = *const c_void;
pub type CFMutableDictionaryRef = *mut c_void;
pub type NSUInteger = usize;

// โ”€โ”€ MTLSize (used for dispatch) โ”€โ”€

#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct MTLSize {
    pub width: NSUInteger,
    pub height: NSUInteger,
    pub depth: NSUInteger,
}

// โ”€โ”€ MTLRegion โ”€โ”€

#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct MTLOrigin {
    pub x: NSUInteger,
    pub y: NSUInteger,
    pub z: NSUInteger,
}

#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct MTLRegion {
    pub origin: MTLOrigin,
    pub size: MTLSize,
}

// โ”€โ”€ Metal resource options โ”€โ”€

pub const MTLResourceStorageModeShared: NSUInteger = 0;
pub const MTLResourceStorageModeManaged: NSUInteger = 0x10;
pub const MTLResourceStorageModePrivate: NSUInteger = 0x20;

// โ”€โ”€ Metal pixel formats (common) โ”€โ”€

pub const MTLPixelFormatRGBA8Unorm: NSUInteger = 70;
pub const MTLPixelFormatBGRA8Unorm: NSUInteger = 80;
pub const MTLPixelFormatR32Float: NSUInteger = 55;
pub const MTLPixelFormatRGBA32Float: NSUInteger = 125;

// โ”€โ”€ CoreFoundation constants โ”€โ”€

pub const kCFStringEncodingUTF8: u32 = 0x08000100;

// โ”€โ”€ Metal.framework โ”€โ”€

#[link(name = "Metal", kind = "framework")]
extern "C" {
    pub fn MTLCreateSystemDefaultDevice() -> ObjcId;
    pub fn MTLCopyAllDevices() -> ObjcId;
}

// โ”€โ”€ CoreFoundation โ”€โ”€

#[link(name = "CoreFoundation", kind = "framework")]
extern "C" {
    pub fn CFStringCreateWithCString(
        alloc: *const c_void,
        cStr: *const c_char,
        encoding: u32,
    ) -> CFStringRef;
    pub fn CFStringCreateWithBytes(
        alloc: *const c_void,
        bytes: *const u8,
        numBytes: isize,
        encoding: u32,
        isExternalRepresentation: bool,
    ) -> CFStringRef;
    pub fn CFRelease(cf: CFTypeRef);
    pub fn CFRetain(cf: CFTypeRef) -> CFTypeRef;
}

// โ”€โ”€ ObjC runtime โ”€โ”€

extern "C" {
    pub fn objc_getClass(name: *const c_char) -> ObjcClass;
    pub fn sel_registerName(name: *const c_char) -> ObjcSel;
    pub fn objc_msgSend() -> ObjcId;
    pub fn objc_retain(obj: ObjcId) -> ObjcId;
    pub fn objc_release(obj: ObjcId);
    pub fn objc_autoreleasePoolPush() -> *mut c_void;
    pub fn objc_autoreleasePoolPop(pool: *mut c_void);
    pub fn object_getClass(obj: ObjcId) -> ObjcClass;
    pub fn class_getMethodImplementation(cls: ObjcClass, sel: ObjcSel) -> *const c_void;
    /// ARC optimization: if called immediately after a msg_send that returns
    /// an autoreleased object, the runtime skips the autorelease+retain
    /// round-trip entirely. Must be called with no intervening code.
    pub fn objc_retainAutoreleasedReturnValue(obj: ObjcId) -> ObjcId;
}

// โ”€โ”€ String helpers โ”€โ”€

#[mutants::skip] // null err โ†’ None โ€” mutant โ†’ None passes on success path
pub fn nserror_string(err: ObjcId) -> Option<String> {
    if err.is_null() {
        return None;
    }
    unsafe {
        let desc = msg0(err, SEL_localizedDescription());
        if desc.is_null() {
            return None;
        }
        nsstring_to_rust(desc)
    }
}

pub fn nsstring_to_rust(obj: ObjcId) -> Option<String> {
    if obj.is_null() {
        return None;
    }
    unsafe {
        type F = unsafe extern "C" fn(ObjcId, ObjcSel) -> *const c_char;
        let f: F = std::mem::transmute(objc_msgSend as *const c_void);
        let cstr = f(obj, SEL_UTF8String());
        if cstr.is_null() {
            return None;
        }
        Some(CStr::from_ptr(cstr).to_string_lossy().into_owned())
    }
}

/// Create NSString from &str. Zero-alloc: uses CFStringCreateWithBytes
/// directly on the Rust string's UTF-8 bytes, no CString intermediate.
pub fn nsstring(s: &str) -> ObjcId {
    unsafe {
        CFStringCreateWithBytes(
            std::ptr::null(),
            s.as_ptr(),
            s.len() as isize,
            kCFStringEncodingUTF8,
            false,
        ) as ObjcId
    }
}

// โ”€โ”€ Retain/release (hot path โ€” cached selectors) โ”€โ”€

/// Retain via objc_retain (direct C call, not msg_send).
#[inline(always)]
pub unsafe fn retain(obj: ObjcId) -> ObjcId {
    if !obj.is_null() {
        objc_retain(obj);
    }
    obj
}

/// Release via objc_release (direct C call, not msg_send).
#[inline(always)]
pub unsafe fn release(obj: ObjcId) {
    if !obj.is_null() {
        objc_release(obj);
    }
}

/// Retain a known-non-null object. No null check โ€” hot path only.
#[inline(always)]
pub unsafe fn retain_nonnull(obj: ObjcId) -> ObjcId {
    debug_assert!(!obj.is_null());
    objc_retain(obj);
    obj
}

/// Release a known-non-null object. No null check โ€” hot path only.
#[inline(always)]
pub unsafe fn release_nonnull(obj: ObjcId) {
    debug_assert!(!obj.is_null());
    objc_release(obj);
}

Synonyms

trident/src/typecheck/mod.rs
optica/src/scanner/mod.rs
optica/src/output/mod.rs
trident/src/package/mod.rs
trident/src/gpu/mod.rs
trident/src/ir/mod.rs
trident/src/api/mod.rs
trident/src/config/mod.rs
trident/src/import/mod.rs
optica/src/query/mod.rs
trident/src/runtime/mod.rs
optica/src/render/mod.rs
nox/rs/noun/mod.rs
optica/src/server/mod.rs
trident/src/cost/mod.rs
trident/src/syntax/mod.rs
trident/src/field/mod.rs
nox/rs/patterns/mod.rs
optica/src/parser/mod.rs
trident/src/cli/mod.rs
trident/src/compile/mod.rs
trident/src/neural/mod.rs
trident/src/verify/mod.rs
optica/src/graph/mod.rs
trident/src/diagnostic/mod.rs
trident/src/lsp/mod.rs
trident/src/deploy/mod.rs
trident/src/ast/mod.rs
trident/src/neural/training/mod.rs
trident/src/verify/report/mod.rs
honeycrisp/acpu/src/pulse/mod.rs
trident/src/syntax/lexer/mod.rs
trident/src/ir/tir/mod.rs
trident/src/cost/model/mod.rs
rs/rsc/src/lints/mod.rs
trident/src/lsp/util/mod.rs
trident/src/neural/data/mod.rs
bostrom-mcp/rust/src/tools/mod.rs
rs/core/src/bounded/mod.rs
trident/src/package/store/mod.rs
bostrom-mcp/rust/src/proto/mod.rs
radio/iroh-blobs/examples/common/mod.rs
trident/src/syntax/parser/mod.rs
honeycrisp/acpu/src/probe/mod.rs
bostrom-mcp/rust/src/clients/mod.rs
trident/src/verify/smt/mod.rs
trident/src/typecheck/tests/mod.rs
trident/src/config/scaffold/mod.rs
trident/src/syntax/format/mod.rs
trident/src/lsp/semantic/mod.rs
trident/src/neural/model/mod.rs
honeycrisp/acpu/src/crypto/mod.rs
trident/src/package/hash/mod.rs
honeycrisp/rane/src/mil/mod.rs
strata/nebu/rs/extension/mod.rs
trident/src/ir/tree/mod.rs
trident/src/neural/inference/mod.rs
trident/src/verify/synthesize/mod.rs
trident/src/cost/stack_verifier/mod.rs
rs/macros/src/addressed/mod.rs
trident/src/verify/sym/mod.rs
honeycrisp/acpu/src/matrix/mod.rs
rs/core/src/fixed_point/mod.rs
trident/src/config/resolve/mod.rs
honeycrisp/acpu/src/sync/mod.rs
trident/src/package/registry/mod.rs
trident/src/syntax/grammar/mod.rs
honeycrisp/acpu/src/gemm/mod.rs
radio/iroh-blobs/src/store/mod.rs
trident/src/verify/equiv/mod.rs
honeycrisp/acpu/src/vector/mod.rs
trident/src/package/manifest/mod.rs
rs/macros/src/registers/mod.rs
honeycrisp/acpu/src/field/mod.rs
trident/src/ir/kir/mod.rs
radio/cyber-bao/src/io/mod.rs
trident/src/ir/lir/mod.rs
trident/src/api/tests/mod.rs
rs/macros/src/cell/mod.rs
honeycrisp/acpu/src/numeric/mod.rs
trident/src/verify/solve/mod.rs
trident/src/ir/lir/lower/mod.rs
trident/src/ir/tir/neural/mod.rs
cyb/cyb/cyb-shell/src/shell/mod.rs
trident/src/ir/tree/lower/mod.rs
cw-cyber/packages/cyber-std/src/tokenfactory/mod.rs
strata/trop/wgsl/src/shaders/mod.rs
trident/src/ir/tir/stack/mod.rs
cw-cyber/contracts/cybernet/src/tests/mod.rs
trident/src/syntax/parser/tests/mod.rs
trident/src/ir/tir/lower/mod.rs
cyb/cyb/cyb-shell/src/worlds/mod.rs
trident/src/neural/data/tir_graph/mod.rs
cyb/cyb/cyb-shell/src/agent/mod.rs
trident/src/ir/tir/optimize/mod.rs
strata/genies/wgsl/src/shaders/mod.rs
trident/src/ir/kir/lower/mod.rs
strata/jali/wgsl/src/shaders/mod.rs
strata/kuro/wgsl/src/shaders/mod.rs
trident/src/ir/tir/builder/mod.rs

Neighbours