Import cocoa.
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
*~
|
||||
build
|
||||
/target
|
||||
/Cargo.lock
|
||||
@@ -0,0 +1,6 @@
|
||||
os: osx
|
||||
|
||||
language: rust
|
||||
|
||||
notifications:
|
||||
webhooks: http://build.servo.org:54856/travis
|
||||
@@ -0,0 +1,5 @@
|
||||
Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
<LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
option. All files in the project carrying such notice may not be
|
||||
copied, modified, or distributed except according to those terms.
|
||||
@@ -0,0 +1,20 @@
|
||||
|
||||
[package]
|
||||
name = "cocoa"
|
||||
description = "Bindings to Cocoa for OS X"
|
||||
homepage = "https://github.com/servo/cocoa-rs"
|
||||
repository = "https://github.com/servo/cocoa-rs"
|
||||
version = "0.14.0"
|
||||
authors = ["The Servo Project Developers"]
|
||||
license = "MIT / Apache-2.0"
|
||||
|
||||
[lib]
|
||||
name = "cocoa"
|
||||
crate-type = ["rlib"]
|
||||
|
||||
[dependencies]
|
||||
block = "0.1"
|
||||
bitflags = "1.0"
|
||||
libc = "0.2"
|
||||
core-graphics = "0.13"
|
||||
objc = "0.2"
|
||||
@@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
@@ -0,0 +1,25 @@
|
||||
Copyright (c) 2012-2013 Mozilla Foundation
|
||||
|
||||
Permission is hereby granted, free of charge, to any
|
||||
person obtaining a copy of this software and associated
|
||||
documentation files (the "Software"), to deal in the
|
||||
Software without restriction, including without
|
||||
limitation the rights to use, copy, modify, merge,
|
||||
publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software
|
||||
is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice
|
||||
shall be included in all copies or substantial portions
|
||||
of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
||||
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
@@ -0,0 +1,6 @@
|
||||
Cocoa-rs
|
||||
--------
|
||||
|
||||
This crate provides Rust bindings to Cocoa for OSX. It's dual-licensed MIT /
|
||||
Apache 2.0. If you'd like to help improve cocoa-rs, check out [the Servo
|
||||
contributing guide](https://github.com/servo/servo/blob/master/CONTRIBUTING.md)!
|
||||
@@ -0,0 +1,53 @@
|
||||
extern crate cocoa;
|
||||
|
||||
use cocoa::base::{selector, nil, NO};
|
||||
use cocoa::foundation::{NSRect, NSPoint, NSSize, NSAutoreleasePool, NSProcessInfo,
|
||||
NSString};
|
||||
use cocoa::appkit::{NSApp, NSApplication, NSApplicationActivationPolicyRegular, NSWindow,
|
||||
NSBackingStoreBuffered, NSMenu, NSMenuItem, NSWindowStyleMask,
|
||||
NSRunningApplication, NSApplicationActivateIgnoringOtherApps};
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
let _pool = NSAutoreleasePool::new(nil);
|
||||
|
||||
let app = NSApp();
|
||||
app.setActivationPolicy_(NSApplicationActivationPolicyRegular);
|
||||
|
||||
// create Menu Bar
|
||||
let menubar = NSMenu::new(nil).autorelease();
|
||||
let app_menu_item = NSMenuItem::new(nil).autorelease();
|
||||
menubar.addItem_(app_menu_item);
|
||||
app.setMainMenu_(menubar);
|
||||
|
||||
// create Application menu
|
||||
let app_menu = NSMenu::new(nil).autorelease();
|
||||
let quit_prefix = NSString::alloc(nil).init_str("Quit ");
|
||||
let quit_title =
|
||||
quit_prefix.stringByAppendingString_(NSProcessInfo::processInfo(nil).processName());
|
||||
let quit_action = selector("terminate:");
|
||||
let quit_key = NSString::alloc(nil).init_str("q");
|
||||
let quit_item = NSMenuItem::alloc(nil)
|
||||
.initWithTitle_action_keyEquivalent_(quit_title, quit_action, quit_key)
|
||||
.autorelease();
|
||||
app_menu.addItem_(quit_item);
|
||||
app_menu_item.setSubmenu_(app_menu);
|
||||
|
||||
// create Window
|
||||
let window = NSWindow::alloc(nil)
|
||||
.initWithContentRect_styleMask_backing_defer_(NSRect::new(NSPoint::new(0., 0.),
|
||||
NSSize::new(200., 200.)),
|
||||
NSWindowStyleMask::NSTitledWindowMask,
|
||||
NSBackingStoreBuffered,
|
||||
NO)
|
||||
.autorelease();
|
||||
window.cascadeTopLeftFromPoint_(NSPoint::new(20., 20.));
|
||||
window.center();
|
||||
let title = NSString::alloc(nil).init_str("Hello World!");
|
||||
window.setTitle_(title);
|
||||
window.makeKeyAndOrderFront_(nil);
|
||||
let current_app = NSRunningApplication::currentApplication(nil);
|
||||
current_app.activateWithOptions_(NSApplicationActivateIgnoringOtherApps);
|
||||
app.run();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
extern crate cocoa;
|
||||
|
||||
use cocoa::base::{selector, id, nil, NO};
|
||||
|
||||
|
||||
use cocoa::foundation::{NSRect, NSPoint, NSSize, NSAutoreleasePool, NSProcessInfo,
|
||||
NSString};
|
||||
use cocoa::appkit::{NSApp, NSApplication, NSApplicationActivationPolicyRegular, NSWindow,
|
||||
NSMenu, NSMenuItem, NSTabView, NSWindowStyleMask, NSBackingStoreType,
|
||||
NSTabViewItem, NSRunningApplication, NSApplicationActivateIgnoringOtherApps};
|
||||
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
|
||||
// create a tab View
|
||||
let tab_view = NSTabView::new(nil)
|
||||
.initWithFrame_(NSRect::new(NSPoint::new(0., 0.), NSSize::new(200., 200.)));
|
||||
|
||||
// create a tab view item
|
||||
let tab_view_item = NSTabViewItem::new(nil)
|
||||
.initWithIdentifier_(NSString::alloc(nil).init_str("TabView1"));
|
||||
|
||||
tab_view_item.setLabel_(NSString::alloc(nil).init_str("Tab view item 1"));
|
||||
tab_view.addTabViewItem_(tab_view_item);
|
||||
|
||||
// create a second tab view item
|
||||
let tab_view_item2 = NSTabViewItem::new(nil)
|
||||
.initWithIdentifier_(NSString::alloc(nil).init_str("TabView2"));
|
||||
|
||||
tab_view_item2.setLabel_(NSString::alloc(nil).init_str("Tab view item 2"));
|
||||
tab_view.addTabViewItem_(tab_view_item2);
|
||||
|
||||
// Create the app and set the content.
|
||||
let app = create_app(NSString::alloc(nil).init_str("Tab View"), tab_view);
|
||||
app.run();
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn create_app(title: id, content: id) -> id {
|
||||
let _pool = NSAutoreleasePool::new(nil);
|
||||
|
||||
let app = NSApp();
|
||||
app.setActivationPolicy_(NSApplicationActivationPolicyRegular);
|
||||
|
||||
// create Menu Bar
|
||||
let menubar = NSMenu::new(nil).autorelease();
|
||||
let app_menu_item = NSMenuItem::new(nil).autorelease();
|
||||
menubar.addItem_(app_menu_item);
|
||||
app.setMainMenu_(menubar);
|
||||
|
||||
// create Application menu
|
||||
let app_menu = NSMenu::new(nil).autorelease();
|
||||
let quit_prefix = NSString::alloc(nil).init_str("Quit ");
|
||||
let quit_title =
|
||||
quit_prefix.stringByAppendingString_(NSProcessInfo::processInfo(nil).processName());
|
||||
let quit_action = selector("terminate:");
|
||||
let quit_key = NSString::alloc(nil).init_str("q");
|
||||
let quit_item = NSMenuItem::alloc(nil)
|
||||
.initWithTitle_action_keyEquivalent_(quit_title, quit_action, quit_key)
|
||||
.autorelease();
|
||||
app_menu.addItem_(quit_item);
|
||||
app_menu_item.setSubmenu_(app_menu);
|
||||
|
||||
// create Window
|
||||
let window = NSWindow::alloc(nil).initWithContentRect_styleMask_backing_defer_(
|
||||
NSRect::new(NSPoint::new(0., 0.), NSSize::new(200., 200.)),
|
||||
NSWindowStyleMask::NSTitledWindowMask |
|
||||
NSWindowStyleMask::NSClosableWindowMask |
|
||||
NSWindowStyleMask::NSResizableWindowMask |
|
||||
NSWindowStyleMask::NSMiniaturizableWindowMask |
|
||||
NSWindowStyleMask::NSUnifiedTitleAndToolbarWindowMask,
|
||||
NSBackingStoreType::NSBackingStoreBuffered,
|
||||
NO
|
||||
).autorelease();
|
||||
window.cascadeTopLeftFromPoint_(NSPoint::new(20., 20.));
|
||||
window.center();
|
||||
|
||||
window.setTitle_(title);
|
||||
window.makeKeyAndOrderFront_(nil);
|
||||
|
||||
window.setContentView_(content);
|
||||
let current_app = NSRunningApplication::currentApplication(nil);
|
||||
current_app.activateWithOptions_(NSApplicationActivateIgnoringOtherApps);
|
||||
|
||||
return app;
|
||||
}
|
||||
+3754
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,37 @@
|
||||
// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.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 objc::runtime;
|
||||
use std::mem;
|
||||
|
||||
pub use objc::runtime::{BOOL, NO, YES};
|
||||
|
||||
pub type Class = *mut runtime::Class;
|
||||
#[allow(non_camel_case_types)]
|
||||
pub type id = *mut runtime::Object;
|
||||
pub type SEL = runtime::Sel;
|
||||
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub const nil: id = 0 as id;
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub const Nil: Class = 0 as Class;
|
||||
|
||||
/// A convenience method to convert the name of a class to the class object itself.
|
||||
#[inline]
|
||||
pub fn class(name: &str) -> Class {
|
||||
unsafe {
|
||||
mem::transmute(runtime::Class::get(name))
|
||||
}
|
||||
}
|
||||
|
||||
/// A convenience method to convert the name of a selector to the selector object.
|
||||
#[inline]
|
||||
pub fn selector(name: &str) -> SEL {
|
||||
runtime::Sel::register(name)
|
||||
}
|
||||
@@ -0,0 +1,932 @@
|
||||
// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.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.
|
||||
|
||||
#![allow(non_upper_case_globals)]
|
||||
|
||||
use std::ptr;
|
||||
use base::{id, class, BOOL, NO, SEL, nil};
|
||||
use block::Block;
|
||||
use libc;
|
||||
|
||||
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
pub type NSInteger = libc::c_int;
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
pub type NSUInteger = libc::c_uint;
|
||||
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
pub type NSInteger = libc::c_long;
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
pub type NSUInteger = libc::c_ulong;
|
||||
|
||||
const UTF8_ENCODING: usize = 4;
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
mod macos {
|
||||
use std::mem;
|
||||
use base::{id, class};
|
||||
use core_graphics::base::CGFloat;
|
||||
use core_graphics::geometry::CGRect;
|
||||
use objc;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct NSPoint {
|
||||
pub x: f64,
|
||||
pub y: f64,
|
||||
}
|
||||
|
||||
impl NSPoint {
|
||||
#[inline]
|
||||
pub fn new(x: f64, y: f64) -> NSPoint {
|
||||
NSPoint {
|
||||
x: x,
|
||||
y: y,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl objc::Encode for NSPoint {
|
||||
fn encode() -> objc::Encoding {
|
||||
let encoding = format!("{{CGPoint={}{}}}",
|
||||
f64::encode().as_str(),
|
||||
f64::encode().as_str());
|
||||
unsafe { objc::Encoding::from_str(&encoding) }
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct NSSize {
|
||||
pub width: f64,
|
||||
pub height: f64,
|
||||
}
|
||||
|
||||
impl NSSize {
|
||||
#[inline]
|
||||
pub fn new(width: f64, height: f64) -> NSSize {
|
||||
NSSize {
|
||||
width: width,
|
||||
height: height,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl objc::Encode for NSSize {
|
||||
fn encode() -> objc::Encoding {
|
||||
let encoding = format!("{{CGSize={}{}}}",
|
||||
f64::encode().as_str(),
|
||||
f64::encode().as_str());
|
||||
unsafe { objc::Encoding::from_str(&encoding) }
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct NSRect {
|
||||
pub origin: NSPoint,
|
||||
pub size: NSSize,
|
||||
}
|
||||
|
||||
impl NSRect {
|
||||
#[inline]
|
||||
pub fn new(origin: NSPoint, size: NSSize) -> NSRect {
|
||||
NSRect {
|
||||
origin: origin,
|
||||
size: size
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn as_CGRect(&self) -> &CGRect {
|
||||
unsafe {
|
||||
mem::transmute::<&NSRect, &CGRect>(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn inset(&self, x: CGFloat, y: CGFloat) -> NSRect {
|
||||
unsafe {
|
||||
NSInsetRect(*self, x, y)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl objc::Encode for NSRect {
|
||||
fn encode() -> objc::Encoding {
|
||||
let encoding = format!("{{CGRect={}{}}}",
|
||||
NSPoint::encode().as_str(),
|
||||
NSSize::encode().as_str());
|
||||
unsafe { objc::Encoding::from_str(&encoding) }
|
||||
}
|
||||
}
|
||||
|
||||
// Same as CGRectEdge
|
||||
#[repr(u32)]
|
||||
pub enum NSRectEdge {
|
||||
NSRectMinXEdge,
|
||||
NSRectMinYEdge,
|
||||
NSRectMaxXEdge,
|
||||
NSRectMaxYEdge,
|
||||
}
|
||||
|
||||
#[link(name = "Foundation", kind = "framework")]
|
||||
extern {
|
||||
fn NSInsetRect(rect: NSRect, x: CGFloat, y: CGFloat) -> NSRect;
|
||||
}
|
||||
|
||||
pub trait NSValue: Sized {
|
||||
unsafe fn valueWithPoint(_: Self, point: NSPoint) -> id {
|
||||
msg_send![class("NSValue"), valueWithPoint:point]
|
||||
}
|
||||
|
||||
unsafe fn valueWithSize(_: Self, size: NSSize) -> id {
|
||||
msg_send![class("NSValue"), valueWithSize:size]
|
||||
}
|
||||
}
|
||||
|
||||
impl NSValue for id {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
pub use self::macos::*;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct NSRange {
|
||||
pub location: NSUInteger,
|
||||
pub length: NSUInteger,
|
||||
}
|
||||
|
||||
impl NSRange {
|
||||
#[inline]
|
||||
pub fn new(location: NSUInteger, length: NSUInteger) -> NSRange {
|
||||
NSRange {
|
||||
location: location,
|
||||
length: length
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[link(name = "Foundation", kind = "framework")]
|
||||
extern {
|
||||
pub static NSDefaultRunLoopMode: id;
|
||||
}
|
||||
|
||||
pub trait NSAutoreleasePool: Sized {
|
||||
unsafe fn new(_: Self) -> id {
|
||||
msg_send![class("NSAutoreleasePool"), new]
|
||||
}
|
||||
|
||||
unsafe fn autorelease(self) -> Self;
|
||||
unsafe fn drain(self);
|
||||
}
|
||||
|
||||
impl NSAutoreleasePool for id {
|
||||
unsafe fn autorelease(self) -> id {
|
||||
msg_send![self, autorelease]
|
||||
}
|
||||
|
||||
unsafe fn drain(self) {
|
||||
msg_send![self, drain]
|
||||
}
|
||||
}
|
||||
|
||||
pub trait NSProcessInfo: Sized {
|
||||
unsafe fn processInfo(_: Self) -> id {
|
||||
msg_send![class("NSProcessInfo"), processInfo]
|
||||
}
|
||||
|
||||
unsafe fn processName(self) -> id;
|
||||
}
|
||||
|
||||
impl NSProcessInfo for id {
|
||||
unsafe fn processName(self) -> id {
|
||||
msg_send![self, processName]
|
||||
}
|
||||
}
|
||||
|
||||
pub type NSTimeInterval = libc::c_double;
|
||||
|
||||
pub trait NSArray: Sized {
|
||||
unsafe fn array(_: Self) -> id {
|
||||
msg_send![class("NSArray"), array]
|
||||
}
|
||||
|
||||
unsafe fn arrayWithObjects(_: Self, objects: &[id]) -> id {
|
||||
msg_send![class("NSArray"), arrayWithObjects:objects.as_ptr()
|
||||
count:objects.len()]
|
||||
}
|
||||
|
||||
unsafe fn arrayWithObject(_: Self, object: id) -> id {
|
||||
msg_send![class("NSArray"), arrayWithObject:object]
|
||||
}
|
||||
|
||||
unsafe fn arrayByAddingObjectFromArray(self, object: id) -> id;
|
||||
unsafe fn arrayByAddingObjectsFromArray(self, objects: id) -> id;
|
||||
}
|
||||
|
||||
impl NSArray for id {
|
||||
unsafe fn arrayByAddingObjectFromArray(self, object: id) -> id {
|
||||
msg_send![self, arrayByAddingObjectFromArray:object]
|
||||
}
|
||||
|
||||
unsafe fn arrayByAddingObjectsFromArray(self, objects: id) -> id {
|
||||
msg_send![self, arrayByAddingObjectsFromArray:objects]
|
||||
}
|
||||
}
|
||||
|
||||
pub trait NSDictionary: Sized {
|
||||
unsafe fn dictionary(_: Self) -> id {
|
||||
msg_send![class("NSDictionary"), dictionary]
|
||||
}
|
||||
|
||||
unsafe fn dictionaryWithContentsOfFile_(_: Self, path: id) -> id {
|
||||
msg_send![class("NSDictionary"), dictionaryWithContentsOfFile:path]
|
||||
}
|
||||
|
||||
unsafe fn dictionaryWithContentsOfURL_(_: Self, aURL: id) -> id {
|
||||
msg_send![class("NSDictionary"), dictionaryWithContentsOfURL:aURL]
|
||||
}
|
||||
|
||||
unsafe fn dictionaryWithDictionary_(_: Self, otherDictionary: id) -> id {
|
||||
msg_send![class("NSDictionary"), dictionaryWithDictionary:otherDictionary]
|
||||
}
|
||||
|
||||
unsafe fn dictionaryWithObject_forKey_(_: Self, anObject: id, aKey: id) -> id {
|
||||
msg_send![class("NSDictionary"), dictionaryWithObject:anObject forKey:aKey]
|
||||
}
|
||||
|
||||
unsafe fn dictionaryWithObjects_forKeys_(_: Self, objects: id, keys: id) -> id {
|
||||
msg_send![class("NSDictionary"), dictionaryWithObjects:objects forKeys:keys]
|
||||
}
|
||||
|
||||
unsafe fn dictionaryWithObjects_forKeys_count_(_: Self, objects: *const id, keys: *const id, count: NSUInteger) -> id {
|
||||
msg_send![class("NSDictionary"), dictionaryWithObjects:objects forKeys:keys count:count]
|
||||
}
|
||||
|
||||
unsafe fn dictionaryWithObjectsAndKeys_(_: Self, firstObject: id) -> id {
|
||||
msg_send![class("NSDictionary"), dictionaryWithObjectsAndKeys:firstObject]
|
||||
}
|
||||
|
||||
unsafe fn init(self) -> id;
|
||||
unsafe fn initWithContentsOfFile_(self, path: id) -> id;
|
||||
unsafe fn initWithContentsOfURL_(self, aURL: id) -> id;
|
||||
unsafe fn initWithDictionary_(self, otherDicitonary: id) -> id;
|
||||
unsafe fn initWithDictionary_copyItems_(self, otherDicitonary: id, flag: BOOL) -> id;
|
||||
unsafe fn initWithObjects_forKeys_(self, objects: id, keys: id) -> id;
|
||||
unsafe fn initWithObjects_forKeys_count_(self, objects: id, keys: id, count: NSUInteger) -> id;
|
||||
unsafe fn initWithObjectsAndKeys_(self, firstObject: id) -> id;
|
||||
|
||||
unsafe fn sharedKeySetForKeys_(_: Self, keys: id) -> id {
|
||||
msg_send![class("NSDictionary"), sharedKeySetForKeys:keys]
|
||||
}
|
||||
|
||||
unsafe fn count(self) -> NSUInteger;
|
||||
|
||||
unsafe fn isEqualToDictionary_(self, otherDictionary: id) -> BOOL;
|
||||
|
||||
unsafe fn allKeys(self) -> id;
|
||||
unsafe fn allKeysForObject_(self, anObject: id) -> id;
|
||||
unsafe fn allValues(self) -> id;
|
||||
unsafe fn objectForKey_(self, aKey: id) -> id;
|
||||
unsafe fn objectForKeyedSubscript_(self, key: id) -> id;
|
||||
unsafe fn objectsForKeys_notFoundMarker_(self, keys: id, anObject: id) -> id;
|
||||
unsafe fn valueForKey_(self, key: id) -> id;
|
||||
|
||||
unsafe fn keyEnumerator(self) -> id;
|
||||
unsafe fn objectEnumerator(self) -> id;
|
||||
unsafe fn enumerateKeysAndObjectsUsingBlock_(self, block: *mut Block<(id, id, *mut BOOL), ()>);
|
||||
unsafe fn enumerateKeysAndObjectsWithOptions_usingBlock_(self, opts: NSEnumerationOptions,
|
||||
block: *mut Block<(id, id, *mut BOOL), ()>);
|
||||
|
||||
unsafe fn keysSortedByValueUsingSelector_(self, comparator: SEL) -> id;
|
||||
unsafe fn keysSortedByValueUsingComparator_(self, cmptr: NSComparator) -> id;
|
||||
unsafe fn keysSortedByValueWithOptions_usingComparator_(self, opts: NSEnumerationOptions, cmptr: NSComparator) -> id;
|
||||
|
||||
unsafe fn keysOfEntriesPassingTest_(self, predicate: *mut Block<(id, id, *mut BOOL), BOOL>) -> id;
|
||||
unsafe fn keysOfEntriesWithOptions_PassingTest_(self, opts: NSEnumerationOptions,
|
||||
predicate: *mut Block<(id, id, *mut BOOL), BOOL>) -> id;
|
||||
|
||||
unsafe fn writeToFile_atomically_(self, path: id, flag: BOOL) -> BOOL;
|
||||
unsafe fn writeToURL_atomically_(self, aURL: id, flag: BOOL) -> BOOL;
|
||||
|
||||
unsafe fn fileCreationDate(self) -> id;
|
||||
unsafe fn fileExtensionHidden(self) -> BOOL;
|
||||
unsafe fn fileGroupOwnerAccountID(self) -> id;
|
||||
unsafe fn fileGroupOwnerAccountName(self) -> id;
|
||||
unsafe fn fileIsAppendOnly(self) -> BOOL;
|
||||
unsafe fn fileIsImmutable(self) -> BOOL;
|
||||
unsafe fn fileModificationDate(self) -> id;
|
||||
unsafe fn fileOwnerAccountID(self) -> id;
|
||||
unsafe fn fileOwnerAccountName(self) -> id;
|
||||
unsafe fn filePosixPermissions(self) -> NSUInteger;
|
||||
unsafe fn fileSize(self) -> libc::c_ulonglong;
|
||||
unsafe fn fileSystemFileNumber(self) -> NSUInteger;
|
||||
unsafe fn fileSystemNumber(self) -> NSInteger;
|
||||
unsafe fn fileType(self) -> id;
|
||||
|
||||
unsafe fn description(self) -> id;
|
||||
unsafe fn descriptionInStringsFileFormat(self) -> id;
|
||||
unsafe fn descriptionWithLocale_(self, locale: id) -> id;
|
||||
unsafe fn descriptionWithLocale_indent_(self, locale: id, indent: NSUInteger) -> id;
|
||||
}
|
||||
|
||||
impl NSDictionary for id {
|
||||
unsafe fn init(self) -> id {
|
||||
msg_send![self, init]
|
||||
}
|
||||
|
||||
unsafe fn initWithContentsOfFile_(self, path: id) -> id {
|
||||
msg_send![self, initWithContentsOfFile:path]
|
||||
}
|
||||
|
||||
unsafe fn initWithContentsOfURL_(self, aURL: id) -> id {
|
||||
msg_send![self, initWithContentsOfURL:aURL]
|
||||
}
|
||||
|
||||
unsafe fn initWithDictionary_(self, otherDictionary: id) -> id {
|
||||
msg_send![self, initWithDictionary:otherDictionary]
|
||||
}
|
||||
|
||||
unsafe fn initWithDictionary_copyItems_(self, otherDictionary: id, flag: BOOL) -> id {
|
||||
msg_send![self, initWithDictionary:otherDictionary copyItems:flag]
|
||||
}
|
||||
|
||||
unsafe fn initWithObjects_forKeys_(self, objects: id, keys: id) -> id {
|
||||
msg_send![self, initWithObjects:objects forKeys:keys]
|
||||
}
|
||||
|
||||
unsafe fn initWithObjects_forKeys_count_(self, objects: id, keys: id, count: NSUInteger) -> id {
|
||||
msg_send![self, initWithObjects:objects forKeys:keys count:count]
|
||||
}
|
||||
|
||||
unsafe fn initWithObjectsAndKeys_(self, firstObject: id) -> id {
|
||||
msg_send![self, initWithObjectsAndKeys:firstObject]
|
||||
}
|
||||
|
||||
unsafe fn count(self) -> NSUInteger {
|
||||
msg_send![self, count]
|
||||
}
|
||||
|
||||
unsafe fn isEqualToDictionary_(self, otherDictionary: id) -> BOOL {
|
||||
msg_send![self, isEqualToDictionary:otherDictionary]
|
||||
}
|
||||
|
||||
unsafe fn allKeys(self) -> id {
|
||||
msg_send![self, allKeys]
|
||||
}
|
||||
|
||||
unsafe fn allKeysForObject_(self, anObject: id) -> id {
|
||||
msg_send![self, allKeysForObject:anObject]
|
||||
}
|
||||
|
||||
unsafe fn allValues(self) -> id {
|
||||
msg_send![self, allValues]
|
||||
}
|
||||
|
||||
unsafe fn objectForKey_(self, aKey: id) -> id {
|
||||
msg_send![self, objectForKey:aKey]
|
||||
}
|
||||
|
||||
unsafe fn objectForKeyedSubscript_(self, key: id) -> id {
|
||||
msg_send![self, objectForKeyedSubscript:key]
|
||||
}
|
||||
|
||||
unsafe fn objectsForKeys_notFoundMarker_(self, keys: id, anObject: id) -> id {
|
||||
msg_send![self, objectsForKeys:keys notFoundMarker:anObject]
|
||||
}
|
||||
|
||||
unsafe fn valueForKey_(self, key: id) -> id {
|
||||
msg_send![self, valueForKey:key]
|
||||
}
|
||||
|
||||
unsafe fn keyEnumerator(self) -> id {
|
||||
msg_send![self, keyEnumerator]
|
||||
}
|
||||
|
||||
unsafe fn objectEnumerator(self) -> id {
|
||||
msg_send![self, objectEnumerator]
|
||||
}
|
||||
|
||||
unsafe fn enumerateKeysAndObjectsUsingBlock_(self, block: *mut Block<(id, id, *mut BOOL), ()>) {
|
||||
msg_send![self, enumerateKeysAndObjectsUsingBlock:block]
|
||||
}
|
||||
|
||||
unsafe fn enumerateKeysAndObjectsWithOptions_usingBlock_(self, opts: NSEnumerationOptions,
|
||||
block: *mut Block<(id, id, *mut BOOL), ()>) {
|
||||
msg_send![self, enumerateKeysAndObjectsWithOptions:opts usingBlock:block]
|
||||
}
|
||||
|
||||
unsafe fn keysSortedByValueUsingSelector_(self, comparator: SEL) -> id {
|
||||
msg_send![self, keysSortedByValueUsingSelector:comparator]
|
||||
}
|
||||
|
||||
unsafe fn keysSortedByValueUsingComparator_(self, cmptr: NSComparator) -> id {
|
||||
msg_send![self, keysSortedByValueUsingComparator:cmptr]
|
||||
}
|
||||
|
||||
unsafe fn keysSortedByValueWithOptions_usingComparator_(self, opts: NSEnumerationOptions, cmptr: NSComparator) -> id {
|
||||
let rv: id = msg_send![self, keysSortedByValueWithOptions:opts usingComparator:cmptr];
|
||||
rv
|
||||
}
|
||||
|
||||
unsafe fn keysOfEntriesPassingTest_(self, predicate: *mut Block<(id, id, *mut BOOL), BOOL>) -> id {
|
||||
msg_send![self, keysOfEntriesPassingTest:predicate]
|
||||
}
|
||||
|
||||
unsafe fn keysOfEntriesWithOptions_PassingTest_(self, opts: NSEnumerationOptions,
|
||||
predicate: *mut Block<(id, id, *mut BOOL), BOOL>) -> id {
|
||||
msg_send![self, keysOfEntriesWithOptions:opts PassingTest:predicate]
|
||||
}
|
||||
|
||||
unsafe fn writeToFile_atomically_(self, path: id, flag: BOOL) -> BOOL {
|
||||
msg_send![self, writeToFile:path atomically:flag]
|
||||
}
|
||||
|
||||
unsafe fn writeToURL_atomically_(self, aURL: id, flag: BOOL) -> BOOL {
|
||||
msg_send![self, writeToURL:aURL atomically:flag]
|
||||
}
|
||||
|
||||
unsafe fn fileCreationDate(self) -> id {
|
||||
msg_send![self, fileCreationDate]
|
||||
}
|
||||
|
||||
unsafe fn fileExtensionHidden(self) -> BOOL {
|
||||
msg_send![self, fileExtensionHidden]
|
||||
}
|
||||
|
||||
unsafe fn fileGroupOwnerAccountID(self) -> id {
|
||||
msg_send![self, fileGroupOwnerAccountID]
|
||||
}
|
||||
|
||||
unsafe fn fileGroupOwnerAccountName(self) -> id {
|
||||
msg_send![self, fileGroupOwnerAccountName]
|
||||
}
|
||||
|
||||
unsafe fn fileIsAppendOnly(self) -> BOOL {
|
||||
msg_send![self, fileIsAppendOnly]
|
||||
}
|
||||
|
||||
unsafe fn fileIsImmutable(self) -> BOOL {
|
||||
msg_send![self, fileIsImmutable]
|
||||
}
|
||||
|
||||
unsafe fn fileModificationDate(self) -> id {
|
||||
msg_send![self, fileModificationDate]
|
||||
}
|
||||
|
||||
unsafe fn fileOwnerAccountID(self) -> id {
|
||||
msg_send![self, fileOwnerAccountID]
|
||||
}
|
||||
|
||||
unsafe fn fileOwnerAccountName(self) -> id {
|
||||
msg_send![self, fileOwnerAccountName]
|
||||
}
|
||||
|
||||
unsafe fn filePosixPermissions(self) -> NSUInteger {
|
||||
msg_send![self, filePosixPermissions]
|
||||
}
|
||||
|
||||
unsafe fn fileSize(self) -> libc::c_ulonglong {
|
||||
msg_send![self, fileSize]
|
||||
}
|
||||
|
||||
unsafe fn fileSystemFileNumber(self) -> NSUInteger {
|
||||
msg_send![self, fileSystemFileNumber]
|
||||
}
|
||||
|
||||
unsafe fn fileSystemNumber(self) -> NSInteger {
|
||||
msg_send![self, fileSystemNumber]
|
||||
}
|
||||
|
||||
unsafe fn fileType(self) -> id {
|
||||
msg_send![self, fileType]
|
||||
}
|
||||
|
||||
unsafe fn description(self) -> id {
|
||||
msg_send![self, description]
|
||||
}
|
||||
|
||||
unsafe fn descriptionInStringsFileFormat(self) -> id {
|
||||
msg_send![self, descriptionInStringsFileFormat]
|
||||
}
|
||||
|
||||
unsafe fn descriptionWithLocale_(self, locale: id) -> id {
|
||||
msg_send![self, descriptionWithLocale:locale]
|
||||
}
|
||||
|
||||
unsafe fn descriptionWithLocale_indent_(self, locale: id, indent: NSUInteger) -> id {
|
||||
msg_send![self, descriptionWithLocale:locale indent:indent]
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
pub struct NSEnumerationOptions: libc::c_ulonglong {
|
||||
const NSEnumerationConcurrent = 1 << 0;
|
||||
const NSEnumerationReverse = 1 << 1;
|
||||
}
|
||||
}
|
||||
|
||||
pub type NSComparator = *mut Block<(id, id), NSComparisonResult>;
|
||||
|
||||
#[repr(isize)]
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub enum NSComparisonResult {
|
||||
NSOrderedAscending = -1,
|
||||
NSOrderedSame = 0,
|
||||
NSOrderedDescending = 1
|
||||
}
|
||||
|
||||
pub trait NSString: Sized {
|
||||
unsafe fn alloc(_: Self) -> id {
|
||||
msg_send![class("NSString"), alloc]
|
||||
}
|
||||
|
||||
unsafe fn stringByAppendingString_(self, other: id) -> id;
|
||||
unsafe fn init_str(self, string: &str) -> Self;
|
||||
unsafe fn UTF8String(self) -> *const libc::c_char;
|
||||
unsafe fn len(self) -> usize;
|
||||
unsafe fn isEqualToString(self, &str) -> bool;
|
||||
}
|
||||
|
||||
impl NSString for id {
|
||||
unsafe fn isEqualToString(self, other: &str) -> bool {
|
||||
let other = NSString::alloc(nil).init_str(other);
|
||||
let rv: BOOL = msg_send![self, isEqualToString:other];
|
||||
rv != NO
|
||||
}
|
||||
|
||||
unsafe fn stringByAppendingString_(self, other: id) -> id {
|
||||
msg_send![self, stringByAppendingString:other]
|
||||
}
|
||||
|
||||
unsafe fn init_str(self, string: &str) -> id {
|
||||
return msg_send![self,
|
||||
initWithBytes:string.as_ptr()
|
||||
length:string.len()
|
||||
encoding:UTF8_ENCODING as id];
|
||||
}
|
||||
|
||||
unsafe fn len(self) -> usize {
|
||||
msg_send![self, lengthOfBytesUsingEncoding:UTF8_ENCODING]
|
||||
}
|
||||
|
||||
unsafe fn UTF8String(self) -> *const libc::c_char {
|
||||
msg_send![self, UTF8String]
|
||||
}
|
||||
}
|
||||
|
||||
pub trait NSDate: Sized {
|
||||
unsafe fn distantPast(_: Self) -> id {
|
||||
msg_send![class("NSDate"), distantPast]
|
||||
}
|
||||
|
||||
unsafe fn distantFuture(_: Self) -> id {
|
||||
msg_send![class("NSDate"), distantFuture]
|
||||
}
|
||||
}
|
||||
|
||||
impl NSDate for id {
|
||||
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
struct NSFastEnumerationState {
|
||||
pub state: libc::c_ulong,
|
||||
pub items_ptr: *mut id,
|
||||
pub mutations_ptr: *mut libc::c_ulong,
|
||||
pub extra: [libc::c_ulong; 5]
|
||||
}
|
||||
|
||||
const NS_FAST_ENUM_BUF_SIZE: usize = 16;
|
||||
|
||||
pub struct NSFastIterator {
|
||||
state: NSFastEnumerationState,
|
||||
buffer: [id; NS_FAST_ENUM_BUF_SIZE],
|
||||
mut_val: Option<libc::c_ulong>,
|
||||
len: usize,
|
||||
idx: usize,
|
||||
object: id
|
||||
}
|
||||
|
||||
impl Iterator for NSFastIterator {
|
||||
type Item = id;
|
||||
|
||||
fn next(&mut self) -> Option<id> {
|
||||
if self.idx >= self.len {
|
||||
self.len = unsafe {
|
||||
msg_send![self.object, countByEnumeratingWithState:&mut self.state objects:self.buffer.as_mut_ptr() count:NS_FAST_ENUM_BUF_SIZE]
|
||||
};
|
||||
self.idx = 0;
|
||||
}
|
||||
|
||||
let new_mut = unsafe {
|
||||
*self.state.mutations_ptr
|
||||
};
|
||||
|
||||
if let Some(old_mut) = self.mut_val {
|
||||
assert!(old_mut == new_mut, "The collection was mutated while being enumerated");
|
||||
}
|
||||
|
||||
if self.idx < self.len {
|
||||
let object = unsafe {
|
||||
*self.state.items_ptr.offset(self.idx as isize)
|
||||
};
|
||||
self.mut_val = Some(new_mut);
|
||||
self.idx += 1;
|
||||
Some(object)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait NSFastEnumeration: Sized {
|
||||
unsafe fn iter(self) -> NSFastIterator;
|
||||
}
|
||||
|
||||
impl NSFastEnumeration for id {
|
||||
unsafe fn iter(self) -> NSFastIterator {
|
||||
NSFastIterator {
|
||||
state: NSFastEnumerationState {
|
||||
state: 0,
|
||||
items_ptr: ptr::null_mut(),
|
||||
mutations_ptr: ptr::null_mut(),
|
||||
extra: [0; 5]
|
||||
},
|
||||
buffer: [nil; NS_FAST_ENUM_BUF_SIZE],
|
||||
mut_val: None,
|
||||
len: 0,
|
||||
idx: 0,
|
||||
object: self
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait NSRunLoop: Sized {
|
||||
unsafe fn currentRunLoop() -> Self;
|
||||
|
||||
unsafe fn performSelector_target_argument_order_modes_(self,
|
||||
aSelector: SEL,
|
||||
target: id,
|
||||
anArgument: id,
|
||||
order: NSUInteger,
|
||||
modes: id);
|
||||
}
|
||||
|
||||
impl NSRunLoop for id {
|
||||
unsafe fn currentRunLoop() -> id {
|
||||
msg_send![class("NSRunLoop"), currentRunLoop]
|
||||
}
|
||||
|
||||
unsafe fn performSelector_target_argument_order_modes_(self,
|
||||
aSelector: SEL,
|
||||
target: id,
|
||||
anArgument: id,
|
||||
order: NSUInteger,
|
||||
modes: id) {
|
||||
msg_send![self, performSelector:aSelector
|
||||
target:target
|
||||
argument:anArgument
|
||||
order:order
|
||||
modes:modes]
|
||||
}
|
||||
}
|
||||
|
||||
pub trait NSData: Sized {
|
||||
unsafe fn data(_: Self) -> id {
|
||||
msg_send![class("NSData"), data]
|
||||
}
|
||||
|
||||
unsafe fn dataWithBytes_length_(_: Self, bytes: *const libc::c_void, length: NSUInteger) -> id {
|
||||
msg_send![class("NSData"), dataWithBytes:bytes length:length]
|
||||
}
|
||||
|
||||
unsafe fn dataWithBytesNoCopy_length_(_: Self, bytes: *const libc::c_void, length: NSUInteger) -> id {
|
||||
msg_send![class("NSData"), dataWithBytesNoCopy:bytes length:length]
|
||||
}
|
||||
|
||||
unsafe fn dataWithBytesNoCopy_length_freeWhenDone_(_: Self, bytes: *const libc::c_void,
|
||||
length: NSUInteger, freeWhenDone: BOOL) -> id {
|
||||
msg_send![class("NSData"), dataWithBytesNoCopy:bytes length:length freeWhenDone:freeWhenDone]
|
||||
}
|
||||
|
||||
unsafe fn dataWithContentsOfFile_(_: Self, path: id) -> id {
|
||||
msg_send![class("NSData"), dataWithContentsOfFile:path]
|
||||
}
|
||||
|
||||
unsafe fn dataWithContentsOfFile_options_error_(_: Self, path: id, mask: NSDataReadingOptions,
|
||||
errorPtr: *mut id) -> id {
|
||||
msg_send![class("NSData"), dataWithContentsOfFile:path options:mask error:errorPtr]
|
||||
}
|
||||
|
||||
unsafe fn dataWithContentsOfURL_(_: Self, aURL: id) -> id {
|
||||
msg_send![class("NSData"), dataWithContentsOfURL:aURL]
|
||||
}
|
||||
|
||||
unsafe fn dataWithContentsOfURL_options_error_(_: Self, aURL: id, mask: NSDataReadingOptions,
|
||||
errorPtr: *mut id) -> id {
|
||||
msg_send![class("NSData"), dataWithContentsOfURL:aURL options:mask error:errorPtr]
|
||||
}
|
||||
|
||||
unsafe fn dataWithData_(_: Self, aData: id) -> id {
|
||||
msg_send![class("NSData"), dataWithData:aData]
|
||||
}
|
||||
|
||||
unsafe fn initWithBase64EncodedData_options_(self, base64Data: id, options: NSDataBase64DecodingOptions)
|
||||
-> id;
|
||||
unsafe fn initWithBase64EncodedString_options_(self, base64String: id, options: NSDataBase64DecodingOptions)
|
||||
-> id;
|
||||
unsafe fn initWithBytes_length_(self, bytes: *const libc::c_void, length: NSUInteger) -> id;
|
||||
unsafe fn initWithBytesNoCopy_length_(self, bytes: *const libc::c_void, length: NSUInteger) -> id;
|
||||
unsafe fn initWithBytesNoCopy_length_deallocator_(self, bytes: *const libc::c_void, length: NSUInteger,
|
||||
deallocator: *mut Block<(*const libc::c_void, NSUInteger), ()>)
|
||||
-> id;
|
||||
unsafe fn initWithBytesNoCopy_length_freeWhenDone_(self, bytes: *const libc::c_void,
|
||||
length: NSUInteger, freeWhenDone: BOOL) -> id;
|
||||
unsafe fn initWithContentsOfFile_(self, path: id) -> id;
|
||||
unsafe fn initWithContentsOfFile_options_error(self, path: id, mask: NSDataReadingOptions, errorPtr: *mut id)
|
||||
-> id;
|
||||
unsafe fn initWithContentsOfURL_(self, aURL: id) -> id;
|
||||
unsafe fn initWithContentsOfURL_options_error_(self, aURL: id, mask: NSDataReadingOptions, errorPtr: *mut id)
|
||||
-> id;
|
||||
unsafe fn initWithData_(self, data: id) -> id;
|
||||
|
||||
unsafe fn bytes(self) -> *const libc::c_void;
|
||||
unsafe fn description(self) -> id;
|
||||
unsafe fn enumerateByteRangesUsingBlock_(self, block: *mut Block<(*const libc::c_void, NSRange, *mut BOOL), ()>);
|
||||
unsafe fn getBytes_length_(self, buffer: *mut libc::c_void, length: NSUInteger);
|
||||
unsafe fn getBytes_range_(self, buffer: *mut libc::c_void, range: NSRange);
|
||||
unsafe fn subdataWithRange_(self, range: NSRange) -> id;
|
||||
unsafe fn rangeOfData_options_range_(self, dataToFind: id, options: NSDataSearchOptions, searchRange: NSRange)
|
||||
-> NSRange;
|
||||
|
||||
unsafe fn base64EncodedDataWithOptions_(self, options: NSDataBase64EncodingOptions) -> id;
|
||||
unsafe fn base64EncodedStringWithOptions_(self, options: NSDataBase64EncodingOptions) -> id;
|
||||
|
||||
unsafe fn isEqualToData_(self, otherData: id) -> id;
|
||||
unsafe fn length(self) -> NSUInteger;
|
||||
|
||||
unsafe fn writeToFile_atomically_(self, path: id, atomically: BOOL) -> BOOL;
|
||||
unsafe fn writeToFile_options_error_(self, path: id, mask: NSDataWritingOptions, errorPtr: *mut id) -> BOOL;
|
||||
unsafe fn writeToURL_atomically_(self, aURL: id, atomically: BOOL) -> BOOL;
|
||||
unsafe fn writeToURL_options_error_(self, aURL: id, mask: NSDataWritingOptions, errorPtr: *mut id) -> BOOL;
|
||||
}
|
||||
|
||||
impl NSData for id {
|
||||
unsafe fn initWithBase64EncodedData_options_(self, base64Data: id, options: NSDataBase64DecodingOptions)
|
||||
-> id {
|
||||
msg_send![self, initWithBase64EncodedData:base64Data options:options]
|
||||
}
|
||||
|
||||
unsafe fn initWithBase64EncodedString_options_(self, base64String: id, options: NSDataBase64DecodingOptions)
|
||||
-> id {
|
||||
msg_send![self, initWithBase64EncodedString:base64String options:options]
|
||||
}
|
||||
|
||||
unsafe fn initWithBytes_length_(self, bytes: *const libc::c_void, length: NSUInteger) -> id {
|
||||
msg_send![self,initWithBytes:bytes length:length]
|
||||
}
|
||||
|
||||
unsafe fn initWithBytesNoCopy_length_(self, bytes: *const libc::c_void, length: NSUInteger) -> id {
|
||||
msg_send![self, initWithBytesNoCopy:bytes length:length]
|
||||
}
|
||||
|
||||
unsafe fn initWithBytesNoCopy_length_deallocator_(self, bytes: *const libc::c_void, length: NSUInteger,
|
||||
deallocator: *mut Block<(*const libc::c_void, NSUInteger), ()>)
|
||||
-> id {
|
||||
msg_send![self, initWithBytesNoCopy:bytes length:length deallocator:deallocator]
|
||||
}
|
||||
|
||||
unsafe fn initWithBytesNoCopy_length_freeWhenDone_(self, bytes: *const libc::c_void,
|
||||
length: NSUInteger, freeWhenDone: BOOL) -> id {
|
||||
msg_send![self, initWithBytesNoCopy:bytes length:length freeWhenDone:freeWhenDone]
|
||||
}
|
||||
|
||||
unsafe fn initWithContentsOfFile_(self, path: id) -> id {
|
||||
msg_send![self, initWithContentsOfFile:path]
|
||||
}
|
||||
|
||||
unsafe fn initWithContentsOfFile_options_error(self, path: id, mask: NSDataReadingOptions, errorPtr: *mut id)
|
||||
-> id {
|
||||
msg_send![self, initWithContentsOfFile:path options:mask error:errorPtr]
|
||||
}
|
||||
|
||||
unsafe fn initWithContentsOfURL_(self, aURL: id) -> id {
|
||||
msg_send![self, initWithContentsOfURL:aURL]
|
||||
}
|
||||
|
||||
unsafe fn initWithContentsOfURL_options_error_(self, aURL: id, mask: NSDataReadingOptions, errorPtr: *mut id)
|
||||
-> id {
|
||||
msg_send![self, initWithContentsOfURL:aURL options:mask error:errorPtr]
|
||||
}
|
||||
|
||||
unsafe fn initWithData_(self, data: id) -> id {
|
||||
msg_send![self, initWithData:data]
|
||||
}
|
||||
|
||||
unsafe fn bytes(self) -> *const libc::c_void {
|
||||
msg_send![self, bytes]
|
||||
}
|
||||
|
||||
unsafe fn description(self) -> id {
|
||||
msg_send![self, description]
|
||||
}
|
||||
|
||||
unsafe fn enumerateByteRangesUsingBlock_(self, block: *mut Block<(*const libc::c_void, NSRange, *mut BOOL), ()>) {
|
||||
msg_send![self, enumerateByteRangesUsingBlock:block]
|
||||
}
|
||||
|
||||
unsafe fn getBytes_length_(self, buffer: *mut libc::c_void, length: NSUInteger) {
|
||||
msg_send![self, getBytes:buffer length:length]
|
||||
}
|
||||
|
||||
unsafe fn getBytes_range_(self, buffer: *mut libc::c_void, range: NSRange) {
|
||||
msg_send![self, getBytes:buffer range:range]
|
||||
}
|
||||
|
||||
unsafe fn subdataWithRange_(self, range: NSRange) -> id {
|
||||
msg_send![self, subdataWithRange:range]
|
||||
}
|
||||
|
||||
unsafe fn rangeOfData_options_range_(self, dataToFind: id, options: NSDataSearchOptions, searchRange: NSRange)
|
||||
-> NSRange {
|
||||
msg_send![self, rangeOfData:dataToFind options:options range:searchRange]
|
||||
}
|
||||
|
||||
unsafe fn base64EncodedDataWithOptions_(self, options: NSDataBase64EncodingOptions) -> id {
|
||||
msg_send![self, base64EncodedDataWithOptions:options]
|
||||
}
|
||||
|
||||
unsafe fn base64EncodedStringWithOptions_(self, options: NSDataBase64EncodingOptions) -> id {
|
||||
msg_send![self, base64EncodedStringWithOptions:options]
|
||||
}
|
||||
|
||||
unsafe fn isEqualToData_(self, otherData: id) -> id {
|
||||
msg_send![self, isEqualToData:otherData]
|
||||
}
|
||||
|
||||
unsafe fn length(self) -> NSUInteger {
|
||||
msg_send![self, length]
|
||||
}
|
||||
|
||||
unsafe fn writeToFile_atomically_(self, path: id, atomically: BOOL) -> BOOL {
|
||||
msg_send![self, writeToFile:path atomically:atomically]
|
||||
}
|
||||
|
||||
unsafe fn writeToFile_options_error_(self, path: id, mask: NSDataWritingOptions, errorPtr: *mut id) -> BOOL {
|
||||
msg_send![self, writeToFile:path options:mask error:errorPtr]
|
||||
}
|
||||
|
||||
unsafe fn writeToURL_atomically_(self, aURL: id, atomically: BOOL) -> BOOL {
|
||||
msg_send![self, writeToURL:aURL atomically:atomically]
|
||||
}
|
||||
|
||||
unsafe fn writeToURL_options_error_(self, aURL: id, mask: NSDataWritingOptions, errorPtr: *mut id) -> BOOL {
|
||||
msg_send![self, writeToURL:aURL options:mask error:errorPtr]
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
pub struct NSDataReadingOptions: libc::c_ulonglong {
|
||||
const NSDataReadingMappedIfSafe = 1 << 0;
|
||||
const NSDataReadingUncached = 1 << 1;
|
||||
const NSDataReadingMappedAlways = 1 << 3;
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
pub struct NSDataBase64EncodingOptions: libc::c_ulonglong {
|
||||
const NSDataBase64Encoding64CharacterLineLength = 1 << 0;
|
||||
const NSDataBase64Encoding76CharacterLineLength = 1 << 1;
|
||||
const NSDataBase64EncodingEndLineWithCarriageReturn = 1 << 4;
|
||||
const NSDataBase64EncodingEndLineWithLineFeed = 1 << 5;
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
pub struct NSDataBase64DecodingOptions: libc::c_ulonglong {
|
||||
const NSDataBase64DecodingIgnoreUnknownCharacters = 1 << 0;
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
pub struct NSDataWritingOptions: libc::c_ulonglong {
|
||||
const NSDataWritingAtomic = 1 << 0;
|
||||
const NSDataWritingWithoutOverwriting = 1 << 1;
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
pub struct NSDataSearchOptions: libc::c_ulonglong {
|
||||
const NSDataSearchBackwards = 1 << 0;
|
||||
const NSDataSearchAnchored = 1 << 1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.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.
|
||||
|
||||
#![crate_name = "cocoa"]
|
||||
#![crate_type = "rlib"]
|
||||
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
extern crate block;
|
||||
#[macro_use]
|
||||
extern crate bitflags;
|
||||
extern crate libc;
|
||||
extern crate core_graphics;
|
||||
#[macro_use]
|
||||
extern crate objc;
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
pub mod appkit;
|
||||
pub mod base;
|
||||
pub mod foundation;
|
||||
@@ -0,0 +1,189 @@
|
||||
#[macro_use]
|
||||
extern crate objc;
|
||||
extern crate block;
|
||||
extern crate cocoa;
|
||||
|
||||
#[cfg(test)]
|
||||
mod foundation {
|
||||
mod nsstring {
|
||||
use cocoa::foundation::NSString;
|
||||
use cocoa::base::nil;
|
||||
use std::slice;
|
||||
use std::str;
|
||||
|
||||
#[test]
|
||||
fn test_utf8() {
|
||||
let expected = "Iñtërnâtiônàlizætiøn";
|
||||
unsafe {
|
||||
let built = NSString::alloc(nil).init_str(expected);
|
||||
let bytes = built.UTF8String() as *const u8;
|
||||
let objc_string = str::from_utf8(slice::from_raw_parts(bytes, built.len()))
|
||||
.unwrap();
|
||||
assert!(objc_string.len() == expected.len());
|
||||
assert!(objc_string == expected);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_string() {
|
||||
let expected = "Hello World!";
|
||||
unsafe {
|
||||
let built = NSString::alloc(nil).init_str(expected);
|
||||
let bytes = built.UTF8String() as *const u8;
|
||||
let objc_string = str::from_utf8(slice::from_raw_parts(bytes, built.len()))
|
||||
.unwrap();
|
||||
assert!(objc_string.len() == expected.len());
|
||||
assert!(objc_string == expected);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_length() {
|
||||
let expected = "Hello!";
|
||||
unsafe {
|
||||
let built = NSString::alloc(nil).init_str(expected);
|
||||
assert!(built.len() == expected.len());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_append_by_appending_string() {
|
||||
let initial_str = "Iñtërnâtiônàlizætiøn";
|
||||
let to_append = "_more_strings";
|
||||
let expected = concat!("Iñtërnâtiônàlizætiøn", "_more_strings");
|
||||
unsafe {
|
||||
let built = NSString::alloc(nil).init_str(initial_str);
|
||||
let built_to_append = NSString::alloc(nil).init_str(to_append);
|
||||
let append_string = built.stringByAppendingString_(built_to_append);
|
||||
let bytes = append_string.UTF8String() as *const u8;
|
||||
let objc_string = str::from_utf8(slice::from_raw_parts(bytes, append_string.len()))
|
||||
.unwrap();
|
||||
assert!(objc_string == expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mod nsfastenumeration {
|
||||
use std::str;
|
||||
use std::slice;
|
||||
use cocoa::foundation::{NSString, NSFastEnumeration};
|
||||
use cocoa::base::{id, nil};
|
||||
|
||||
#[test]
|
||||
fn test_iter() {
|
||||
unsafe {
|
||||
let string = NSString::alloc(nil).init_str("this is a test string");
|
||||
let separator = NSString::alloc(nil).init_str(" ");
|
||||
let components: id = msg_send![string, componentsSeparatedByString: separator];
|
||||
|
||||
let combined = components.iter()
|
||||
.map(|s| {
|
||||
let bytes = s.UTF8String() as *const u8;
|
||||
str::from_utf8(slice::from_raw_parts(bytes, s.len())).unwrap()
|
||||
})
|
||||
.fold(String::new(), |mut acc, s| {
|
||||
acc.push_str(s);
|
||||
acc
|
||||
});
|
||||
|
||||
assert_eq!(combined, "thisisateststring");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_mutation() {
|
||||
unsafe {
|
||||
let string = NSString::alloc(nil).init_str("this is a test string");
|
||||
let separator = NSString::alloc(nil).init_str(" ");
|
||||
let components: id = msg_send![string, componentsSeparatedByString: separator];
|
||||
let mut_components: id = msg_send![components, mutableCopy];
|
||||
let mut iter = mut_components.iter();
|
||||
iter.next();
|
||||
msg_send![mut_components, removeObjectAtIndex:1];
|
||||
iter.next();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mod nsdictionary {
|
||||
use block::ConcreteBlock;
|
||||
use cocoa::foundation::{NSArray, NSComparisonResult, NSDictionary, NSFastEnumeration,
|
||||
NSString};
|
||||
use cocoa::base::{id, nil};
|
||||
|
||||
#[test]
|
||||
fn test_get() {
|
||||
const KEY: &'static str = "The key";
|
||||
const VALUE: &'static str = "Some value";
|
||||
unsafe {
|
||||
let key = NSString::alloc(nil).init_str(KEY);
|
||||
let value = NSString::alloc(nil).init_str(VALUE);
|
||||
let dict = NSDictionary::dictionaryWithObject_forKey_(nil, value, key);
|
||||
|
||||
let retrieved_value = dict.objectForKey_(key);
|
||||
assert!(retrieved_value.isEqualToString(VALUE));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_iter() {
|
||||
let mkstr = |s| unsafe { NSString::alloc(nil).init_str(s) };
|
||||
let keys = vec!["a", "b", "c", "d", "e", "f"];
|
||||
let objects = vec!["1", "2", "3", "4", "5", "6"];
|
||||
unsafe {
|
||||
use std::{slice, str};
|
||||
use std::cmp::{Ord, Ordering};
|
||||
|
||||
let keys_raw_vec = keys.clone().into_iter().map(&mkstr).collect::<Vec<_>>();
|
||||
let objs_raw_vec = objects.clone().into_iter().map(&mkstr).collect::<Vec<_>>();
|
||||
|
||||
let keys_array = NSArray::arrayWithObjects(nil, &keys_raw_vec);
|
||||
let objs_array = NSArray::arrayWithObjects(nil, &objs_raw_vec);
|
||||
|
||||
let dict =
|
||||
NSDictionary::dictionaryWithObjects_forKeys_(nil, objs_array, keys_array);
|
||||
|
||||
// NSDictionary does not store its contents in order of insertion, so ask for
|
||||
// sorted iterators to ensure that each item is the same as its counterpart in
|
||||
// the vector.
|
||||
|
||||
// First test cocoa sorting...
|
||||
let mut comparator = ConcreteBlock::new(|s0: id, s1: id| {
|
||||
let (bytes0, len0) = (s0.UTF8String() as *const u8, s0.len());
|
||||
let (bytes1, len1) = (s1.UTF8String() as *const u8, s1.len());
|
||||
let (s0, s1) = (str::from_utf8(slice::from_raw_parts(bytes0, len0)).unwrap(),
|
||||
str::from_utf8(slice::from_raw_parts(bytes1, len1)).unwrap());
|
||||
let (c0, c1) = (s0.chars().next().unwrap(), s1.chars().next().unwrap());
|
||||
match c0.cmp(&c1) {
|
||||
Ordering::Less => NSComparisonResult::NSOrderedAscending,
|
||||
Ordering::Equal => NSComparisonResult::NSOrderedSame,
|
||||
Ordering::Greater => NSComparisonResult::NSOrderedDescending,
|
||||
}
|
||||
});
|
||||
|
||||
let associated_iter = keys.iter().zip(objects.iter());
|
||||
for (k_id, (k, v)) in dict.keysSortedByValueUsingComparator_(&mut *comparator)
|
||||
.iter()
|
||||
.zip(associated_iter) {
|
||||
assert!(k_id.isEqualToString(k));
|
||||
let v_id = dict.objectForKey_(k_id);
|
||||
assert!(v_id.isEqualToString(v));
|
||||
}
|
||||
|
||||
// Then use rust sorting
|
||||
let mut keys_arr = dict.allKeys().iter().collect::<Vec<_>>();
|
||||
keys_arr.sort();
|
||||
for (k0, k1) in keys_arr.into_iter().zip(keys.iter()) {
|
||||
assert!(k0.isEqualToString(k1));
|
||||
}
|
||||
|
||||
let mut objects_arr = dict.allValues().iter().collect::<Vec<_>>();
|
||||
objects_arr.sort();
|
||||
for (v0, v1) in objects_arr.into_iter().zip(objects.iter()) {
|
||||
assert!(v0.isEqualToString(v1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user