virtualization-rs 0.1.2

virtualization-rs provides the API of the Apple Virtualization.framework in Rust language.
Documentation
//! base module

use std::marker::PhantomData;
use std::slice;
use std::str;

use block::Block;
use libc::c_void;
use objc::rc::StrongPtr;
use objc::runtime::{Object, BOOL, NO, YES};
use objc::{class, msg_send, sel, sel_impl};

#[link(name = "Virtualization", kind = "framework")]
extern "C" {}

#[link(name = "Foundation", kind = "framework")]
extern "C" {
    pub fn dispatch_queue_create(label: *const libc::c_char, attr: Id) -> Id;
    // pub fn dispatch_sync(queue: Id, block: &Block<(), ()>);
    pub fn dispatch_sync(queue: Id, block: *mut c_void);
    pub fn dispatch_async(queue: Id, block: &Block<(), ()>);
// pub fn dispatch_async(queue: Id, block: *mut c_void);
}

pub type Id = *mut Object;
pub const NIL: Id = 0 as Id;

pub struct NSArray<T> {
    pub _phantom: PhantomData<T>,
    pub p: StrongPtr,
}

impl<T> NSArray<T> {
    pub fn array_with_objects(objects: Vec<Id>) -> NSArray<T> {
        unsafe {
            let p = StrongPtr::new(
                msg_send![class!(NSArray), arrayWithObjects:objects.as_slice().as_ptr() count:objects.len()],
            );
            NSArray {
                p: p,
                _phantom: PhantomData,
            }
        }
    }

    pub fn count(&self) -> usize {
        unsafe { msg_send![*self.p, count] }
    }
}

impl<T: From<StrongPtr>> NSArray<T> {
    pub fn object_at_index(&self, index: usize) -> T {
        debug_assert!(index < self.count());
        unsafe { T::from(StrongPtr::retain(msg_send![*self.p, objectAtIndex: index])) }
    }
}

const UTF8_ENCODING: usize = 4;
pub struct NSString(pub StrongPtr);

impl NSString {
    pub fn new(string: &str) -> NSString {
        unsafe {
            let alloc: Id = msg_send![class!(NSString), alloc];
            let p = StrongPtr::new(
                msg_send![alloc, initWithBytes:string.as_ptr() length:string.len() encoding:UTF8_ENCODING as Id],
            );
            NSString(p)
        }
    }

    pub fn len(&self) -> usize {
        unsafe { msg_send![*self.0, lengthOfBytesUsingEncoding: UTF8_ENCODING] }
    }

    pub fn as_str(&self) -> &str {
        unsafe {
            let bytes = {
                let bytes: *const libc::c_char = msg_send![*self.0, UTF8String];
                bytes as *const u8
            };
            let len = self.len();
            let bytes = slice::from_raw_parts(bytes, len);
            str::from_utf8(bytes).unwrap()
        }
    }
}

impl From<StrongPtr> for NSString {
    fn from(p: StrongPtr) -> Self {
        NSString(p)
    }
}

pub struct NSURL(pub StrongPtr);

impl NSURL {
    pub fn url_with_string(url: &str) -> NSURL {
        unsafe {
            let url_nsstring = NSString::new(url);
            let p = StrongPtr::retain(msg_send![class!(NSURL), URLWithString: url_nsstring]);
            NSURL(p)
        }
    }

    pub fn file_url_with_path(path: &str, is_directory: bool) -> NSURL {
        unsafe {
            let path_nsstring = NSString::new(path);
            let is_directory_ = if is_directory { YES } else { NO };
            let p = StrongPtr::retain(
                msg_send![class!(NSURL), fileURLWithPath:path_nsstring isDirectory:is_directory_],
            );
            NSURL(p)
        }
    }

    pub fn check_resource_is_reachable_and_return_error(&self) -> bool {
        let b = unsafe {
            let obj: Id = msg_send![*self.0, checkResourceIsReachableAndReturnError: NIL];
            obj as BOOL
        };
        b == YES
    }

    pub fn absolute_url(&self) -> NSURL {
        unsafe {
            let p = StrongPtr::retain(msg_send![*self.0, absoluteURL]);
            NSURL(p)
        }
    }
}

pub struct NSFileHandle(pub StrongPtr);

impl NSFileHandle {
    pub fn new() -> NSFileHandle {
        unsafe {
            let p = StrongPtr::new(msg_send![class!(NSFileHandle), new]);
            NSFileHandle(p)
        }
    }

    pub fn file_handle_with_standard_input() -> NSFileHandle {
        unsafe {
            let p = StrongPtr::retain(msg_send![class!(NSFileHandle), fileHandleWithStandardInput]);
            NSFileHandle(p)
        }
    }

    pub fn file_handle_with_standard_output() -> NSFileHandle {
        unsafe {
            let p = StrongPtr::retain(msg_send![
                class!(NSFileHandle),
                fileHandleWithStandardOutput
            ]);
            NSFileHandle(p)
        }
    }
}

pub struct NSDictionary(pub StrongPtr);

impl NSDictionary {
    pub fn all_keys<T>(&self) -> NSArray<T> {
        unsafe {
            NSArray {
                p: StrongPtr::retain(msg_send![*self.0, allKeys]),
                _phantom: PhantomData,
            }
        }
    }

    pub fn all_values<T>(&self) -> NSArray<T> {
        unsafe {
            NSArray {
                p: StrongPtr::retain(msg_send![*self.0, allValues]),
                _phantom: PhantomData,
            }
        }
    }
}

pub struct NSError(pub StrongPtr);

impl NSError {
    pub fn nil() -> NSError {
        unsafe {
            let p = StrongPtr::new(NIL);
            NSError(p)
        }
    }

    pub fn code(&self) -> isize {
        unsafe { msg_send![*self.0, code] }
    }

    pub fn localized_description(&self) -> NSString {
        unsafe { NSString(StrongPtr::retain(msg_send![*self.0, localizedDescription])) }
    }

    pub fn localized_failure_reason(&self) -> NSString {
        unsafe {
            NSString(StrongPtr::retain(msg_send![
                *self.0,
                localizedFailureReason
            ]))
        }
    }

    pub fn localized_recovery_suggestion(&self) -> NSString {
        unsafe {
            NSString(StrongPtr::retain(msg_send![
                *self.0,
                localizedRecoverySuggestion
            ]))
        }
    }

    pub fn help_anchor(&self) -> NSString {
        unsafe { NSString(StrongPtr::retain(msg_send![*self.0, helpAnchor])) }
    }

    pub fn user_info(&self) -> NSDictionary {
        unsafe { NSDictionary(StrongPtr::retain(msg_send![*self.0, userInfo])) }
    }

    pub fn dump(&self) {
        let code = self.code();
        println!("code: {}", code);
        let localized_description = self.localized_description();
        println!("localizedDescription : {}", localized_description.as_str());
        let localized_failure_reason = self.localized_failure_reason();
        println!(
            "localizedFailureReason : {}",
            localized_failure_reason.as_str()
        );
        let localized_recovery_suggestion = self.localized_recovery_suggestion();
        println!(
            "localizedRecoverySuggestion : {}",
            localized_recovery_suggestion.as_str()
        );
        let help_anchor = self.help_anchor();
        println!("helpAnchor : {}", help_anchor.as_str());
        let user_info = self.user_info();
        println!("userInfo :");
        let keys: NSArray<NSString> = user_info.all_keys();
        let values: NSArray<NSString> = user_info.all_values();
        let cnt = keys.count();
        for i in 0..cnt {
            let k = keys.object_at_index(i);
            let o = values.object_at_index(i);
            println!("    key: {}, value: {}", k.as_str(), o.as_str());
        }
    }
}