ui-automation 0.1.1

Control the User Interface, cross-platform.
Documentation
// Copyright (C) 2024 Tristan Gerritsen <tristan@thewoosh.org>
// All Rights Reserved.

use std::{ffi::c_void, marker::PhantomData};

use crate::{UIErrorKind, UIResult};

use super::{CFArrayRef, CFSerializable, CFType};

pub type CFDictionaryRef = *const c_void;


#[derive(Debug, Clone)]
pub(crate) struct CFDictionary<K> {
    pub(crate) inner: CFType,
    _key: PhantomData<K>,
}

impl<K> CFDictionary<K>
        where K: CFSerializable {
    pub fn from_get(reference: CFDictionaryRef) -> UIResult<Self> {
        let Some(inner) = CFType::from_get(reference) else {
            return Err(UIErrorKind::AllocationFailed { resource: "CFDictionary" }.into());
        };

        Ok(Self {
            inner,
            _key: PhantomData,
        })
    }

    #[allow(unused)]
    pub fn from_create(reference: CFDictionaryRef) -> UIResult<Self> {
        let Some(inner) = CFType::from_create(reference) else {
            return Err(UIErrorKind::AllocationFailed { resource: "CFDictionary" }.into());
        };

        Ok(Self {
            inner,
            _key: PhantomData,
        })
    }

    pub fn get<V: CFSerializable>(&self, key: &K) -> Option<V> {
        let key = key.to_ptr();
        if key.is_null() {
            return None;
        }

        let value = unsafe { CFDictionaryGetValue(self.inner.ptr(), key) };
        if value.is_null() {
            return None;
        }

        Some(V::from_ptr(value))
    }
}

impl<K> CFSerializable for CFDictionary<K> {
    fn from_ptr(ptr: *const c_void) -> Self {
        Self {
            inner: CFType::from_get(ptr).unwrap(),
            _key: PhantomData,
        }
    }

    fn to_ptr(&self) -> *const c_void {
        self.inner.ptr()
    }
}

extern "C-unwind" {
    pub(super) fn CFDictionaryGetValue(array: CFArrayRef, key: *const c_void) -> *const c_void;
}