2020-03-18 10:55:09 +11:00
|
|
|
//! A wrapper library for `NSString`, which we use throughout the framework. This is abstracted out
|
|
|
|
//! for a few reasons, but namely:
|
|
|
|
//!
|
|
|
|
//! - It's used often, so we want a decent enough API.
|
|
|
|
//! - Playing around with performance for this type is ideal, as it's a lot of heap allocation.
|
|
|
|
//!
|
|
|
|
//! End users should never need to interact with this.
|
|
|
|
|
|
|
|
use std::{slice, str};
|
|
|
|
use std::os::raw::c_char;
|
|
|
|
|
|
|
|
use objc::{class, msg_send, sel, sel_impl};
|
|
|
|
use objc::runtime::Object;
|
|
|
|
use objc_id::Id;
|
|
|
|
|
|
|
|
use crate::foundation::id;
|
|
|
|
|
|
|
|
const UTF8_ENCODING: usize = 4;
|
|
|
|
|
|
|
|
/// Wraps an underlying `NSString`.
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct NSString(pub Id<Object>);
|
|
|
|
|
|
|
|
impl NSString {
|
|
|
|
pub fn new(s: &str) -> Self {
|
|
|
|
NSString(unsafe {
|
|
|
|
let nsstring: *mut Object = msg_send![class!(NSString), alloc];
|
|
|
|
//msg_send![nsstring, initWithBytesNoCopy:s.as_ptr() length:s.len() encoding:4 freeWhenDone:NO]
|
|
|
|
Id::from_ptr(msg_send![nsstring, initWithBytes:s.as_ptr() length:s.len() encoding:UTF8_ENCODING])
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn wrap(object: id) -> Self {
|
|
|
|
NSString(unsafe {
|
2020-03-22 10:46:35 +11:00
|
|
|
Id::from_ptr(object)
|
2020-03-18 10:55:09 +11:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn into_inner(mut self) -> id {
|
|
|
|
&mut *self.0
|
|
|
|
}
|
|
|
|
|
|
|
|
/// A utility method for taking an `NSString` and bridging it to a Rust `&str`.
|
|
|
|
pub fn to_str(self) -> &'static str {
|
|
|
|
unsafe {
|
|
|
|
let bytes = {
|
|
|
|
let bytes: *const c_char = msg_send![&*self.0, UTF8String];
|
|
|
|
bytes as *const u8
|
|
|
|
};
|
|
|
|
|
|
|
|
let len = msg_send![&*self.0, lengthOfBytesUsingEncoding:UTF8_ENCODING];
|
|
|
|
let bytes = slice::from_raw_parts(bytes, len);
|
|
|
|
str::from_utf8(bytes).unwrap()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|