Vendor things
This commit is contained in:
parent
5deceec006
commit
977e3c17e5
19434 changed files with 10682014 additions and 0 deletions
1
third-party/vendor/core-foundation/.cargo-checksum.json
vendored
Normal file
1
third-party/vendor/core-foundation/.cargo-checksum.json
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"files":{"Cargo.toml":"2e85272c5cffb75aadcbb83d8ca1a619af3ccb9d810c1e07349f3b618fa05b7e","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","src/array.rs":"1ec64187ec7c3ff0a9cf9739fb83d1f0b6141d827e4f21a14203b7058ca12056","src/attributed_string.rs":"7c129d266872bf9e0f8cbd9477d8cc27405b806395e59e1647bedf9af06f8949","src/base.rs":"7ec2afcbc200aabaa01687efce2eb27c9effc9eae64d3c579827de731fbd290e","src/boolean.rs":"60aef5be531e867f03524c32a88609100d07d9166184545feab760af9eb3d7ec","src/bundle.rs":"00f7ae30df3cc59079e771da0eda2b1972f52b13cc7bd95ae48b0e9bd1836ff4","src/characterset.rs":"126884d51e75db5be4cb2988f4e97e0e1b592c900e0158082d8c0dda7a453b0f","src/data.rs":"bfaa4427b6bc4c838188506ee154622983bbfcc10641be3f58525b89a854d4cd","src/date.rs":"d1ec3f918cf6c62d0e36d50d495c125d275a9a89442a740eea5d41dcc71a96fa","src/dictionary.rs":"f6d73c08fa9afd30d1df70cceea55dd30c7b81b8a78117d8843f1b3390051dca","src/error.rs":"433982fb7b421f5bf386d7eba22a7ffb8673486bb6455ff3fa30c875b064f718","src/filedescriptor.rs":"d3ece69ff461b215f7ff98dc6139723c4a5a53849a9747cccd24e72c185c4ffd","src/lib.rs":"92502d5f7d0e2ba266ec3531c01dd996e1832f1e6e9e66b10596e6fb870480cb","src/mach_port.rs":"e5400039696a70bdc0e6e14b1a68c493b741136945ce0eb67208cd4d0f895e1b","src/number.rs":"48e2efe219a7eaa4bc7bc3a48fa45f32fbbfd6363620838fef16a98b86e05061","src/propertylist.rs":"23e9a42d506983374d0c3439ab80407bbd472a3487812693a411597ff5eb1bd8","src/runloop.rs":"ff5bbb8a145befa7f244d937161d87f059ea60c9c482ab32e845222ee6fabf34","src/set.rs":"39e41a3d4f9e4dd50864a9c3581508e1b09549dc89d57fa84935964d98469bad","src/string.rs":"3b25b169d0f18dae66e6f123a116a04c79096f9e44e4221d4dbdcea4e152355c","src/timezone.rs":"7b8e46bde9e8aa71a906ab26b8ff7b6251568ebf210bab10d11c6ba0ce64ecd5","src/url.rs":"dc125dd95e9b8386770b89f5437ab904ceff0843e1bf820f548bddfc31e1c40c","src/uuid.rs":"e290c592871b7cea6ec09d2b3e34ec9033968dda725cf49e410535f79d2b41f8","tests/use_macro_outside_crate.rs":"ed5e74ac9e988f2609c0b785189f1e6368d693f6401603ad065521f3ab51df94"},"package":"91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f"}
|
||||
53
third-party/vendor/core-foundation/Cargo.toml
vendored
Normal file
53
third-party/vendor/core-foundation/Cargo.toml
vendored
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
|
||||
#
|
||||
# When uploading crates to the registry Cargo will automatically
|
||||
# "normalize" Cargo.toml files for maximal compatibility
|
||||
# with all versions of Cargo and also rewrite `path` dependencies
|
||||
# to registry (e.g., crates.io) dependencies.
|
||||
#
|
||||
# If you are reading this file be aware that the original Cargo.toml
|
||||
# will likely look very different (and much more reasonable).
|
||||
# See Cargo.toml.orig for the original contents.
|
||||
|
||||
[package]
|
||||
edition = "2018"
|
||||
name = "core-foundation"
|
||||
version = "0.9.4"
|
||||
authors = ["The Servo Project Developers"]
|
||||
description = "Bindings to Core Foundation for macOS"
|
||||
homepage = "https://github.com/servo/core-foundation-rs"
|
||||
keywords = [
|
||||
"macos",
|
||||
"framework",
|
||||
"objc",
|
||||
]
|
||||
categories = ["os::macos-apis"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
repository = "https://github.com/servo/core-foundation-rs"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
all-features = true
|
||||
default-target = "x86_64-apple-darwin"
|
||||
|
||||
[dependencies.chrono]
|
||||
version = "0.4"
|
||||
optional = true
|
||||
|
||||
[dependencies.core-foundation-sys]
|
||||
version = "0.8.6"
|
||||
default-features = false
|
||||
|
||||
[dependencies.libc]
|
||||
version = "0.2"
|
||||
|
||||
[dependencies.uuid]
|
||||
version = "0.5"
|
||||
optional = true
|
||||
|
||||
[features]
|
||||
default = ["link"]
|
||||
link = ["core-foundation-sys/link"]
|
||||
mac_os_10_7_support = ["core-foundation-sys/mac_os_10_7_support"]
|
||||
mac_os_10_8_features = ["core-foundation-sys/mac_os_10_8_features"]
|
||||
with-chrono = ["chrono"]
|
||||
with-uuid = ["uuid"]
|
||||
201
third-party/vendor/core-foundation/LICENSE-APACHE
vendored
Normal file
201
third-party/vendor/core-foundation/LICENSE-APACHE
vendored
Normal file
|
|
@ -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.
|
||||
25
third-party/vendor/core-foundation/LICENSE-MIT
vendored
Normal file
25
third-party/vendor/core-foundation/LICENSE-MIT
vendored
Normal file
|
|
@ -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.
|
||||
309
third-party/vendor/core-foundation/src/array.rs
vendored
Normal file
309
third-party/vendor/core-foundation/src/array.rs
vendored
Normal file
|
|
@ -0,0 +1,309 @@
|
|||
// 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.
|
||||
|
||||
//! Heterogeneous immutable arrays.
|
||||
|
||||
use crate::ConcreteCFType;
|
||||
pub use core_foundation_sys::array::*;
|
||||
pub use core_foundation_sys::base::CFIndex;
|
||||
use core_foundation_sys::base::{kCFAllocatorDefault, CFRelease, CFTypeRef};
|
||||
use std::marker::PhantomData;
|
||||
use std::mem;
|
||||
use std::os::raw::c_void;
|
||||
use std::ptr;
|
||||
|
||||
use crate::base::{CFIndexConvertible, CFRange, TCFType};
|
||||
use crate::base::{FromVoid, ItemRef};
|
||||
|
||||
/// A heterogeneous immutable array.
|
||||
pub struct CFArray<T = *const c_void>(CFArrayRef, PhantomData<T>);
|
||||
|
||||
impl<T> Drop for CFArray<T> {
|
||||
fn drop(&mut self) {
|
||||
unsafe { CFRelease(self.as_CFTypeRef()) }
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CFArrayIterator<'a, T: 'a> {
|
||||
array: &'a CFArray<T>,
|
||||
index: CFIndex,
|
||||
len: CFIndex,
|
||||
}
|
||||
|
||||
impl<'a, T: FromVoid> Iterator for CFArrayIterator<'a, T> {
|
||||
type Item = ItemRef<'a, T>;
|
||||
|
||||
fn next(&mut self) -> Option<ItemRef<'a, T>> {
|
||||
if self.index >= self.len {
|
||||
None
|
||||
} else {
|
||||
let value = unsafe { self.array.get_unchecked(self.index) };
|
||||
self.index += 1;
|
||||
Some(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: FromVoid> ExactSizeIterator for CFArrayIterator<'a, T> {
|
||||
fn len(&self) -> usize {
|
||||
(self.array.len() - self.index) as usize
|
||||
}
|
||||
}
|
||||
|
||||
impl_TCFType!(CFArray<T>, CFArrayRef, CFArrayGetTypeID);
|
||||
impl_CFTypeDescription!(CFArray<T>);
|
||||
|
||||
unsafe impl ConcreteCFType for CFArray<*const c_void> {}
|
||||
|
||||
impl<T> CFArray<T> {
|
||||
/// Creates a new `CFArray` with the given elements, which must implement `Copy`.
|
||||
pub fn from_copyable(elems: &[T]) -> CFArray<T>
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
unsafe {
|
||||
let array_ref = CFArrayCreate(
|
||||
kCFAllocatorDefault,
|
||||
elems.as_ptr() as *const *const c_void,
|
||||
elems.len().to_CFIndex(),
|
||||
ptr::null(),
|
||||
);
|
||||
TCFType::wrap_under_create_rule(array_ref)
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new `CFArray` with the given elements, which must be `CFType` objects.
|
||||
pub fn from_CFTypes(elems: &[T]) -> CFArray<T>
|
||||
where
|
||||
T: TCFType,
|
||||
{
|
||||
unsafe {
|
||||
let elems: Vec<CFTypeRef> = elems.iter().map(|elem| elem.as_CFTypeRef()).collect();
|
||||
let array_ref = CFArrayCreate(
|
||||
kCFAllocatorDefault,
|
||||
elems.as_ptr(),
|
||||
elems.len().to_CFIndex(),
|
||||
&kCFTypeArrayCallBacks,
|
||||
);
|
||||
TCFType::wrap_under_create_rule(array_ref)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_untyped(&self) -> CFArray {
|
||||
unsafe { CFArray::wrap_under_get_rule(self.0) }
|
||||
}
|
||||
|
||||
/// Returns the same array, but with the type reset to void pointers.
|
||||
/// Equal to `to_untyped`, but is faster since it does not increment the retain count.
|
||||
#[inline]
|
||||
pub fn into_untyped(self) -> CFArray {
|
||||
let reference = self.0;
|
||||
mem::forget(self);
|
||||
unsafe { CFArray::wrap_under_create_rule(reference) }
|
||||
}
|
||||
|
||||
/// Iterates over the elements of this `CFArray`.
|
||||
///
|
||||
/// Careful; the loop body must wrap the reference properly. Generally, when array elements are
|
||||
/// Core Foundation objects (not always true), they need to be wrapped with
|
||||
/// `TCFType::wrap_under_get_rule()`.
|
||||
#[inline]
|
||||
pub fn iter(&self) -> CFArrayIterator<'_, T> {
|
||||
CFArrayIterator {
|
||||
array: self,
|
||||
index: 0,
|
||||
len: self.len(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn len(&self) -> CFIndex {
|
||||
unsafe { CFArrayGetCount(self.0) }
|
||||
}
|
||||
|
||||
/// Returns `true` if the array contains no elements.
|
||||
#[inline]
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.len() == 0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn get_unchecked(&self, index: CFIndex) -> ItemRef<'_, T>
|
||||
where
|
||||
T: FromVoid,
|
||||
{
|
||||
T::from_void(CFArrayGetValueAtIndex(self.0, index))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get(&self, index: CFIndex) -> Option<ItemRef<'_, T>>
|
||||
where
|
||||
T: FromVoid,
|
||||
{
|
||||
if index < self.len() {
|
||||
Some(unsafe { T::from_void(CFArrayGetValueAtIndex(self.0, index)) })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_values(&self, range: CFRange) -> Vec<*const c_void> {
|
||||
let mut vec = Vec::with_capacity(range.length as usize);
|
||||
unsafe {
|
||||
CFArrayGetValues(self.0, range, vec.as_mut_ptr());
|
||||
vec.set_len(range.length as usize);
|
||||
vec
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_all_values(&self) -> Vec<*const c_void> {
|
||||
self.get_values(CFRange {
|
||||
location: 0,
|
||||
length: self.len(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: FromVoid> IntoIterator for &'a CFArray<T> {
|
||||
type Item = ItemRef<'a, T>;
|
||||
type IntoIter = CFArrayIterator<'a, T>;
|
||||
|
||||
fn into_iter(self) -> CFArrayIterator<'a, T> {
|
||||
self.iter()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::number::CFNumber;
|
||||
|
||||
use super::*;
|
||||
use crate::base::CFType;
|
||||
use std::mem;
|
||||
|
||||
#[test]
|
||||
fn to_untyped_correct_retain_count() {
|
||||
let array = CFArray::<CFType>::from_CFTypes(&[CFNumber::from(4).as_CFType()]);
|
||||
assert_eq!(array.retain_count(), 1);
|
||||
|
||||
let untyped_array = array.to_untyped();
|
||||
assert_eq!(array.retain_count(), 2);
|
||||
assert_eq!(untyped_array.retain_count(), 2);
|
||||
|
||||
mem::drop(array);
|
||||
assert_eq!(untyped_array.retain_count(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn into_untyped() {
|
||||
let array = CFArray::<CFType>::from_CFTypes(&[CFNumber::from(4).as_CFType()]);
|
||||
let array2 = array.to_untyped();
|
||||
assert_eq!(array.retain_count(), 2);
|
||||
|
||||
let untyped_array = array.into_untyped();
|
||||
assert_eq!(untyped_array.retain_count(), 2);
|
||||
|
||||
mem::drop(array2);
|
||||
assert_eq!(untyped_array.retain_count(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn borrow() {
|
||||
use crate::string::CFString;
|
||||
|
||||
let string = CFString::from_static_string("alongerstring");
|
||||
assert_eq!(string.retain_count(), 1);
|
||||
let x;
|
||||
{
|
||||
let arr: CFArray<CFString> = CFArray::from_CFTypes(&[string]);
|
||||
{
|
||||
let p = arr.get(0).unwrap();
|
||||
assert_eq!(p.retain_count(), 1);
|
||||
}
|
||||
{
|
||||
x = arr.get(0).unwrap().clone();
|
||||
assert_eq!(x.retain_count(), 2);
|
||||
assert_eq!(x.to_string(), "alongerstring");
|
||||
}
|
||||
}
|
||||
assert_eq!(x.retain_count(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn iter_untyped_array() {
|
||||
use crate::base::TCFTypeRef;
|
||||
use crate::string::{CFString, CFStringRef};
|
||||
|
||||
let cf_string = CFString::from_static_string("alongerstring");
|
||||
let array: CFArray = CFArray::from_CFTypes(&[cf_string.clone()]).into_untyped();
|
||||
|
||||
let cf_strings = array
|
||||
.iter()
|
||||
.map(|ptr| unsafe { CFString::wrap_under_get_rule(CFStringRef::from_void_ptr(*ptr)) })
|
||||
.collect::<Vec<_>>();
|
||||
let strings = cf_strings.iter().map(|s| s.to_string()).collect::<Vec<_>>();
|
||||
assert_eq!(cf_string.retain_count(), 3);
|
||||
assert_eq!(&strings[..], &["alongerstring"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_box_and_unbox() {
|
||||
use crate::number::CFNumber;
|
||||
|
||||
let n0 = CFNumber::from(0);
|
||||
let n1 = CFNumber::from(1);
|
||||
let n2 = CFNumber::from(2);
|
||||
let n3 = CFNumber::from(3);
|
||||
let n4 = CFNumber::from(4);
|
||||
let n5 = CFNumber::from(5);
|
||||
|
||||
let arr = CFArray::from_CFTypes(&[
|
||||
n0.as_CFType(),
|
||||
n1.as_CFType(),
|
||||
n2.as_CFType(),
|
||||
n3.as_CFType(),
|
||||
n4.as_CFType(),
|
||||
n5.as_CFType(),
|
||||
]);
|
||||
|
||||
assert_eq!(
|
||||
arr.get_all_values(),
|
||||
&[
|
||||
n0.as_CFTypeRef(),
|
||||
n1.as_CFTypeRef(),
|
||||
n2.as_CFTypeRef(),
|
||||
n3.as_CFTypeRef(),
|
||||
n4.as_CFTypeRef(),
|
||||
n5.as_CFTypeRef()
|
||||
]
|
||||
);
|
||||
|
||||
let mut sum = 0;
|
||||
|
||||
let mut iter = arr.iter();
|
||||
assert_eq!(iter.len(), 6);
|
||||
assert!(iter.next().is_some());
|
||||
assert_eq!(iter.len(), 5);
|
||||
|
||||
for elem in iter {
|
||||
let number: CFNumber = elem.downcast::<CFNumber>().unwrap();
|
||||
sum += number.to_i64().unwrap()
|
||||
}
|
||||
|
||||
assert_eq!(sum, 15);
|
||||
|
||||
for elem in arr.iter() {
|
||||
let number: CFNumber = elem.downcast::<CFNumber>().unwrap();
|
||||
sum += number.to_i64().unwrap()
|
||||
}
|
||||
|
||||
assert_eq!(sum, 30);
|
||||
}
|
||||
}
|
||||
101
third-party/vendor/core-foundation/src/attributed_string.rs
vendored
Normal file
101
third-party/vendor/core-foundation/src/attributed_string.rs
vendored
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
// 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.
|
||||
|
||||
pub use core_foundation_sys::attributed_string::*;
|
||||
|
||||
use crate::base::TCFType;
|
||||
use crate::string::{CFString, CFStringRef};
|
||||
use core_foundation_sys::base::{kCFAllocatorDefault, CFIndex, CFRange};
|
||||
use std::ptr::null;
|
||||
|
||||
declare_TCFType! {
|
||||
CFAttributedString, CFAttributedStringRef
|
||||
}
|
||||
impl_TCFType!(
|
||||
CFAttributedString,
|
||||
CFAttributedStringRef,
|
||||
CFAttributedStringGetTypeID
|
||||
);
|
||||
|
||||
impl CFAttributedString {
|
||||
#[inline]
|
||||
pub fn new(string: &CFString) -> Self {
|
||||
unsafe {
|
||||
let astr_ref =
|
||||
CFAttributedStringCreate(kCFAllocatorDefault, string.as_concrete_TypeRef(), null());
|
||||
|
||||
CFAttributedString::wrap_under_create_rule(astr_ref)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn char_len(&self) -> CFIndex {
|
||||
unsafe { CFAttributedStringGetLength(self.0) }
|
||||
}
|
||||
}
|
||||
|
||||
declare_TCFType! {
|
||||
CFMutableAttributedString, CFMutableAttributedStringRef
|
||||
}
|
||||
impl_TCFType!(
|
||||
CFMutableAttributedString,
|
||||
CFMutableAttributedStringRef,
|
||||
CFAttributedStringGetTypeID
|
||||
);
|
||||
|
||||
impl CFMutableAttributedString {
|
||||
#[inline]
|
||||
pub fn new() -> Self {
|
||||
unsafe {
|
||||
let astr_ref = CFAttributedStringCreateMutable(kCFAllocatorDefault, 0);
|
||||
|
||||
CFMutableAttributedString::wrap_under_create_rule(astr_ref)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn char_len(&self) -> CFIndex {
|
||||
unsafe { CFAttributedStringGetLength(self.0) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn replace_str(&mut self, string: &CFString, range: CFRange) {
|
||||
unsafe {
|
||||
CFAttributedStringReplaceString(self.0, range, string.as_concrete_TypeRef());
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_attribute<T: TCFType>(&mut self, range: CFRange, name: CFStringRef, value: &T) {
|
||||
unsafe {
|
||||
CFAttributedStringSetAttribute(self.0, range, name, value.as_CFTypeRef());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for CFMutableAttributedString {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn attributed_string_type_id_comparison() {
|
||||
// CFMutableAttributedString TypeID must be equal to CFAttributedString TypeID.
|
||||
// Compilation must not fail.
|
||||
assert_eq!(
|
||||
<CFAttributedString as TCFType>::type_id(),
|
||||
<CFMutableAttributedString as TCFType>::type_id()
|
||||
);
|
||||
}
|
||||
}
|
||||
446
third-party/vendor/core-foundation/src/base.rs
vendored
Normal file
446
third-party/vendor/core-foundation/src/base.rs
vendored
Normal file
|
|
@ -0,0 +1,446 @@
|
|||
// 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 std;
|
||||
use std::fmt;
|
||||
use std::marker::PhantomData;
|
||||
use std::mem;
|
||||
use std::mem::ManuallyDrop;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::os::raw::c_void;
|
||||
|
||||
pub use core_foundation_sys::base::*;
|
||||
|
||||
use crate::string::CFString;
|
||||
use crate::ConcreteCFType;
|
||||
|
||||
pub trait CFIndexConvertible {
|
||||
/// Always use this method to construct a `CFIndex` value. It performs bounds checking to
|
||||
/// ensure the value is in range.
|
||||
fn to_CFIndex(self) -> CFIndex;
|
||||
}
|
||||
|
||||
impl CFIndexConvertible for usize {
|
||||
#[inline]
|
||||
fn to_CFIndex(self) -> CFIndex {
|
||||
let max_CFIndex = CFIndex::max_value();
|
||||
if self > (max_CFIndex as usize) {
|
||||
panic!("value out of range")
|
||||
}
|
||||
self as CFIndex
|
||||
}
|
||||
}
|
||||
|
||||
declare_TCFType! {
|
||||
/// Superclass of all Core Foundation objects.
|
||||
CFType, CFTypeRef
|
||||
}
|
||||
|
||||
impl CFType {
|
||||
/// Try to downcast the `CFType` to a subclass. Checking if the instance is the
|
||||
/// correct subclass happens at runtime and `None` is returned if it is not the correct type.
|
||||
/// Works similar to [`Box::downcast`] and [`CFPropertyList::downcast`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # use core_foundation::string::CFString;
|
||||
/// # use core_foundation::boolean::CFBoolean;
|
||||
/// # use core_foundation::base::{CFType, TCFType};
|
||||
/// #
|
||||
/// // Create a string.
|
||||
/// let string: CFString = CFString::from_static_string("FooBar");
|
||||
/// // Cast it up to a CFType.
|
||||
/// let cf_type: CFType = string.as_CFType();
|
||||
/// // Cast it down again.
|
||||
/// assert_eq!(cf_type.downcast::<CFString>().unwrap().to_string(), "FooBar");
|
||||
/// // Casting it to some other type will yield `None`
|
||||
/// assert!(cf_type.downcast::<CFBoolean>().is_none());
|
||||
/// ```
|
||||
///
|
||||
/// ```compile_fail
|
||||
/// # use core_foundation::array::CFArray;
|
||||
/// # use core_foundation::base::TCFType;
|
||||
/// # use core_foundation::boolean::CFBoolean;
|
||||
/// # use core_foundation::string::CFString;
|
||||
/// #
|
||||
/// let boolean_array = CFArray::from_CFTypes(&[CFBoolean::true_value()]).into_CFType();
|
||||
///
|
||||
/// // This downcast is not allowed and causes compiler error, since it would cause undefined
|
||||
/// // behavior to access the elements of the array as a CFString:
|
||||
/// let invalid_string_array = boolean_array
|
||||
/// .downcast_into::<CFArray<CFString>>()
|
||||
/// .unwrap();
|
||||
/// ```
|
||||
///
|
||||
/// [`Box::downcast`]: https://doc.rust-lang.org/std/boxed/struct.Box.html#method.downcast
|
||||
/// [`CFPropertyList::downcast`]: ../propertylist/struct.CFPropertyList.html#method.downcast
|
||||
#[inline]
|
||||
pub fn downcast<T: ConcreteCFType>(&self) -> Option<T> {
|
||||
if self.instance_of::<T>() {
|
||||
unsafe {
|
||||
let reference = T::Ref::from_void_ptr(self.0);
|
||||
Some(T::wrap_under_get_rule(reference))
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Similar to [`downcast`], but consumes self and can thus avoid touching the retain count.
|
||||
///
|
||||
/// [`downcast`]: #method.downcast
|
||||
#[inline]
|
||||
pub fn downcast_into<T: ConcreteCFType>(self) -> Option<T> {
|
||||
if self.instance_of::<T>() {
|
||||
unsafe {
|
||||
let reference = T::Ref::from_void_ptr(self.0);
|
||||
mem::forget(self);
|
||||
Some(T::wrap_under_create_rule(reference))
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for CFType {
|
||||
/// Formats the value using [`CFCopyDescription`].
|
||||
///
|
||||
/// [`CFCopyDescription`]: https://developer.apple.com/documentation/corefoundation/1521252-cfcopydescription?language=objc
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let desc = unsafe { CFString::wrap_under_create_rule(CFCopyDescription(self.0)) };
|
||||
desc.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for CFType {
|
||||
#[inline]
|
||||
fn clone(&self) -> CFType {
|
||||
unsafe { TCFType::wrap_under_get_rule(self.0) }
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for CFType {
|
||||
#[inline]
|
||||
fn eq(&self, other: &CFType) -> bool {
|
||||
unsafe { CFEqual(self.as_CFTypeRef(), other.as_CFTypeRef()) != 0 }
|
||||
}
|
||||
}
|
||||
|
||||
declare_TCFType!(CFAllocator, CFAllocatorRef);
|
||||
impl_TCFType!(CFAllocator, CFAllocatorRef, CFAllocatorGetTypeID);
|
||||
|
||||
impl CFAllocator {
|
||||
#[inline]
|
||||
pub fn new(mut context: CFAllocatorContext) -> CFAllocator {
|
||||
unsafe {
|
||||
let allocator_ref = CFAllocatorCreate(kCFAllocatorDefault, &mut context);
|
||||
TCFType::wrap_under_create_rule(allocator_ref)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// All Core Foundation types implement this trait. The associated type `Ref` specifies the
|
||||
/// associated Core Foundation type: e.g. for `CFType` this is `CFTypeRef`; for `CFArray` this is
|
||||
/// `CFArrayRef`.
|
||||
///
|
||||
/// Most structs that implement this trait will do so via the [`impl_TCFType`] macro.
|
||||
///
|
||||
/// [`impl_TCFType`]: ../macro.impl_TCFType.html
|
||||
pub trait TCFType {
|
||||
/// The reference type wrapped inside this type.
|
||||
type Ref: TCFTypeRef;
|
||||
|
||||
/// Returns the object as its concrete `TypeRef`.
|
||||
fn as_concrete_TypeRef(&self) -> Self::Ref;
|
||||
|
||||
/// Returns an instance of the object, wrapping the underlying `CFTypeRef` subclass. Use this
|
||||
/// when following Core Foundation's "Create Rule". The reference count is *not* bumped.
|
||||
unsafe fn wrap_under_create_rule(obj: Self::Ref) -> Self;
|
||||
|
||||
/// Returns the type ID for this class.
|
||||
fn type_id() -> CFTypeID;
|
||||
|
||||
/// Returns the object as a wrapped `CFType`. The reference count is incremented by one.
|
||||
#[inline]
|
||||
fn as_CFType(&self) -> CFType {
|
||||
unsafe { TCFType::wrap_under_get_rule(self.as_CFTypeRef()) }
|
||||
}
|
||||
|
||||
/// Returns the object as a wrapped `CFType`. Consumes self and avoids changing the reference
|
||||
/// count.
|
||||
#[inline]
|
||||
fn into_CFType(self) -> CFType
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
let reference = self.as_CFTypeRef();
|
||||
mem::forget(self);
|
||||
unsafe { TCFType::wrap_under_create_rule(reference) }
|
||||
}
|
||||
|
||||
/// Returns the object as a raw `CFTypeRef`. The reference count is not adjusted.
|
||||
fn as_CFTypeRef(&self) -> CFTypeRef;
|
||||
|
||||
/// Returns an instance of the object, wrapping the underlying `CFTypeRef` subclass. Use this
|
||||
/// when following Core Foundation's "Get Rule". The reference count *is* bumped.
|
||||
unsafe fn wrap_under_get_rule(reference: Self::Ref) -> Self;
|
||||
|
||||
/// Returns the reference count of the object. It is unwise to do anything other than test
|
||||
/// whether the return value of this method is greater than zero.
|
||||
#[inline]
|
||||
fn retain_count(&self) -> CFIndex {
|
||||
unsafe { CFGetRetainCount(self.as_CFTypeRef()) }
|
||||
}
|
||||
|
||||
/// Returns the type ID of this object.
|
||||
#[inline]
|
||||
fn type_of(&self) -> CFTypeID {
|
||||
unsafe { CFGetTypeID(self.as_CFTypeRef()) }
|
||||
}
|
||||
|
||||
/// Writes a debugging version of this object on standard error.
|
||||
fn show(&self) {
|
||||
unsafe { CFShow(self.as_CFTypeRef()) }
|
||||
}
|
||||
|
||||
/// Returns `true` if this value is an instance of another type.
|
||||
#[inline]
|
||||
fn instance_of<OtherCFType: TCFType>(&self) -> bool {
|
||||
self.type_of() == OtherCFType::type_id()
|
||||
}
|
||||
}
|
||||
|
||||
impl TCFType for CFType {
|
||||
type Ref = CFTypeRef;
|
||||
|
||||
#[inline]
|
||||
fn as_concrete_TypeRef(&self) -> CFTypeRef {
|
||||
self.0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn wrap_under_get_rule(reference: CFTypeRef) -> CFType {
|
||||
assert!(!reference.is_null(), "Attempted to create a NULL object.");
|
||||
let reference: CFTypeRef = CFRetain(reference);
|
||||
TCFType::wrap_under_create_rule(reference)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_CFTypeRef(&self) -> CFTypeRef {
|
||||
self.as_concrete_TypeRef()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn wrap_under_create_rule(obj: CFTypeRef) -> CFType {
|
||||
assert!(!obj.is_null(), "Attempted to create a NULL object.");
|
||||
CFType(obj)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn type_id() -> CFTypeID {
|
||||
// FIXME(pcwalton): Is this right?
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
/// A reference to an element inside a container
|
||||
pub struct ItemRef<'a, T: 'a>(ManuallyDrop<T>, PhantomData<&'a T>);
|
||||
|
||||
impl<'a, T> Deref for ItemRef<'a, T> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &T {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: fmt::Debug> fmt::Debug for ItemRef<'a, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
self.0.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: PartialEq> PartialEq for ItemRef<'a, T> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.0.eq(&other.0)
|
||||
}
|
||||
}
|
||||
|
||||
/// A reference to a mutable element inside a container
|
||||
pub struct ItemMutRef<'a, T: 'a>(ManuallyDrop<T>, PhantomData<&'a T>);
|
||||
|
||||
impl<'a, T> Deref for ItemMutRef<'a, T> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &T {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> DerefMut for ItemMutRef<'a, T> {
|
||||
fn deref_mut(&mut self) -> &mut T {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: fmt::Debug> fmt::Debug for ItemMutRef<'a, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
self.0.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: PartialEq> PartialEq for ItemMutRef<'a, T> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.0.eq(&other.0)
|
||||
}
|
||||
}
|
||||
|
||||
/// A trait describing how to convert from the stored `*mut c_void` to the desired `T`
|
||||
pub unsafe trait FromMutVoid {
|
||||
unsafe fn from_mut_void<'a>(x: *mut c_void) -> ItemMutRef<'a, Self>
|
||||
where
|
||||
Self: std::marker::Sized;
|
||||
}
|
||||
|
||||
unsafe impl FromMutVoid for u32 {
|
||||
unsafe fn from_mut_void<'a>(x: *mut c_void) -> ItemMutRef<'a, Self> {
|
||||
ItemMutRef(ManuallyDrop::new(x as u32), PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl FromMutVoid for *const c_void {
|
||||
unsafe fn from_mut_void<'a>(x: *mut c_void) -> ItemMutRef<'a, Self> {
|
||||
ItemMutRef(ManuallyDrop::new(x), PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<T: TCFType> FromMutVoid for T {
|
||||
unsafe fn from_mut_void<'a>(x: *mut c_void) -> ItemMutRef<'a, Self> {
|
||||
ItemMutRef(
|
||||
ManuallyDrop::new(TCFType::wrap_under_create_rule(T::Ref::from_void_ptr(x))),
|
||||
PhantomData,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// A trait describing how to convert from the stored `*const c_void` to the desired `T`
|
||||
pub unsafe trait FromVoid {
|
||||
unsafe fn from_void<'a>(x: *const c_void) -> ItemRef<'a, Self>
|
||||
where
|
||||
Self: std::marker::Sized;
|
||||
}
|
||||
|
||||
unsafe impl FromVoid for u32 {
|
||||
unsafe fn from_void<'a>(x: *const c_void) -> ItemRef<'a, Self> {
|
||||
// Functions like CGFontCopyTableTags treat the void*'s as u32's
|
||||
// so we convert by casting directly
|
||||
ItemRef(ManuallyDrop::new(x as u32), PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl FromVoid for *const c_void {
|
||||
unsafe fn from_void<'a>(x: *const c_void) -> ItemRef<'a, Self> {
|
||||
ItemRef(ManuallyDrop::new(x), PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<T: TCFType> FromVoid for T {
|
||||
unsafe fn from_void<'a>(x: *const c_void) -> ItemRef<'a, Self> {
|
||||
ItemRef(
|
||||
ManuallyDrop::new(TCFType::wrap_under_create_rule(T::Ref::from_void_ptr(x))),
|
||||
PhantomData,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// A trait describing how to convert from the stored `*const c_void` to the desired `T`
|
||||
pub unsafe trait ToVoid<T> {
|
||||
fn to_void(&self) -> *const c_void;
|
||||
}
|
||||
|
||||
unsafe impl ToVoid<*const c_void> for *const c_void {
|
||||
fn to_void(&self) -> *const c_void {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<'a> ToVoid<CFType> for &'a CFType {
|
||||
fn to_void(&self) -> *const ::std::os::raw::c_void {
|
||||
self.as_concrete_TypeRef().as_void_ptr()
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl ToVoid<CFType> for CFType {
|
||||
fn to_void(&self) -> *const ::std::os::raw::c_void {
|
||||
self.as_concrete_TypeRef().as_void_ptr()
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl ToVoid<CFType> for CFTypeRef {
|
||||
fn to_void(&self) -> *const ::std::os::raw::c_void {
|
||||
self.as_void_ptr()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::boolean::CFBoolean;
|
||||
use std::mem;
|
||||
|
||||
#[test]
|
||||
fn cftype_instance_of() {
|
||||
let string = CFString::from_static_string("foo");
|
||||
let cftype = string.as_CFType();
|
||||
|
||||
assert!(cftype.instance_of::<CFString>());
|
||||
assert!(!cftype.instance_of::<CFBoolean>());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn as_cftype_retain_count() {
|
||||
let string = CFString::from_static_string("alongerstring");
|
||||
assert_eq!(string.retain_count(), 1);
|
||||
let cftype = string.as_CFType();
|
||||
assert_eq!(cftype.retain_count(), 2);
|
||||
mem::drop(string);
|
||||
assert_eq!(cftype.retain_count(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn into_cftype_retain_count() {
|
||||
let string = CFString::from_static_string("alongerstring");
|
||||
assert_eq!(string.retain_count(), 1);
|
||||
let cftype = string.into_CFType();
|
||||
assert_eq!(cftype.retain_count(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn as_cftype_and_downcast() {
|
||||
let string = CFString::from_static_string("alongerstring");
|
||||
let cftype = string.as_CFType();
|
||||
let string2 = cftype.downcast::<CFString>().unwrap();
|
||||
assert_eq!(string2.to_string(), "alongerstring");
|
||||
|
||||
assert_eq!(string.retain_count(), 3);
|
||||
assert_eq!(cftype.retain_count(), 3);
|
||||
assert_eq!(string2.retain_count(), 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn into_cftype_and_downcast_into() {
|
||||
let string = CFString::from_static_string("alongerstring");
|
||||
let cftype = string.into_CFType();
|
||||
let string2 = cftype.downcast_into::<CFString>().unwrap();
|
||||
assert_eq!(string2.to_string(), "alongerstring");
|
||||
assert_eq!(string2.retain_count(), 1);
|
||||
}
|
||||
}
|
||||
67
third-party/vendor/core-foundation/src/boolean.rs
vendored
Normal file
67
third-party/vendor/core-foundation/src/boolean.rs
vendored
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
// 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.
|
||||
|
||||
//! A Boolean type.
|
||||
|
||||
pub use core_foundation_sys::number::{
|
||||
kCFBooleanFalse, kCFBooleanTrue, CFBooleanGetTypeID, CFBooleanRef,
|
||||
};
|
||||
|
||||
use crate::base::TCFType;
|
||||
|
||||
declare_TCFType! {
|
||||
/// A Boolean type.
|
||||
///
|
||||
/// FIXME(pcwalton): Should be a newtype struct, but that fails due to a Rust compiler bug.
|
||||
CFBoolean, CFBooleanRef
|
||||
}
|
||||
impl_TCFType!(CFBoolean, CFBooleanRef, CFBooleanGetTypeID);
|
||||
impl_CFTypeDescription!(CFBoolean);
|
||||
|
||||
impl CFBoolean {
|
||||
pub fn true_value() -> CFBoolean {
|
||||
unsafe { TCFType::wrap_under_get_rule(kCFBooleanTrue) }
|
||||
}
|
||||
|
||||
pub fn false_value() -> CFBoolean {
|
||||
unsafe { TCFType::wrap_under_get_rule(kCFBooleanFalse) }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<bool> for CFBoolean {
|
||||
fn from(value: bool) -> CFBoolean {
|
||||
if value {
|
||||
CFBoolean::true_value()
|
||||
} else {
|
||||
CFBoolean::false_value()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CFBoolean> for bool {
|
||||
fn from(value: CFBoolean) -> bool {
|
||||
value.0 == unsafe { kCFBooleanTrue }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn to_and_from_bool() {
|
||||
let b_false = CFBoolean::from(false);
|
||||
let b_true = CFBoolean::from(true);
|
||||
assert_ne!(b_false, b_true);
|
||||
assert_eq!(b_false, CFBoolean::false_value());
|
||||
assert_eq!(b_true, CFBoolean::true_value());
|
||||
assert!(!bool::from(b_false));
|
||||
assert!(bool::from(b_true));
|
||||
}
|
||||
}
|
||||
199
third-party/vendor/core-foundation/src/bundle.rs
vendored
Normal file
199
third-party/vendor/core-foundation/src/bundle.rs
vendored
Normal file
|
|
@ -0,0 +1,199 @@
|
|||
// 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.
|
||||
|
||||
//! Core Foundation Bundle Type
|
||||
|
||||
use core_foundation_sys::base::kCFAllocatorDefault;
|
||||
pub use core_foundation_sys::bundle::*;
|
||||
use core_foundation_sys::url::kCFURLPOSIXPathStyle;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use crate::base::{CFType, TCFType};
|
||||
use crate::dictionary::CFDictionary;
|
||||
use crate::string::CFString;
|
||||
use crate::url::CFURL;
|
||||
use std::os::raw::c_void;
|
||||
|
||||
declare_TCFType! {
|
||||
/// A Bundle type.
|
||||
CFBundle, CFBundleRef
|
||||
}
|
||||
impl_TCFType!(CFBundle, CFBundleRef, CFBundleGetTypeID);
|
||||
|
||||
impl CFBundle {
|
||||
pub fn new(bundleURL: CFURL) -> Option<CFBundle> {
|
||||
unsafe {
|
||||
let bundle_ref = CFBundleCreate(kCFAllocatorDefault, bundleURL.as_concrete_TypeRef());
|
||||
if bundle_ref.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(TCFType::wrap_under_create_rule(bundle_ref))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bundle_with_identifier(identifier: CFString) -> Option<CFBundle> {
|
||||
unsafe {
|
||||
let bundle_ref = CFBundleGetBundleWithIdentifier(identifier.as_concrete_TypeRef());
|
||||
if bundle_ref.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(TCFType::wrap_under_get_rule(bundle_ref))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn function_pointer_for_name(&self, function_name: CFString) -> *const c_void {
|
||||
unsafe {
|
||||
CFBundleGetFunctionPointerForName(
|
||||
self.as_concrete_TypeRef(),
|
||||
function_name.as_concrete_TypeRef(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn main_bundle() -> CFBundle {
|
||||
unsafe {
|
||||
let bundle_ref = CFBundleGetMainBundle();
|
||||
TCFType::wrap_under_get_rule(bundle_ref)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn info_dictionary(&self) -> CFDictionary<CFString, CFType> {
|
||||
unsafe {
|
||||
let info_dictionary = CFBundleGetInfoDictionary(self.0);
|
||||
TCFType::wrap_under_get_rule(info_dictionary)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn executable_url(&self) -> Option<CFURL> {
|
||||
unsafe {
|
||||
let exe_url = CFBundleCopyExecutableURL(self.0);
|
||||
if exe_url.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(TCFType::wrap_under_create_rule(exe_url))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Bundle's own location
|
||||
pub fn bundle_url(&self) -> Option<CFURL> {
|
||||
unsafe {
|
||||
let bundle_url = CFBundleCopyBundleURL(self.0);
|
||||
if bundle_url.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(TCFType::wrap_under_create_rule(bundle_url))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Bundle's own location
|
||||
pub fn path(&self) -> Option<PathBuf> {
|
||||
let url = self.bundle_url()?;
|
||||
Some(PathBuf::from(
|
||||
url.get_file_system_path(kCFURLPOSIXPathStyle).to_string(),
|
||||
))
|
||||
}
|
||||
|
||||
/// Bundle's resources location
|
||||
pub fn bundle_resources_url(&self) -> Option<CFURL> {
|
||||
unsafe {
|
||||
let bundle_url = CFBundleCopyResourcesDirectoryURL(self.0);
|
||||
if bundle_url.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(TCFType::wrap_under_create_rule(bundle_url))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Bundle's resources location
|
||||
pub fn resources_path(&self) -> Option<PathBuf> {
|
||||
let url = self.bundle_resources_url()?;
|
||||
Some(PathBuf::from(
|
||||
url.get_file_system_path(kCFURLPOSIXPathStyle).to_string(),
|
||||
))
|
||||
}
|
||||
|
||||
pub fn private_frameworks_url(&self) -> Option<CFURL> {
|
||||
unsafe {
|
||||
let fw_url = CFBundleCopyPrivateFrameworksURL(self.0);
|
||||
if fw_url.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(TCFType::wrap_under_create_rule(fw_url))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn shared_support_url(&self) -> Option<CFURL> {
|
||||
unsafe {
|
||||
let fw_url = CFBundleCopySharedSupportURL(self.0);
|
||||
if fw_url.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(TCFType::wrap_under_create_rule(fw_url))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn safari_executable_url() {
|
||||
use crate::string::CFString;
|
||||
use crate::url::{kCFURLPOSIXPathStyle, CFURL};
|
||||
|
||||
let cfstr_path = CFString::from_static_string("/Applications/Safari.app");
|
||||
let cfurl_path = CFURL::from_file_system_path(cfstr_path, kCFURLPOSIXPathStyle, true);
|
||||
let cfurl_executable = CFBundle::new(cfurl_path)
|
||||
.expect("Safari not present")
|
||||
.executable_url();
|
||||
assert!(cfurl_executable.is_some());
|
||||
assert_eq!(
|
||||
cfurl_executable
|
||||
.unwrap()
|
||||
.absolute()
|
||||
.get_file_system_path(kCFURLPOSIXPathStyle)
|
||||
.to_string(),
|
||||
"/Applications/Safari.app/Contents/MacOS/Safari"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn safari_private_frameworks_url() {
|
||||
use crate::string::CFString;
|
||||
use crate::url::{kCFURLPOSIXPathStyle, CFURL};
|
||||
|
||||
let cfstr_path = CFString::from_static_string("/Applications/Safari.app");
|
||||
let cfurl_path = CFURL::from_file_system_path(cfstr_path, kCFURLPOSIXPathStyle, true);
|
||||
let cfurl_executable = CFBundle::new(cfurl_path)
|
||||
.expect("Safari not present")
|
||||
.private_frameworks_url();
|
||||
assert!(cfurl_executable.is_some());
|
||||
assert_eq!(
|
||||
cfurl_executable
|
||||
.unwrap()
|
||||
.absolute()
|
||||
.get_file_system_path(kCFURLPOSIXPathStyle)
|
||||
.to_string(),
|
||||
"/Applications/Safari.app/Contents/Frameworks"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn non_existant_bundle() {
|
||||
use crate::string::CFString;
|
||||
use crate::url::{kCFURLPOSIXPathStyle, CFURL};
|
||||
|
||||
let cfstr_path = CFString::from_static_string("/usr/local/foo");
|
||||
let cfurl_path = CFURL::from_file_system_path(cfstr_path, kCFURLPOSIXPathStyle, true);
|
||||
assert!(CFBundle::new(cfurl_path).is_none());
|
||||
}
|
||||
21
third-party/vendor/core-foundation/src/characterset.rs
vendored
Normal file
21
third-party/vendor/core-foundation/src/characterset.rs
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
// Copyright 2019 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.
|
||||
|
||||
//! A set of Unicode compliant characters.
|
||||
|
||||
pub use core_foundation_sys::characterset::*;
|
||||
|
||||
use crate::base::TCFType;
|
||||
|
||||
declare_TCFType! {
|
||||
/// An immutable set of Unicde characters.
|
||||
CFCharacterSet, CFCharacterSetRef
|
||||
}
|
||||
impl_TCFType!(CFCharacterSet, CFCharacterSetRef, CFCharacterSetGetTypeID);
|
||||
impl_CFTypeDescription!(CFCharacterSet);
|
||||
153
third-party/vendor/core-foundation/src/data.rs
vendored
Normal file
153
third-party/vendor/core-foundation/src/data.rs
vendored
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
// 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.
|
||||
|
||||
//! Core Foundation byte buffers.
|
||||
|
||||
use core_foundation_sys::base::kCFAllocatorDefault;
|
||||
use core_foundation_sys::base::CFIndex;
|
||||
pub use core_foundation_sys::data::*;
|
||||
use std::ops::Deref;
|
||||
use std::slice;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::base::{CFIndexConvertible, TCFType};
|
||||
|
||||
declare_TCFType! {
|
||||
/// A byte buffer.
|
||||
CFData, CFDataRef
|
||||
}
|
||||
impl_TCFType!(CFData, CFDataRef, CFDataGetTypeID);
|
||||
impl_CFTypeDescription!(CFData);
|
||||
|
||||
impl CFData {
|
||||
/// Creates a [`CFData`] around a copy `buffer`
|
||||
pub fn from_buffer(buffer: &[u8]) -> CFData {
|
||||
unsafe {
|
||||
let data_ref = CFDataCreate(
|
||||
kCFAllocatorDefault,
|
||||
buffer.as_ptr(),
|
||||
buffer.len().to_CFIndex(),
|
||||
);
|
||||
TCFType::wrap_under_create_rule(data_ref)
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a [`CFData`] referencing `buffer` without creating a copy
|
||||
pub fn from_arc<T: AsRef<[u8]> + Sync + Send>(buffer: Arc<T>) -> Self {
|
||||
use crate::base::{CFAllocator, CFAllocatorContext};
|
||||
use std::os::raw::c_void;
|
||||
|
||||
unsafe {
|
||||
let ptr = (*buffer).as_ref().as_ptr() as *const _;
|
||||
let len = (*buffer).as_ref().len().to_CFIndex();
|
||||
let info = Arc::into_raw(buffer) as *mut c_void;
|
||||
|
||||
extern "C" fn deallocate<T>(_: *mut c_void, info: *mut c_void) {
|
||||
unsafe {
|
||||
drop(Arc::from_raw(info as *mut T));
|
||||
}
|
||||
}
|
||||
|
||||
// Use a separate allocator for each allocation because
|
||||
// we need `info` to do the deallocation vs. `ptr`
|
||||
let allocator = CFAllocator::new(CFAllocatorContext {
|
||||
info,
|
||||
version: 0,
|
||||
retain: None,
|
||||
reallocate: None,
|
||||
release: None,
|
||||
copyDescription: None,
|
||||
allocate: None,
|
||||
deallocate: Some(deallocate::<T>),
|
||||
preferredSize: None,
|
||||
});
|
||||
let data_ref = CFDataCreateWithBytesNoCopy(
|
||||
kCFAllocatorDefault,
|
||||
ptr,
|
||||
len,
|
||||
allocator.as_CFTypeRef(),
|
||||
);
|
||||
TCFType::wrap_under_create_rule(data_ref)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a pointer to the underlying bytes in this data. Note that this byte buffer is
|
||||
/// read-only.
|
||||
#[inline]
|
||||
pub fn bytes(&self) -> &[u8] {
|
||||
unsafe { slice::from_raw_parts(CFDataGetBytePtr(self.0), self.len() as usize) }
|
||||
}
|
||||
|
||||
/// Returns the length of this byte buffer.
|
||||
#[inline]
|
||||
pub fn len(&self) -> CFIndex {
|
||||
unsafe { CFDataGetLength(self.0) }
|
||||
}
|
||||
|
||||
/// Returns `true` if this byte buffer is empty.
|
||||
#[inline]
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.len() == 0
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for CFData {
|
||||
type Target = [u8];
|
||||
|
||||
#[inline]
|
||||
fn deref(&self) -> &[u8] {
|
||||
self.bytes()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::CFData;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[test]
|
||||
fn test_data_provider() {
|
||||
let l = vec![5];
|
||||
CFData::from_arc(Arc::new(l));
|
||||
|
||||
let l = vec![5];
|
||||
CFData::from_arc(Arc::new(l.into_boxed_slice()));
|
||||
|
||||
// Make sure the buffer is actually dropped
|
||||
use std::sync::atomic::{AtomicBool, Ordering::SeqCst};
|
||||
struct VecWrapper {
|
||||
inner: Vec<u8>,
|
||||
dropped: Arc<AtomicBool>,
|
||||
}
|
||||
|
||||
impl Drop for VecWrapper {
|
||||
fn drop(&mut self) {
|
||||
self.dropped.store(true, SeqCst)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::AsRef<[u8]> for VecWrapper {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
let dropped = Arc::new(AtomicBool::default());
|
||||
let l = Arc::new(VecWrapper {
|
||||
inner: vec![5],
|
||||
dropped: dropped.clone(),
|
||||
});
|
||||
let m = l.clone();
|
||||
let dp = CFData::from_arc(l);
|
||||
drop(m);
|
||||
assert!(!dropped.load(SeqCst));
|
||||
drop(dp);
|
||||
assert!(dropped.load(SeqCst))
|
||||
}
|
||||
}
|
||||
121
third-party/vendor/core-foundation/src/date.rs
vendored
Normal file
121
third-party/vendor/core-foundation/src/date.rs
vendored
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
// 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.
|
||||
|
||||
//! Core Foundation date objects.
|
||||
|
||||
use core_foundation_sys::base::kCFAllocatorDefault;
|
||||
pub use core_foundation_sys::date::*;
|
||||
|
||||
use crate::base::TCFType;
|
||||
|
||||
#[cfg(feature = "with-chrono")]
|
||||
use chrono::NaiveDateTime;
|
||||
|
||||
declare_TCFType! {
|
||||
/// A date.
|
||||
CFDate, CFDateRef
|
||||
}
|
||||
impl_TCFType!(CFDate, CFDateRef, CFDateGetTypeID);
|
||||
impl_CFTypeDescription!(CFDate);
|
||||
impl_CFComparison!(CFDate, CFDateCompare);
|
||||
|
||||
impl CFDate {
|
||||
#[inline]
|
||||
pub fn new(time: CFAbsoluteTime) -> CFDate {
|
||||
unsafe {
|
||||
let date_ref = CFDateCreate(kCFAllocatorDefault, time);
|
||||
TCFType::wrap_under_create_rule(date_ref)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn now() -> CFDate {
|
||||
CFDate::new(unsafe { CFAbsoluteTimeGetCurrent() })
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn abs_time(&self) -> CFAbsoluteTime {
|
||||
unsafe { CFDateGetAbsoluteTime(self.0) }
|
||||
}
|
||||
|
||||
#[cfg(feature = "with-chrono")]
|
||||
pub fn naive_utc(&self) -> NaiveDateTime {
|
||||
let ts = unsafe { self.abs_time() + kCFAbsoluteTimeIntervalSince1970 };
|
||||
let (secs, nanos) = if ts.is_sign_positive() {
|
||||
(ts.trunc() as i64, ts.fract())
|
||||
} else {
|
||||
// nanoseconds can't be negative in NaiveDateTime
|
||||
(ts.trunc() as i64 - 1, 1.0 - ts.fract().abs())
|
||||
};
|
||||
NaiveDateTime::from_timestamp(secs, (nanos * 1e9).floor() as u32)
|
||||
}
|
||||
|
||||
#[cfg(feature = "with-chrono")]
|
||||
pub fn from_naive_utc(time: NaiveDateTime) -> CFDate {
|
||||
let secs = time.timestamp();
|
||||
let nanos = time.timestamp_subsec_nanos();
|
||||
let ts = unsafe { secs as f64 + (nanos as f64 / 1e9) - kCFAbsoluteTimeIntervalSince1970 };
|
||||
CFDate::new(ts)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::CFDate;
|
||||
use std::cmp::Ordering;
|
||||
|
||||
#[cfg(feature = "with-chrono")]
|
||||
use chrono::NaiveDateTime;
|
||||
|
||||
#[cfg(feature = "with-chrono")]
|
||||
fn approx_eq(a: f64, b: f64) -> bool {
|
||||
use std::f64;
|
||||
|
||||
let same_sign = a.is_sign_positive() == b.is_sign_positive();
|
||||
let equal = ((a - b).abs() / f64::min(a.abs() + b.abs(), f64::MAX)) < f64::EPSILON;
|
||||
same_sign && equal
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn date_comparison() {
|
||||
let now = CFDate::now();
|
||||
let past = CFDate::new(now.abs_time() - 1.0);
|
||||
assert_eq!(now.cmp(&past), Ordering::Greater);
|
||||
assert_eq!(now.cmp(&now), Ordering::Equal);
|
||||
assert_eq!(past.cmp(&now), Ordering::Less);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn date_equality() {
|
||||
let now = CFDate::now();
|
||||
let same_time = CFDate::new(now.abs_time());
|
||||
assert_eq!(now, same_time);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "with-chrono")]
|
||||
fn date_chrono_conversion_positive() {
|
||||
let date = CFDate::now();
|
||||
let datetime = date.naive_utc();
|
||||
let converted = CFDate::from_naive_utc(datetime);
|
||||
assert!(approx_eq(date.abs_time(), converted.abs_time()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "with-chrono")]
|
||||
fn date_chrono_conversion_negative() {
|
||||
use super::kCFAbsoluteTimeIntervalSince1970;
|
||||
|
||||
let ts = unsafe { kCFAbsoluteTimeIntervalSince1970 - 420.0 };
|
||||
let date = CFDate::new(ts);
|
||||
let datetime: NaiveDateTime = date.naive_utc();
|
||||
let converted = CFDate::from_naive_utc(datetime);
|
||||
assert!(approx_eq(date.abs_time(), converted.abs_time()));
|
||||
}
|
||||
}
|
||||
481
third-party/vendor/core-foundation/src/dictionary.rs
vendored
Normal file
481
third-party/vendor/core-foundation/src/dictionary.rs
vendored
Normal file
|
|
@ -0,0 +1,481 @@
|
|||
// 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.
|
||||
|
||||
//! Dictionaries of key-value pairs.
|
||||
|
||||
pub use core_foundation_sys::dictionary::*;
|
||||
|
||||
use core_foundation_sys::base::{kCFAllocatorDefault, CFRelease, CFTypeRef};
|
||||
use std::marker::PhantomData;
|
||||
use std::mem;
|
||||
use std::os::raw::c_void;
|
||||
use std::ptr;
|
||||
|
||||
use crate::base::{CFIndexConvertible, TCFType};
|
||||
use crate::base::{FromVoid, ItemRef, ToVoid};
|
||||
use crate::ConcreteCFType;
|
||||
|
||||
// consume the type parameters with PhantomDatas
|
||||
pub struct CFDictionary<K = *const c_void, V = *const c_void>(
|
||||
CFDictionaryRef,
|
||||
PhantomData<K>,
|
||||
PhantomData<V>,
|
||||
);
|
||||
|
||||
impl<K, V> Drop for CFDictionary<K, V> {
|
||||
fn drop(&mut self) {
|
||||
unsafe { CFRelease(self.as_CFTypeRef()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl_TCFType!(CFDictionary<K, V>, CFDictionaryRef, CFDictionaryGetTypeID);
|
||||
impl_CFTypeDescription!(CFDictionary<K, V>);
|
||||
|
||||
unsafe impl ConcreteCFType for CFDictionary<*const c_void, *const c_void> {}
|
||||
|
||||
impl<K, V> CFDictionary<K, V> {
|
||||
pub fn from_CFType_pairs(pairs: &[(K, V)]) -> CFDictionary<K, V>
|
||||
where
|
||||
K: TCFType,
|
||||
V: TCFType,
|
||||
{
|
||||
let (keys, values): (Vec<CFTypeRef>, Vec<CFTypeRef>) = pairs
|
||||
.iter()
|
||||
.map(|(key, value)| (key.as_CFTypeRef(), value.as_CFTypeRef()))
|
||||
.unzip();
|
||||
|
||||
unsafe {
|
||||
let dictionary_ref = CFDictionaryCreate(
|
||||
kCFAllocatorDefault,
|
||||
keys.as_ptr(),
|
||||
values.as_ptr(),
|
||||
keys.len().to_CFIndex(),
|
||||
&kCFTypeDictionaryKeyCallBacks,
|
||||
&kCFTypeDictionaryValueCallBacks,
|
||||
);
|
||||
TCFType::wrap_under_create_rule(dictionary_ref)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_untyped(&self) -> CFDictionary {
|
||||
unsafe { CFDictionary::wrap_under_get_rule(self.0) }
|
||||
}
|
||||
|
||||
/// Returns a `CFMutableDictionary` pointing to the same underlying dictionary as this immutable one.
|
||||
/// This should only be used when the underlying dictionary is mutable.
|
||||
#[inline]
|
||||
pub unsafe fn to_mutable(&self) -> CFMutableDictionary<K, V> {
|
||||
CFMutableDictionary::wrap_under_get_rule(self.0 as CFMutableDictionaryRef)
|
||||
}
|
||||
|
||||
/// Returns the same dictionary, but with the types reset to void pointers.
|
||||
/// Equal to `to_untyped`, but is faster since it does not increment the retain count.
|
||||
#[inline]
|
||||
pub fn into_untyped(self) -> CFDictionary {
|
||||
let reference = self.0;
|
||||
mem::forget(self);
|
||||
unsafe { CFDictionary::wrap_under_create_rule(reference) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn len(&self) -> usize {
|
||||
unsafe { CFDictionaryGetCount(self.0) as usize }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.len() == 0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn contains_key(&self, key: &K) -> bool
|
||||
where
|
||||
K: ToVoid<K>,
|
||||
{
|
||||
unsafe { CFDictionaryContainsKey(self.0, key.to_void()) != 0 }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn find<T: ToVoid<K>>(&self, key: T) -> Option<ItemRef<'_, V>>
|
||||
where
|
||||
V: FromVoid,
|
||||
K: ToVoid<K>,
|
||||
{
|
||||
unsafe {
|
||||
let mut value: *const c_void = ptr::null();
|
||||
if CFDictionaryGetValueIfPresent(self.0, key.to_void(), &mut value) != 0 {
|
||||
Some(V::from_void(value))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the key is not present in the dictionary. Use `find` to get an `Option` instead
|
||||
/// of panicking.
|
||||
#[inline]
|
||||
pub fn get<T: ToVoid<K>>(&self, key: T) -> ItemRef<'_, V>
|
||||
where
|
||||
V: FromVoid,
|
||||
K: ToVoid<K>,
|
||||
{
|
||||
let ptr = key.to_void();
|
||||
self.find(key)
|
||||
.unwrap_or_else(|| panic!("No entry found for key {:p}", ptr))
|
||||
}
|
||||
|
||||
pub fn get_keys_and_values(&self) -> (Vec<*const c_void>, Vec<*const c_void>) {
|
||||
let length = self.len();
|
||||
let mut keys = Vec::with_capacity(length);
|
||||
let mut values = Vec::with_capacity(length);
|
||||
|
||||
unsafe {
|
||||
CFDictionaryGetKeysAndValues(self.0, keys.as_mut_ptr(), values.as_mut_ptr());
|
||||
keys.set_len(length);
|
||||
values.set_len(length);
|
||||
}
|
||||
|
||||
(keys, values)
|
||||
}
|
||||
}
|
||||
|
||||
// consume the type parameters with PhantomDatas
|
||||
pub struct CFMutableDictionary<K = *const c_void, V = *const c_void>(
|
||||
CFMutableDictionaryRef,
|
||||
PhantomData<K>,
|
||||
PhantomData<V>,
|
||||
);
|
||||
|
||||
impl<K, V> Drop for CFMutableDictionary<K, V> {
|
||||
fn drop(&mut self) {
|
||||
unsafe { CFRelease(self.as_CFTypeRef()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl_TCFType!(CFMutableDictionary<K, V>, CFMutableDictionaryRef, CFDictionaryGetTypeID);
|
||||
impl_CFTypeDescription!(CFMutableDictionary);
|
||||
|
||||
impl<K, V> CFMutableDictionary<K, V> {
|
||||
pub fn new() -> Self {
|
||||
Self::with_capacity(0)
|
||||
}
|
||||
|
||||
pub fn with_capacity(capacity: isize) -> Self {
|
||||
unsafe {
|
||||
let dictionary_ref = CFDictionaryCreateMutable(
|
||||
kCFAllocatorDefault,
|
||||
capacity as _,
|
||||
&kCFTypeDictionaryKeyCallBacks,
|
||||
&kCFTypeDictionaryValueCallBacks,
|
||||
);
|
||||
TCFType::wrap_under_create_rule(dictionary_ref)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn copy_with_capacity(&self, capacity: isize) -> Self {
|
||||
unsafe {
|
||||
let dictionary_ref =
|
||||
CFDictionaryCreateMutableCopy(kCFAllocatorDefault, capacity as _, self.0);
|
||||
TCFType::wrap_under_get_rule(dictionary_ref)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_CFType_pairs(pairs: &[(K, V)]) -> CFMutableDictionary<K, V>
|
||||
where
|
||||
K: ToVoid<K>,
|
||||
V: ToVoid<V>,
|
||||
{
|
||||
let mut result = Self::with_capacity(pairs.len() as _);
|
||||
for (key, value) in pairs {
|
||||
result.add(key, value);
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_untyped(&self) -> CFMutableDictionary {
|
||||
unsafe { CFMutableDictionary::wrap_under_get_rule(self.0) }
|
||||
}
|
||||
|
||||
/// Returns the same dictionary, but with the types reset to void pointers.
|
||||
/// Equal to `to_untyped`, but is faster since it does not increment the retain count.
|
||||
#[inline]
|
||||
pub fn into_untyped(self) -> CFMutableDictionary {
|
||||
let reference = self.0;
|
||||
mem::forget(self);
|
||||
unsafe { CFMutableDictionary::wrap_under_create_rule(reference) }
|
||||
}
|
||||
|
||||
/// Returns a `CFDictionary` pointing to the same underlying dictionary as this mutable one.
|
||||
#[inline]
|
||||
pub fn to_immutable(&self) -> CFDictionary<K, V> {
|
||||
unsafe { CFDictionary::wrap_under_get_rule(self.0) }
|
||||
}
|
||||
|
||||
// Immutable interface
|
||||
|
||||
#[inline]
|
||||
pub fn len(&self) -> usize {
|
||||
unsafe { CFDictionaryGetCount(self.0) as usize }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.len() == 0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn contains_key(&self, key: *const c_void) -> bool {
|
||||
unsafe { CFDictionaryContainsKey(self.0, key) != 0 }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn find<'a>(&'a self, key: &K) -> Option<ItemRef<'a, V>>
|
||||
where
|
||||
V: FromVoid,
|
||||
K: ToVoid<K>,
|
||||
{
|
||||
unsafe {
|
||||
let mut value: *const c_void = ptr::null();
|
||||
if CFDictionaryGetValueIfPresent(self.0, key.to_void(), &mut value) != 0 {
|
||||
Some(V::from_void(value))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the key is not present in the dictionary. Use `find` to get an `Option` instead
|
||||
/// of panicking.
|
||||
#[inline]
|
||||
pub fn get<'a>(&'a self, key: &K) -> ItemRef<'a, V>
|
||||
where
|
||||
V: FromVoid,
|
||||
K: ToVoid<K>,
|
||||
{
|
||||
let ptr = key.to_void();
|
||||
self.find(key)
|
||||
.unwrap_or_else(|| panic!("No entry found for key {:p}", ptr))
|
||||
}
|
||||
|
||||
pub fn get_keys_and_values(&self) -> (Vec<*const c_void>, Vec<*const c_void>) {
|
||||
let length = self.len();
|
||||
let mut keys = Vec::with_capacity(length);
|
||||
let mut values = Vec::with_capacity(length);
|
||||
|
||||
unsafe {
|
||||
CFDictionaryGetKeysAndValues(self.0, keys.as_mut_ptr(), values.as_mut_ptr());
|
||||
keys.set_len(length);
|
||||
values.set_len(length);
|
||||
}
|
||||
|
||||
(keys, values)
|
||||
}
|
||||
|
||||
// Mutable interface
|
||||
|
||||
/// Adds the key-value pair to the dictionary if no such key already exist.
|
||||
#[inline]
|
||||
pub fn add(&mut self, key: &K, value: &V)
|
||||
where
|
||||
K: ToVoid<K>,
|
||||
V: ToVoid<V>,
|
||||
{
|
||||
unsafe { CFDictionaryAddValue(self.0, key.to_void(), value.to_void()) }
|
||||
}
|
||||
|
||||
/// Sets the value of the key in the dictionary.
|
||||
#[inline]
|
||||
pub fn set(&mut self, key: K, value: V)
|
||||
where
|
||||
K: ToVoid<K>,
|
||||
V: ToVoid<V>,
|
||||
{
|
||||
unsafe { CFDictionarySetValue(self.0, key.to_void(), value.to_void()) }
|
||||
}
|
||||
|
||||
/// Replaces the value of the key in the dictionary.
|
||||
#[inline]
|
||||
pub fn replace(&mut self, key: K, value: V)
|
||||
where
|
||||
K: ToVoid<K>,
|
||||
V: ToVoid<V>,
|
||||
{
|
||||
unsafe { CFDictionaryReplaceValue(self.0, key.to_void(), value.to_void()) }
|
||||
}
|
||||
|
||||
/// Removes the value of the key from the dictionary.
|
||||
#[inline]
|
||||
pub fn remove(&mut self, key: K)
|
||||
where
|
||||
K: ToVoid<K>,
|
||||
{
|
||||
unsafe { CFDictionaryRemoveValue(self.0, key.to_void()) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn remove_all(&mut self) {
|
||||
unsafe { CFDictionaryRemoveAllValues(self.0) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<K, V> Default for CFMutableDictionary<K, V> {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, K, V> From<&'a CFDictionary<K, V>> for CFMutableDictionary<K, V> {
|
||||
/// Creates a new mutable dictionary with the key-value pairs from another dictionary.
|
||||
/// The capacity of the new mutable dictionary is not limited.
|
||||
fn from(dict: &'a CFDictionary<K, V>) -> Self {
|
||||
unsafe {
|
||||
let mut_dict_ref = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, dict.0);
|
||||
TCFType::wrap_under_create_rule(mut_dict_ref)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod test {
|
||||
use super::*;
|
||||
use crate::base::{CFType, TCFType};
|
||||
use crate::boolean::CFBoolean;
|
||||
use crate::number::CFNumber;
|
||||
use crate::string::CFString;
|
||||
|
||||
#[test]
|
||||
fn dictionary() {
|
||||
let bar = CFString::from_static_string("Bar");
|
||||
let baz = CFString::from_static_string("Baz");
|
||||
let boo = CFString::from_static_string("Boo");
|
||||
let foo = CFString::from_static_string("Foo");
|
||||
let tru = CFBoolean::true_value();
|
||||
let n42 = CFNumber::from(42);
|
||||
|
||||
let d = CFDictionary::from_CFType_pairs(&[
|
||||
(bar.as_CFType(), boo.as_CFType()),
|
||||
(baz.as_CFType(), tru.as_CFType()),
|
||||
(foo.as_CFType(), n42.as_CFType()),
|
||||
]);
|
||||
|
||||
let (v1, v2) = d.get_keys_and_values();
|
||||
assert_eq!(
|
||||
v1,
|
||||
&[bar.as_CFTypeRef(), baz.as_CFTypeRef(), foo.as_CFTypeRef()]
|
||||
);
|
||||
assert_eq!(
|
||||
v2,
|
||||
&[boo.as_CFTypeRef(), tru.as_CFTypeRef(), n42.as_CFTypeRef()]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mutable_dictionary() {
|
||||
let bar = CFString::from_static_string("Bar");
|
||||
let baz = CFString::from_static_string("Baz");
|
||||
let boo = CFString::from_static_string("Boo");
|
||||
let foo = CFString::from_static_string("Foo");
|
||||
let tru = CFBoolean::true_value();
|
||||
let n42 = CFNumber::from(42);
|
||||
|
||||
let mut d = CFMutableDictionary::<CFString, CFType>::new();
|
||||
d.add(&bar, &boo.as_CFType());
|
||||
d.add(&baz, &tru.as_CFType());
|
||||
d.add(&foo, &n42.as_CFType());
|
||||
assert_eq!(d.len(), 3);
|
||||
|
||||
let (v1, v2) = d.get_keys_and_values();
|
||||
assert_eq!(
|
||||
v1,
|
||||
&[bar.as_CFTypeRef(), baz.as_CFTypeRef(), foo.as_CFTypeRef()]
|
||||
);
|
||||
assert_eq!(
|
||||
v2,
|
||||
&[boo.as_CFTypeRef(), tru.as_CFTypeRef(), n42.as_CFTypeRef()]
|
||||
);
|
||||
|
||||
d.remove(baz);
|
||||
assert_eq!(d.len(), 2);
|
||||
|
||||
let (v1, v2) = d.get_keys_and_values();
|
||||
assert_eq!(v1, &[bar.as_CFTypeRef(), foo.as_CFTypeRef()]);
|
||||
assert_eq!(v2, &[boo.as_CFTypeRef(), n42.as_CFTypeRef()]);
|
||||
|
||||
d.remove_all();
|
||||
assert_eq!(d.len(), 0)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dict_find_and_contains_key() {
|
||||
let dict = CFDictionary::from_CFType_pairs(&[(
|
||||
CFString::from_static_string("hello"),
|
||||
CFBoolean::true_value(),
|
||||
)]);
|
||||
let key = CFString::from_static_string("hello");
|
||||
let invalid_key = CFString::from_static_string("foobar");
|
||||
|
||||
assert!(dict.contains_key(&key));
|
||||
assert!(!dict.contains_key(&invalid_key));
|
||||
|
||||
let value = dict.find(&key).unwrap().clone();
|
||||
assert_eq!(value, CFBoolean::true_value());
|
||||
assert_eq!(dict.find(&invalid_key), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn convert_immutable_to_mutable_dict() {
|
||||
let dict: CFDictionary<CFString, CFBoolean> = CFDictionary::from_CFType_pairs(&[(
|
||||
CFString::from_static_string("Foo"),
|
||||
CFBoolean::true_value(),
|
||||
)]);
|
||||
let mut mut_dict = CFMutableDictionary::from(&dict);
|
||||
assert_eq!(dict.retain_count(), 1);
|
||||
assert_eq!(mut_dict.retain_count(), 1);
|
||||
|
||||
assert_eq!(mut_dict.len(), 1);
|
||||
assert_eq!(
|
||||
*mut_dict.get(&CFString::from_static_string("Foo")),
|
||||
CFBoolean::true_value()
|
||||
);
|
||||
|
||||
mut_dict.add(
|
||||
&CFString::from_static_string("Bar"),
|
||||
&CFBoolean::false_value(),
|
||||
);
|
||||
assert_eq!(dict.len(), 1);
|
||||
assert_eq!(mut_dict.len(), 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mutable_dictionary_as_immutable() {
|
||||
let mut mut_dict: CFMutableDictionary<CFString, CFBoolean> = CFMutableDictionary::new();
|
||||
mut_dict.add(
|
||||
&CFString::from_static_string("Bar"),
|
||||
&CFBoolean::false_value(),
|
||||
);
|
||||
assert_eq!(mut_dict.retain_count(), 1);
|
||||
|
||||
let dict = mut_dict.to_immutable();
|
||||
assert_eq!(mut_dict.retain_count(), 2);
|
||||
assert_eq!(dict.retain_count(), 2);
|
||||
assert_eq!(
|
||||
*dict.get(&CFString::from_static_string("Bar")),
|
||||
CFBoolean::false_value()
|
||||
);
|
||||
|
||||
mem::drop(dict);
|
||||
assert_eq!(mut_dict.retain_count(), 1);
|
||||
}
|
||||
}
|
||||
70
third-party/vendor/core-foundation/src/error.rs
vendored
Normal file
70
third-party/vendor/core-foundation/src/error.rs
vendored
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
// Copyright 2016 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.
|
||||
|
||||
//! Core Foundation errors.
|
||||
|
||||
pub use core_foundation_sys::error::*;
|
||||
|
||||
use std::error::Error;
|
||||
use std::fmt;
|
||||
|
||||
use crate::base::{CFIndex, TCFType};
|
||||
use crate::string::CFString;
|
||||
|
||||
declare_TCFType! {
|
||||
/// An error value.
|
||||
CFError, CFErrorRef
|
||||
}
|
||||
impl_TCFType!(CFError, CFErrorRef, CFErrorGetTypeID);
|
||||
|
||||
impl fmt::Debug for CFError {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt.debug_struct("CFError")
|
||||
.field("domain", &self.domain())
|
||||
.field("code", &self.code())
|
||||
.field("description", &self.description())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for CFError {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(fmt, "{}", self.description())
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for CFError {
|
||||
fn description(&self) -> &str {
|
||||
"a Core Foundation error"
|
||||
}
|
||||
}
|
||||
|
||||
impl CFError {
|
||||
/// Returns a string identifying the domain with which this error is
|
||||
/// associated.
|
||||
pub fn domain(&self) -> CFString {
|
||||
unsafe {
|
||||
let s = CFErrorGetDomain(self.0);
|
||||
CFString::wrap_under_get_rule(s)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the code identifying this type of error.
|
||||
pub fn code(&self) -> CFIndex {
|
||||
unsafe { CFErrorGetCode(self.0) }
|
||||
}
|
||||
|
||||
/// Returns a human-presentable description of the error.
|
||||
pub fn description(&self) -> CFString {
|
||||
unsafe {
|
||||
let s = CFErrorCopyDescription(self.0);
|
||||
CFString::wrap_under_create_rule(s)
|
||||
}
|
||||
}
|
||||
}
|
||||
194
third-party/vendor/core-foundation/src/filedescriptor.rs
vendored
Normal file
194
third-party/vendor/core-foundation/src/filedescriptor.rs
vendored
Normal file
|
|
@ -0,0 +1,194 @@
|
|||
// 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.
|
||||
|
||||
pub use core_foundation_sys::filedescriptor::*;
|
||||
|
||||
use core_foundation_sys::base::{kCFAllocatorDefault, CFOptionFlags};
|
||||
use core_foundation_sys::base::{Boolean, CFIndex};
|
||||
|
||||
use crate::base::TCFType;
|
||||
use crate::runloop::CFRunLoopSource;
|
||||
|
||||
use std::mem::MaybeUninit;
|
||||
use std::os::unix::io::{AsRawFd, RawFd};
|
||||
use std::ptr;
|
||||
|
||||
declare_TCFType! {
|
||||
CFFileDescriptor, CFFileDescriptorRef
|
||||
}
|
||||
impl_TCFType!(
|
||||
CFFileDescriptor,
|
||||
CFFileDescriptorRef,
|
||||
CFFileDescriptorGetTypeID
|
||||
);
|
||||
|
||||
impl CFFileDescriptor {
|
||||
pub fn new(
|
||||
fd: RawFd,
|
||||
closeOnInvalidate: bool,
|
||||
callout: CFFileDescriptorCallBack,
|
||||
context: Option<&CFFileDescriptorContext>,
|
||||
) -> Option<CFFileDescriptor> {
|
||||
let context = context.map_or(ptr::null(), |c| c as *const _);
|
||||
unsafe {
|
||||
let fd_ref = CFFileDescriptorCreate(
|
||||
kCFAllocatorDefault,
|
||||
fd,
|
||||
closeOnInvalidate as Boolean,
|
||||
callout,
|
||||
context,
|
||||
);
|
||||
if fd_ref.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(TCFType::wrap_under_create_rule(fd_ref))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn context(&self) -> CFFileDescriptorContext {
|
||||
unsafe {
|
||||
let mut context = MaybeUninit::<CFFileDescriptorContext>::uninit();
|
||||
CFFileDescriptorGetContext(self.0, context.as_mut_ptr());
|
||||
context.assume_init()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn enable_callbacks(&self, callback_types: CFOptionFlags) {
|
||||
unsafe { CFFileDescriptorEnableCallBacks(self.0, callback_types) }
|
||||
}
|
||||
|
||||
pub fn disable_callbacks(&self, callback_types: CFOptionFlags) {
|
||||
unsafe { CFFileDescriptorDisableCallBacks(self.0, callback_types) }
|
||||
}
|
||||
|
||||
pub fn valid(&self) -> bool {
|
||||
unsafe { CFFileDescriptorIsValid(self.0) != 0 }
|
||||
}
|
||||
|
||||
pub fn invalidate(&self) {
|
||||
unsafe { CFFileDescriptorInvalidate(self.0) }
|
||||
}
|
||||
|
||||
pub fn to_run_loop_source(&self, order: CFIndex) -> Option<CFRunLoopSource> {
|
||||
unsafe {
|
||||
let source_ref =
|
||||
CFFileDescriptorCreateRunLoopSource(kCFAllocatorDefault, self.0, order);
|
||||
if source_ref.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(TCFType::wrap_under_create_rule(source_ref))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawFd for CFFileDescriptor {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
unsafe { CFFileDescriptorGetNativeDescriptor(self.0) }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
extern crate libc;
|
||||
|
||||
use super::*;
|
||||
use crate::runloop::CFRunLoop;
|
||||
use core_foundation_sys::base::CFOptionFlags;
|
||||
use core_foundation_sys::runloop::kCFRunLoopDefaultMode;
|
||||
use libc::O_RDWR;
|
||||
use std::ffi::CString;
|
||||
use std::os::raw::c_void;
|
||||
|
||||
#[test]
|
||||
fn test_unconsumed() {
|
||||
let path = CString::new("/dev/null").unwrap();
|
||||
let raw_fd = unsafe { libc::open(path.as_ptr(), O_RDWR, 0) };
|
||||
let cf_fd = CFFileDescriptor::new(raw_fd, false, never_callback, None);
|
||||
assert!(cf_fd.is_some());
|
||||
let cf_fd = cf_fd.unwrap();
|
||||
|
||||
assert!(cf_fd.valid());
|
||||
cf_fd.invalidate();
|
||||
assert!(!cf_fd.valid());
|
||||
|
||||
// close() should succeed
|
||||
assert_eq!(unsafe { libc::close(raw_fd) }, 0);
|
||||
}
|
||||
|
||||
extern "C" fn never_callback(
|
||||
_f: CFFileDescriptorRef,
|
||||
_callback_types: CFOptionFlags,
|
||||
_info_ptr: *mut c_void,
|
||||
) {
|
||||
unreachable!();
|
||||
}
|
||||
|
||||
struct TestInfo {
|
||||
value: CFOptionFlags,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_callback() {
|
||||
let mut info = TestInfo { value: 0 };
|
||||
let context = CFFileDescriptorContext {
|
||||
version: 0,
|
||||
info: &mut info as *mut _ as *mut c_void,
|
||||
retain: None,
|
||||
release: None,
|
||||
copyDescription: None,
|
||||
};
|
||||
|
||||
let path = CString::new("/dev/null").unwrap();
|
||||
let raw_fd = unsafe { libc::open(path.as_ptr(), O_RDWR, 0) };
|
||||
let cf_fd = CFFileDescriptor::new(raw_fd, true, callback, Some(&context));
|
||||
assert!(cf_fd.is_some());
|
||||
let cf_fd = cf_fd.unwrap();
|
||||
|
||||
assert!(cf_fd.valid());
|
||||
|
||||
let run_loop = CFRunLoop::get_current();
|
||||
let source = CFRunLoopSource::from_file_descriptor(&cf_fd, 0);
|
||||
assert!(source.is_some());
|
||||
unsafe {
|
||||
run_loop.add_source(&source.unwrap(), kCFRunLoopDefaultMode);
|
||||
}
|
||||
|
||||
info.value = 0;
|
||||
cf_fd.enable_callbacks(kCFFileDescriptorReadCallBack);
|
||||
CFRunLoop::run_current();
|
||||
assert_eq!(info.value, kCFFileDescriptorReadCallBack);
|
||||
|
||||
info.value = 0;
|
||||
cf_fd.enable_callbacks(kCFFileDescriptorWriteCallBack);
|
||||
CFRunLoop::run_current();
|
||||
assert_eq!(info.value, kCFFileDescriptorWriteCallBack);
|
||||
|
||||
info.value = 0;
|
||||
cf_fd.disable_callbacks(kCFFileDescriptorReadCallBack | kCFFileDescriptorWriteCallBack);
|
||||
|
||||
cf_fd.invalidate();
|
||||
assert!(!cf_fd.valid());
|
||||
}
|
||||
|
||||
extern "C" fn callback(
|
||||
_f: CFFileDescriptorRef,
|
||||
callback_types: CFOptionFlags,
|
||||
info_ptr: *mut c_void,
|
||||
) {
|
||||
assert!(!info_ptr.is_null());
|
||||
|
||||
let info: *mut TestInfo = info_ptr as *mut TestInfo;
|
||||
|
||||
unsafe { (*info).value = callback_types };
|
||||
|
||||
CFRunLoop::get_current().stop();
|
||||
}
|
||||
}
|
||||
242
third-party/vendor/core-foundation/src/lib.rs
vendored
Normal file
242
third-party/vendor/core-foundation/src/lib.rs
vendored
Normal file
|
|
@ -0,0 +1,242 @@
|
|||
// 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_snake_case)]
|
||||
|
||||
//! This crate provides wrappers around the underlying CoreFoundation
|
||||
//! types and functions that are available on Apple's operating systems.
|
||||
//!
|
||||
//! It also provides a framework for other crates to use when wrapping
|
||||
//! other frameworks that use the CoreFoundation framework.
|
||||
|
||||
extern crate core_foundation_sys;
|
||||
extern crate libc;
|
||||
|
||||
#[cfg(feature = "with-chrono")]
|
||||
extern crate chrono;
|
||||
|
||||
use crate::base::TCFType;
|
||||
|
||||
pub unsafe trait ConcreteCFType: TCFType {}
|
||||
|
||||
/// Declare a Rust type that wraps an underlying CoreFoundation type.
|
||||
///
|
||||
/// This will provide an implementation of `Drop` using [`CFRelease`].
|
||||
/// The type must have an implementation of the [`TCFType`] trait, usually
|
||||
/// provided using the [`impl_TCFType`] macro.
|
||||
///
|
||||
/// ```
|
||||
/// #[macro_use] extern crate core_foundation;
|
||||
/// // Make sure that the `TCFType` trait is in scope.
|
||||
/// use core_foundation::base::{CFTypeID, TCFType};
|
||||
///
|
||||
/// extern "C" {
|
||||
/// // We need a function that returns the `CFTypeID`.
|
||||
/// pub fn ShrubberyGetTypeID() -> CFTypeID;
|
||||
/// }
|
||||
///
|
||||
/// pub struct __Shrubbery {}
|
||||
/// // The ref type must be a pointer to the underlying struct.
|
||||
/// pub type ShrubberyRef = *const __Shrubbery;
|
||||
///
|
||||
/// declare_TCFType!(Shrubbery, ShrubberyRef);
|
||||
/// impl_TCFType!(Shrubbery, ShrubberyRef, ShrubberyGetTypeID);
|
||||
/// # fn main() {}
|
||||
/// ```
|
||||
///
|
||||
/// [`CFRelease`]: https://developer.apple.com/documentation/corefoundation/1521153-cfrelease
|
||||
/// [`TCFType`]: base/trait.TCFType.html
|
||||
/// [`impl_TCFType`]: macro.impl_TCFType.html
|
||||
#[macro_export]
|
||||
macro_rules! declare_TCFType {
|
||||
(
|
||||
$(#[$doc:meta])*
|
||||
$ty:ident, $raw:ident
|
||||
) => {
|
||||
$(#[$doc])*
|
||||
pub struct $ty($raw);
|
||||
|
||||
impl Drop for $ty {
|
||||
fn drop(&mut self) {
|
||||
unsafe { $crate::base::CFRelease(self.as_CFTypeRef()) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Provide an implementation of the [`TCFType`] trait for the Rust
|
||||
/// wrapper type around an underlying CoreFoundation type.
|
||||
///
|
||||
/// See [`declare_TCFType`] for details.
|
||||
///
|
||||
/// [`declare_TCFType`]: macro.declare_TCFType.html
|
||||
/// [`TCFType`]: base/trait.TCFType.html
|
||||
#[macro_export]
|
||||
macro_rules! impl_TCFType {
|
||||
($ty:ident, $ty_ref:ident, $ty_id:ident) => {
|
||||
impl_TCFType!($ty<>, $ty_ref, $ty_id);
|
||||
unsafe impl $crate::ConcreteCFType for $ty { }
|
||||
};
|
||||
|
||||
($ty:ident<$($p:ident $(: $bound:path)*),*>, $ty_ref:ident, $ty_id:ident) => {
|
||||
impl<$($p $(: $bound)*),*> $crate::base::TCFType for $ty<$($p),*> {
|
||||
type Ref = $ty_ref;
|
||||
|
||||
#[inline]
|
||||
fn as_concrete_TypeRef(&self) -> $ty_ref {
|
||||
self.0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn wrap_under_get_rule(reference: $ty_ref) -> Self {
|
||||
assert!(!reference.is_null(), "Attempted to create a NULL object.");
|
||||
let reference = $crate::base::CFRetain(reference as *const ::std::os::raw::c_void) as $ty_ref;
|
||||
$crate::base::TCFType::wrap_under_create_rule(reference)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_CFTypeRef(&self) -> $crate::base::CFTypeRef {
|
||||
self.as_concrete_TypeRef() as $crate::base::CFTypeRef
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn wrap_under_create_rule(reference: $ty_ref) -> Self {
|
||||
assert!(!reference.is_null(), "Attempted to create a NULL object.");
|
||||
// we need one PhantomData for each type parameter so call ourselves
|
||||
// again with @Phantom $p to produce that
|
||||
$ty(reference $(, impl_TCFType!(@Phantom $p))*)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn type_id() -> $crate::base::CFTypeID {
|
||||
unsafe {
|
||||
$ty_id()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for $ty {
|
||||
#[inline]
|
||||
fn clone(&self) -> $ty {
|
||||
unsafe {
|
||||
$ty::wrap_under_get_rule(self.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for $ty {
|
||||
#[inline]
|
||||
fn eq(&self, other: &$ty) -> bool {
|
||||
self.as_CFType().eq(&other.as_CFType())
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for $ty { }
|
||||
|
||||
unsafe impl<'a> $crate::base::ToVoid<$ty> for &'a $ty {
|
||||
fn to_void(&self) -> *const ::std::os::raw::c_void {
|
||||
use $crate::base::TCFTypeRef;
|
||||
self.as_concrete_TypeRef().as_void_ptr()
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl $crate::base::ToVoid<$ty> for $ty {
|
||||
fn to_void(&self) -> *const ::std::os::raw::c_void {
|
||||
use $crate::base::TCFTypeRef;
|
||||
self.as_concrete_TypeRef().as_void_ptr()
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl $crate::base::ToVoid<$ty> for $ty_ref {
|
||||
fn to_void(&self) -> *const ::std::os::raw::c_void {
|
||||
use $crate::base::TCFTypeRef;
|
||||
self.as_void_ptr()
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
(@Phantom $x:ident) => { ::std::marker::PhantomData };
|
||||
}
|
||||
|
||||
/// Implement `std::fmt::Debug` for the given type.
|
||||
///
|
||||
/// This will invoke the implementation of `Debug` for [`CFType`]
|
||||
/// which invokes [`CFCopyDescription`].
|
||||
///
|
||||
/// The type must have an implementation of the [`TCFType`] trait, usually
|
||||
/// provided using the [`impl_TCFType`] macro.
|
||||
///
|
||||
/// [`CFType`]: base/struct.CFType.html#impl-Debug
|
||||
/// [`CFCopyDescription`]: https://developer.apple.com/documentation/corefoundation/1521252-cfcopydescription?language=objc
|
||||
/// [`TCFType`]: base/trait.TCFType.html
|
||||
/// [`impl_TCFType`]: macro.impl_TCFType.html
|
||||
#[macro_export]
|
||||
macro_rules! impl_CFTypeDescription {
|
||||
($ty:ident) => {
|
||||
// it's fine to use an empty <> list
|
||||
impl_CFTypeDescription!($ty<>);
|
||||
};
|
||||
($ty:ident<$($p:ident $(: $bound:path)*),*>) => {
|
||||
impl<$($p $(: $bound)*),*> ::std::fmt::Debug for $ty<$($p),*> {
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
||||
self.as_CFType().fmt(f)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! impl_CFComparison {
|
||||
($ty:ident, $compare:ident) => {
|
||||
impl PartialOrd for $ty {
|
||||
#[inline]
|
||||
fn partial_cmp(&self, other: &$ty) -> Option<::std::cmp::Ordering> {
|
||||
unsafe {
|
||||
Some(
|
||||
$compare(
|
||||
self.as_concrete_TypeRef(),
|
||||
other.as_concrete_TypeRef(),
|
||||
::std::ptr::null_mut(),
|
||||
)
|
||||
.into(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for $ty {
|
||||
#[inline]
|
||||
fn cmp(&self, other: &$ty) -> ::std::cmp::Ordering {
|
||||
self.partial_cmp(other).unwrap()
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub mod array;
|
||||
pub mod attributed_string;
|
||||
pub mod base;
|
||||
pub mod boolean;
|
||||
pub mod bundle;
|
||||
pub mod characterset;
|
||||
pub mod data;
|
||||
pub mod date;
|
||||
pub mod dictionary;
|
||||
pub mod error;
|
||||
pub mod filedescriptor;
|
||||
pub mod mach_port;
|
||||
pub mod number;
|
||||
pub mod propertylist;
|
||||
pub mod runloop;
|
||||
pub mod set;
|
||||
pub mod string;
|
||||
pub mod timezone;
|
||||
pub mod url;
|
||||
pub mod uuid;
|
||||
25
third-party/vendor/core-foundation/src/mach_port.rs
vendored
Normal file
25
third-party/vendor/core-foundation/src/mach_port.rs
vendored
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
use crate::base::TCFType;
|
||||
use crate::runloop::CFRunLoopSource;
|
||||
use core_foundation_sys::base::kCFAllocatorDefault;
|
||||
pub use core_foundation_sys::mach_port::*;
|
||||
|
||||
declare_TCFType! {
|
||||
/// An immutable numeric value.
|
||||
CFMachPort, CFMachPortRef
|
||||
}
|
||||
impl_TCFType!(CFMachPort, CFMachPortRef, CFMachPortGetTypeID);
|
||||
impl_CFTypeDescription!(CFMachPort);
|
||||
|
||||
impl CFMachPort {
|
||||
pub fn create_runloop_source(&self, order: CFIndex) -> Result<CFRunLoopSource, ()> {
|
||||
unsafe {
|
||||
let runloop_source_ref =
|
||||
CFMachPortCreateRunLoopSource(kCFAllocatorDefault, self.0, order);
|
||||
if runloop_source_ref.is_null() {
|
||||
Err(())
|
||||
} else {
|
||||
Ok(CFRunLoopSource::wrap_under_create_rule(runloop_source_ref))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
150
third-party/vendor/core-foundation/src/number.rs
vendored
Normal file
150
third-party/vendor/core-foundation/src/number.rs
vendored
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
// 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.
|
||||
|
||||
//! Immutable numbers.
|
||||
|
||||
use core_foundation_sys::base::kCFAllocatorDefault;
|
||||
pub use core_foundation_sys::number::*;
|
||||
use std::os::raw::c_void;
|
||||
|
||||
use crate::base::TCFType;
|
||||
|
||||
declare_TCFType! {
|
||||
/// An immutable numeric value.
|
||||
CFNumber, CFNumberRef
|
||||
}
|
||||
impl_TCFType!(CFNumber, CFNumberRef, CFNumberGetTypeID);
|
||||
impl_CFTypeDescription!(CFNumber);
|
||||
impl_CFComparison!(CFNumber, CFNumberCompare);
|
||||
|
||||
impl CFNumber {
|
||||
#[inline]
|
||||
pub fn to_i32(&self) -> Option<i32> {
|
||||
unsafe {
|
||||
let mut value: i32 = 0;
|
||||
let ok = CFNumberGetValue(
|
||||
self.0,
|
||||
kCFNumberSInt32Type,
|
||||
&mut value as *mut i32 as *mut c_void,
|
||||
);
|
||||
if ok {
|
||||
Some(value)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_i64(&self) -> Option<i64> {
|
||||
unsafe {
|
||||
let mut value: i64 = 0;
|
||||
let ok = CFNumberGetValue(
|
||||
self.0,
|
||||
kCFNumberSInt64Type,
|
||||
&mut value as *mut i64 as *mut c_void,
|
||||
);
|
||||
if ok {
|
||||
Some(value)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_f32(&self) -> Option<f32> {
|
||||
unsafe {
|
||||
let mut value: f32 = 0.0;
|
||||
let ok = CFNumberGetValue(
|
||||
self.0,
|
||||
kCFNumberFloat32Type,
|
||||
&mut value as *mut f32 as *mut c_void,
|
||||
);
|
||||
if ok {
|
||||
Some(value)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_f64(&self) -> Option<f64> {
|
||||
unsafe {
|
||||
let mut value: f64 = 0.0;
|
||||
let ok = CFNumberGetValue(
|
||||
self.0,
|
||||
kCFNumberFloat64Type,
|
||||
&mut value as *mut f64 as *mut c_void,
|
||||
);
|
||||
if ok {
|
||||
Some(value)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<i32> for CFNumber {
|
||||
#[inline]
|
||||
fn from(value: i32) -> Self {
|
||||
unsafe {
|
||||
let number_ref = CFNumberCreate(
|
||||
kCFAllocatorDefault,
|
||||
kCFNumberSInt32Type,
|
||||
&value as *const i32 as *const c_void,
|
||||
);
|
||||
TCFType::wrap_under_create_rule(number_ref)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<i64> for CFNumber {
|
||||
#[inline]
|
||||
fn from(value: i64) -> Self {
|
||||
unsafe {
|
||||
let number_ref = CFNumberCreate(
|
||||
kCFAllocatorDefault,
|
||||
kCFNumberSInt64Type,
|
||||
&value as *const i64 as *const c_void,
|
||||
);
|
||||
TCFType::wrap_under_create_rule(number_ref)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<f32> for CFNumber {
|
||||
#[inline]
|
||||
fn from(value: f32) -> Self {
|
||||
unsafe {
|
||||
let number_ref = CFNumberCreate(
|
||||
kCFAllocatorDefault,
|
||||
kCFNumberFloat32Type,
|
||||
&value as *const f32 as *const c_void,
|
||||
);
|
||||
TCFType::wrap_under_create_rule(number_ref)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<f64> for CFNumber {
|
||||
#[inline]
|
||||
fn from(value: f64) -> Self {
|
||||
unsafe {
|
||||
let number_ref = CFNumberCreate(
|
||||
kCFAllocatorDefault,
|
||||
kCFNumberFloat64Type,
|
||||
&value as *const f64 as *const c_void,
|
||||
);
|
||||
TCFType::wrap_under_create_rule(number_ref)
|
||||
}
|
||||
}
|
||||
}
|
||||
334
third-party/vendor/core-foundation/src/propertylist.rs
vendored
Normal file
334
third-party/vendor/core-foundation/src/propertylist.rs
vendored
Normal file
|
|
@ -0,0 +1,334 @@
|
|||
// 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.
|
||||
|
||||
//! Core Foundation property lists
|
||||
|
||||
use std::mem;
|
||||
use std::os::raw::c_void;
|
||||
use std::ptr;
|
||||
|
||||
use crate::base::{CFType, TCFType, TCFTypeRef};
|
||||
use crate::data::CFData;
|
||||
use crate::error::CFError;
|
||||
|
||||
use core_foundation_sys::base::{
|
||||
kCFAllocatorDefault, CFGetRetainCount, CFGetTypeID, CFIndex, CFRetain, CFShow, CFTypeID,
|
||||
};
|
||||
use core_foundation_sys::error::CFErrorRef;
|
||||
pub use core_foundation_sys::propertylist::*;
|
||||
|
||||
pub fn create_with_data(
|
||||
data: CFData,
|
||||
options: CFPropertyListMutabilityOptions,
|
||||
) -> Result<(*const c_void, CFPropertyListFormat), CFError> {
|
||||
unsafe {
|
||||
let mut error: CFErrorRef = ptr::null_mut();
|
||||
let mut format: CFPropertyListFormat = 0;
|
||||
let property_list = CFPropertyListCreateWithData(
|
||||
kCFAllocatorDefault,
|
||||
data.as_concrete_TypeRef(),
|
||||
options,
|
||||
&mut format,
|
||||
&mut error,
|
||||
);
|
||||
if property_list.is_null() {
|
||||
Err(TCFType::wrap_under_create_rule(error))
|
||||
} else {
|
||||
Ok((property_list, format))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_data(
|
||||
property_list: *const c_void,
|
||||
format: CFPropertyListFormat,
|
||||
) -> Result<CFData, CFError> {
|
||||
unsafe {
|
||||
let mut error: CFErrorRef = ptr::null_mut();
|
||||
let data_ref =
|
||||
CFPropertyListCreateData(kCFAllocatorDefault, property_list, format, 0, &mut error);
|
||||
if data_ref.is_null() {
|
||||
Err(TCFType::wrap_under_create_rule(error))
|
||||
} else {
|
||||
Ok(TCFType::wrap_under_create_rule(data_ref))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait for all subclasses of [`CFPropertyList`].
|
||||
///
|
||||
/// [`CFPropertyList`]: struct.CFPropertyList.html
|
||||
pub trait CFPropertyListSubClass: TCFType {
|
||||
/// Create an instance of the superclass type [`CFPropertyList`] for this instance.
|
||||
///
|
||||
/// [`CFPropertyList`]: struct.CFPropertyList.html
|
||||
#[inline]
|
||||
fn to_CFPropertyList(&self) -> CFPropertyList {
|
||||
unsafe { CFPropertyList::wrap_under_get_rule(self.as_concrete_TypeRef().as_void_ptr()) }
|
||||
}
|
||||
|
||||
/// Equal to [`to_CFPropertyList`], but consumes self and avoids changing the reference count.
|
||||
///
|
||||
/// [`to_CFPropertyList`]: #method.to_CFPropertyList
|
||||
#[inline]
|
||||
fn into_CFPropertyList(self) -> CFPropertyList
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
let reference = self.as_concrete_TypeRef().as_void_ptr();
|
||||
mem::forget(self);
|
||||
unsafe { CFPropertyList::wrap_under_create_rule(reference) }
|
||||
}
|
||||
}
|
||||
|
||||
impl CFPropertyListSubClass for crate::data::CFData {}
|
||||
impl CFPropertyListSubClass for crate::string::CFString {}
|
||||
impl CFPropertyListSubClass for crate::array::CFArray {}
|
||||
impl CFPropertyListSubClass for crate::dictionary::CFDictionary {}
|
||||
impl CFPropertyListSubClass for crate::date::CFDate {}
|
||||
impl CFPropertyListSubClass for crate::boolean::CFBoolean {}
|
||||
impl CFPropertyListSubClass for crate::number::CFNumber {}
|
||||
|
||||
declare_TCFType! {
|
||||
/// A CFPropertyList struct. This is superclass to [`CFData`], [`CFString`], [`CFArray`],
|
||||
/// [`CFDictionary`], [`CFDate`], [`CFBoolean`], and [`CFNumber`].
|
||||
///
|
||||
/// This superclass type does not have its own `CFTypeID`, instead each instance has the `CFTypeID`
|
||||
/// of the subclass it is an instance of. Thus, this type cannot implement the [`TCFType`] trait,
|
||||
/// since it cannot implement the static [`TCFType::type_id()`] method.
|
||||
///
|
||||
/// [`CFData`]: ../data/struct.CFData.html
|
||||
/// [`CFString`]: ../string/struct.CFString.html
|
||||
/// [`CFArray`]: ../array/struct.CFArray.html
|
||||
/// [`CFDictionary`]: ../dictionary/struct.CFDictionary.html
|
||||
/// [`CFDate`]: ../date/struct.CFDate.html
|
||||
/// [`CFBoolean`]: ../boolean/struct.CFBoolean.html
|
||||
/// [`CFNumber`]: ../number/struct.CFNumber.html
|
||||
/// [`TCFType`]: ../base/trait.TCFType.html
|
||||
/// [`TCFType::type_id()`]: ../base/trait.TCFType.html#method.type_of
|
||||
CFPropertyList, CFPropertyListRef
|
||||
}
|
||||
|
||||
impl_CFTypeDescription!(CFPropertyList);
|
||||
|
||||
impl CFPropertyList {
|
||||
#[inline]
|
||||
pub fn as_concrete_TypeRef(&self) -> CFPropertyListRef {
|
||||
self.0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn wrap_under_get_rule(reference: CFPropertyListRef) -> CFPropertyList {
|
||||
assert!(!reference.is_null(), "Attempted to create a NULL object.");
|
||||
let reference = CFRetain(reference);
|
||||
CFPropertyList(reference)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn as_CFType(&self) -> CFType {
|
||||
unsafe { CFType::wrap_under_get_rule(self.as_CFTypeRef()) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn into_CFType(self) -> CFType
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
let reference = self.as_CFTypeRef();
|
||||
mem::forget(self);
|
||||
unsafe { TCFType::wrap_under_create_rule(reference) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn as_CFTypeRef(&self) -> ::core_foundation_sys::base::CFTypeRef {
|
||||
self.as_concrete_TypeRef()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn wrap_under_create_rule(obj: CFPropertyListRef) -> CFPropertyList {
|
||||
assert!(!obj.is_null(), "Attempted to create a NULL object.");
|
||||
CFPropertyList(obj)
|
||||
}
|
||||
|
||||
/// Returns the reference count of the object. It is unwise to do anything other than test
|
||||
/// whether the return value of this method is greater than zero.
|
||||
#[inline]
|
||||
pub fn retain_count(&self) -> CFIndex {
|
||||
unsafe { CFGetRetainCount(self.as_CFTypeRef()) }
|
||||
}
|
||||
|
||||
/// Returns the type ID of this object. Will be one of `CFData`, `CFString`, `CFArray`,
|
||||
/// `CFDictionary`, `CFDate`, `CFBoolean`, or `CFNumber`.
|
||||
#[inline]
|
||||
pub fn type_of(&self) -> CFTypeID {
|
||||
unsafe { CFGetTypeID(self.as_CFTypeRef()) }
|
||||
}
|
||||
|
||||
/// Writes a debugging version of this object on standard error.
|
||||
pub fn show(&self) {
|
||||
unsafe { CFShow(self.as_CFTypeRef()) }
|
||||
}
|
||||
|
||||
/// Returns `true` if this value is an instance of another type.
|
||||
#[inline]
|
||||
pub fn instance_of<OtherCFType: TCFType>(&self) -> bool {
|
||||
self.type_of() == OtherCFType::type_id()
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for CFPropertyList {
|
||||
#[inline]
|
||||
fn clone(&self) -> CFPropertyList {
|
||||
unsafe { CFPropertyList::wrap_under_get_rule(self.0) }
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for CFPropertyList {
|
||||
#[inline]
|
||||
fn eq(&self, other: &CFPropertyList) -> bool {
|
||||
self.as_CFType().eq(&other.as_CFType())
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for CFPropertyList {}
|
||||
|
||||
impl CFPropertyList {
|
||||
/// Try to downcast the [`CFPropertyList`] to a subclass. Checking if the instance is the
|
||||
/// correct subclass happens at runtime and `None` is returned if it is not the correct type.
|
||||
/// Works similar to [`Box::downcast`] and [`CFType::downcast`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # use core_foundation::string::CFString;
|
||||
/// # use core_foundation::propertylist::{CFPropertyList, CFPropertyListSubClass};
|
||||
/// #
|
||||
/// // Create a string.
|
||||
/// let string: CFString = CFString::from_static_string("FooBar");
|
||||
/// // Cast it up to a property list.
|
||||
/// let propertylist: CFPropertyList = string.to_CFPropertyList();
|
||||
/// // Cast it down again.
|
||||
/// assert_eq!(propertylist.downcast::<CFString>().unwrap().to_string(), "FooBar");
|
||||
/// ```
|
||||
///
|
||||
/// [`CFPropertyList`]: struct.CFPropertyList.html
|
||||
/// [`Box::downcast`]: https://doc.rust-lang.org/std/boxed/struct.Box.html#method.downcast
|
||||
pub fn downcast<T: CFPropertyListSubClass>(&self) -> Option<T> {
|
||||
if self.instance_of::<T>() {
|
||||
unsafe {
|
||||
let subclass_ref = T::Ref::from_void_ptr(self.0);
|
||||
Some(T::wrap_under_get_rule(subclass_ref))
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Similar to [`downcast`], but consumes self and can thus avoid touching the retain count.
|
||||
///
|
||||
/// [`downcast`]: #method.downcast
|
||||
pub fn downcast_into<T: CFPropertyListSubClass>(self) -> Option<T> {
|
||||
if self.instance_of::<T>() {
|
||||
unsafe {
|
||||
let subclass_ref = T::Ref::from_void_ptr(self.0);
|
||||
mem::forget(self);
|
||||
Some(T::wrap_under_create_rule(subclass_ref))
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod test {
|
||||
use super::*;
|
||||
use crate::boolean::CFBoolean;
|
||||
use crate::string::CFString;
|
||||
|
||||
#[test]
|
||||
fn test_property_list_serialization() {
|
||||
use super::*;
|
||||
use crate::base::{CFEqual, TCFType};
|
||||
use crate::boolean::CFBoolean;
|
||||
use crate::dictionary::CFDictionary;
|
||||
use crate::number::CFNumber;
|
||||
use crate::string::CFString;
|
||||
|
||||
let bar = CFString::from_static_string("Bar");
|
||||
let baz = CFString::from_static_string("Baz");
|
||||
let boo = CFString::from_static_string("Boo");
|
||||
let foo = CFString::from_static_string("Foo");
|
||||
let tru = CFBoolean::true_value();
|
||||
let n42 = CFNumber::from(1i64 << 33);
|
||||
|
||||
let dict1 = CFDictionary::from_CFType_pairs(&[
|
||||
(bar.as_CFType(), boo.as_CFType()),
|
||||
(baz.as_CFType(), tru.as_CFType()),
|
||||
(foo.as_CFType(), n42.as_CFType()),
|
||||
]);
|
||||
|
||||
let data = create_data(dict1.as_CFTypeRef(), kCFPropertyListXMLFormat_v1_0).unwrap();
|
||||
let (dict2, _) = create_with_data(data, kCFPropertyListImmutable).unwrap();
|
||||
unsafe {
|
||||
assert_eq!(CFEqual(dict1.as_CFTypeRef(), dict2), 1);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_propertylist_retain_count() {
|
||||
let string = CFString::from_static_string("alongerstring");
|
||||
assert_eq!(string.retain_count(), 1);
|
||||
|
||||
let propertylist = string.to_CFPropertyList();
|
||||
assert_eq!(string.retain_count(), 2);
|
||||
assert_eq!(propertylist.retain_count(), 2);
|
||||
|
||||
mem::drop(string);
|
||||
assert_eq!(propertylist.retain_count(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn downcast_string() {
|
||||
let propertylist = CFString::from_static_string("Bar").to_CFPropertyList();
|
||||
assert_eq!(
|
||||
propertylist.downcast::<CFString>().unwrap().to_string(),
|
||||
"Bar"
|
||||
);
|
||||
assert!(propertylist.downcast::<CFBoolean>().is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn downcast_boolean() {
|
||||
let propertylist = CFBoolean::true_value().to_CFPropertyList();
|
||||
assert!(propertylist.downcast::<CFBoolean>().is_some());
|
||||
assert!(propertylist.downcast::<CFString>().is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn downcast_into_fail() {
|
||||
let string = CFString::from_static_string("alongerstring");
|
||||
let propertylist = string.to_CFPropertyList();
|
||||
assert_eq!(string.retain_count(), 2);
|
||||
|
||||
assert!(propertylist.downcast_into::<CFBoolean>().is_none());
|
||||
assert_eq!(string.retain_count(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn downcast_into() {
|
||||
let string = CFString::from_static_string("alongerstring");
|
||||
let propertylist = string.to_CFPropertyList();
|
||||
assert_eq!(string.retain_count(), 2);
|
||||
|
||||
let string2 = propertylist.downcast_into::<CFString>().unwrap();
|
||||
assert_eq!(string2.to_string(), "alongerstring");
|
||||
assert_eq!(string2.retain_count(), 2);
|
||||
}
|
||||
}
|
||||
304
third-party/vendor/core-foundation/src/runloop.rs
vendored
Normal file
304
third-party/vendor/core-foundation/src/runloop.rs
vendored
Normal file
|
|
@ -0,0 +1,304 @@
|
|||
// 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 core_foundation_sys::base::CFIndex;
|
||||
use core_foundation_sys::base::{kCFAllocatorDefault, CFOptionFlags};
|
||||
pub use core_foundation_sys::runloop::*;
|
||||
use core_foundation_sys::string::CFStringRef;
|
||||
|
||||
use crate::base::TCFType;
|
||||
use crate::date::{CFAbsoluteTime, CFTimeInterval};
|
||||
use crate::filedescriptor::CFFileDescriptor;
|
||||
use crate::string::CFString;
|
||||
|
||||
pub type CFRunLoopMode = CFStringRef;
|
||||
|
||||
declare_TCFType!(CFRunLoop, CFRunLoopRef);
|
||||
impl_TCFType!(CFRunLoop, CFRunLoopRef, CFRunLoopGetTypeID);
|
||||
impl_CFTypeDescription!(CFRunLoop);
|
||||
|
||||
// https://github.com/servo/core-foundation-rs/issues/550
|
||||
unsafe impl Send for CFRunLoop {}
|
||||
unsafe impl Sync for CFRunLoop {}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
pub enum CFRunLoopRunResult {
|
||||
Finished = 1,
|
||||
Stopped = 2,
|
||||
TimedOut = 3,
|
||||
HandledSource = 4,
|
||||
}
|
||||
|
||||
impl CFRunLoop {
|
||||
pub fn get_current() -> CFRunLoop {
|
||||
unsafe {
|
||||
let run_loop_ref = CFRunLoopGetCurrent();
|
||||
TCFType::wrap_under_get_rule(run_loop_ref)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_main() -> CFRunLoop {
|
||||
unsafe {
|
||||
let run_loop_ref = CFRunLoopGetMain();
|
||||
TCFType::wrap_under_get_rule(run_loop_ref)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run_current() {
|
||||
unsafe {
|
||||
CFRunLoopRun();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run_in_mode(
|
||||
mode: CFStringRef,
|
||||
duration: std::time::Duration,
|
||||
return_after_source_handled: bool,
|
||||
) -> CFRunLoopRunResult {
|
||||
let seconds = duration.as_secs_f64();
|
||||
let return_after_source_handled = if return_after_source_handled { 1 } else { 0 };
|
||||
|
||||
unsafe {
|
||||
match CFRunLoopRunInMode(mode, seconds, return_after_source_handled) {
|
||||
2 => CFRunLoopRunResult::Stopped,
|
||||
3 => CFRunLoopRunResult::TimedOut,
|
||||
4 => CFRunLoopRunResult::HandledSource,
|
||||
_ => CFRunLoopRunResult::Finished,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn stop(&self) {
|
||||
unsafe {
|
||||
CFRunLoopStop(self.0);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn current_mode(&self) -> Option<String> {
|
||||
unsafe {
|
||||
let string_ref = CFRunLoopCopyCurrentMode(self.0);
|
||||
if string_ref.is_null() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let cf_string: CFString = TCFType::wrap_under_create_rule(string_ref);
|
||||
Some(cf_string.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn contains_timer(&self, timer: &CFRunLoopTimer, mode: CFRunLoopMode) -> bool {
|
||||
unsafe { CFRunLoopContainsTimer(self.0, timer.0, mode) != 0 }
|
||||
}
|
||||
|
||||
pub fn add_timer(&self, timer: &CFRunLoopTimer, mode: CFRunLoopMode) {
|
||||
unsafe {
|
||||
CFRunLoopAddTimer(self.0, timer.0, mode);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn remove_timer(&self, timer: &CFRunLoopTimer, mode: CFRunLoopMode) {
|
||||
unsafe {
|
||||
CFRunLoopRemoveTimer(self.0, timer.0, mode);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn contains_source(&self, source: &CFRunLoopSource, mode: CFRunLoopMode) -> bool {
|
||||
unsafe { CFRunLoopContainsSource(self.0, source.0, mode) != 0 }
|
||||
}
|
||||
|
||||
pub fn add_source(&self, source: &CFRunLoopSource, mode: CFRunLoopMode) {
|
||||
unsafe {
|
||||
CFRunLoopAddSource(self.0, source.0, mode);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn remove_source(&self, source: &CFRunLoopSource, mode: CFRunLoopMode) {
|
||||
unsafe {
|
||||
CFRunLoopRemoveSource(self.0, source.0, mode);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn contains_observer(&self, observer: &CFRunLoopObserver, mode: CFRunLoopMode) -> bool {
|
||||
unsafe { CFRunLoopContainsObserver(self.0, observer.0, mode) != 0 }
|
||||
}
|
||||
|
||||
pub fn add_observer(&self, observer: &CFRunLoopObserver, mode: CFRunLoopMode) {
|
||||
unsafe {
|
||||
CFRunLoopAddObserver(self.0, observer.0, mode);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn remove_observer(&self, observer: &CFRunLoopObserver, mode: CFRunLoopMode) {
|
||||
unsafe {
|
||||
CFRunLoopRemoveObserver(self.0, observer.0, mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
declare_TCFType!(CFRunLoopTimer, CFRunLoopTimerRef);
|
||||
impl_TCFType!(CFRunLoopTimer, CFRunLoopTimerRef, CFRunLoopTimerGetTypeID);
|
||||
|
||||
impl CFRunLoopTimer {
|
||||
pub fn new(
|
||||
fireDate: CFAbsoluteTime,
|
||||
interval: CFTimeInterval,
|
||||
flags: CFOptionFlags,
|
||||
order: CFIndex,
|
||||
callout: CFRunLoopTimerCallBack,
|
||||
context: *mut CFRunLoopTimerContext,
|
||||
) -> CFRunLoopTimer {
|
||||
unsafe {
|
||||
let timer_ref = CFRunLoopTimerCreate(
|
||||
kCFAllocatorDefault,
|
||||
fireDate,
|
||||
interval,
|
||||
flags,
|
||||
order,
|
||||
callout,
|
||||
context,
|
||||
);
|
||||
TCFType::wrap_under_create_rule(timer_ref)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
declare_TCFType!(CFRunLoopSource, CFRunLoopSourceRef);
|
||||
impl_TCFType!(
|
||||
CFRunLoopSource,
|
||||
CFRunLoopSourceRef,
|
||||
CFRunLoopSourceGetTypeID
|
||||
);
|
||||
|
||||
impl CFRunLoopSource {
|
||||
pub fn from_file_descriptor(fd: &CFFileDescriptor, order: CFIndex) -> Option<CFRunLoopSource> {
|
||||
fd.to_run_loop_source(order)
|
||||
}
|
||||
}
|
||||
|
||||
declare_TCFType!(CFRunLoopObserver, CFRunLoopObserverRef);
|
||||
impl_TCFType!(
|
||||
CFRunLoopObserver,
|
||||
CFRunLoopObserverRef,
|
||||
CFRunLoopObserverGetTypeID
|
||||
);
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::base::Boolean;
|
||||
use crate::date::{CFAbsoluteTime, CFDate};
|
||||
use std::mem;
|
||||
use std::os::raw::c_void;
|
||||
use std::ptr::null_mut;
|
||||
use std::sync::mpsc;
|
||||
use std::thread::spawn;
|
||||
use std::time::Duration;
|
||||
|
||||
#[test]
|
||||
fn wait_200_milliseconds() {
|
||||
let run_loop = CFRunLoop::get_current();
|
||||
|
||||
let now = CFDate::now().abs_time();
|
||||
let (elapsed_tx, elapsed_rx) = mpsc::channel();
|
||||
let mut info = Info {
|
||||
start_time: now,
|
||||
elapsed_tx,
|
||||
};
|
||||
let mut context = CFRunLoopTimerContext {
|
||||
version: 0,
|
||||
info: &mut info as *mut _ as *mut c_void,
|
||||
retain: None,
|
||||
release: None,
|
||||
copyDescription: None,
|
||||
};
|
||||
|
||||
let run_loop_timer =
|
||||
CFRunLoopTimer::new(now + 0.20f64, 0f64, 0, 0, timer_popped, &mut context);
|
||||
unsafe {
|
||||
run_loop.add_timer(&run_loop_timer, kCFRunLoopDefaultMode);
|
||||
}
|
||||
CFRunLoop::run_current();
|
||||
let elapsed = elapsed_rx.try_recv().unwrap();
|
||||
println!("wait_200_milliseconds, elapsed: {}", elapsed);
|
||||
assert!(elapsed > 0.19 && elapsed < 0.35);
|
||||
}
|
||||
|
||||
struct Info {
|
||||
start_time: CFAbsoluteTime,
|
||||
elapsed_tx: mpsc::Sender<f64>,
|
||||
}
|
||||
|
||||
extern "C" fn timer_popped(_timer: CFRunLoopTimerRef, raw_info: *mut c_void) {
|
||||
let info: *mut Info = unsafe { mem::transmute(raw_info) };
|
||||
let now = CFDate::now().abs_time();
|
||||
let elapsed = now - unsafe { (*info).start_time };
|
||||
let _ = unsafe { (*info).elapsed_tx.send(elapsed) };
|
||||
CFRunLoop::get_current().stop();
|
||||
}
|
||||
|
||||
extern "C" fn observe(_: CFRunLoopObserverRef, _: CFRunLoopActivity, context: *mut c_void) {
|
||||
let tx: &mpsc::Sender<CFRunLoop> = unsafe { &*(context as *const _) };
|
||||
let _ = tx.send(CFRunLoop::get_current());
|
||||
}
|
||||
|
||||
extern "C" fn observe_timer_popped(_: CFRunLoopTimerRef, _: *mut c_void) {
|
||||
panic!("timer popped unexpectedly");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn observe_runloop() {
|
||||
let (tx, rx) = mpsc::channel();
|
||||
spawn(move || {
|
||||
let mut context = CFRunLoopObserverContext {
|
||||
version: 0,
|
||||
info: &tx as *const _ as *mut c_void,
|
||||
retain: None,
|
||||
release: None,
|
||||
copyDescription: None,
|
||||
};
|
||||
|
||||
let observer = unsafe {
|
||||
CFRunLoopObserver::wrap_under_create_rule(CFRunLoopObserverCreate(
|
||||
kCFAllocatorDefault,
|
||||
kCFRunLoopEntry,
|
||||
false as Boolean,
|
||||
0,
|
||||
observe,
|
||||
&mut context,
|
||||
))
|
||||
};
|
||||
|
||||
let runloop = CFRunLoop::get_current();
|
||||
runloop.add_observer(&observer, unsafe { kCFRunLoopDefaultMode });
|
||||
|
||||
let timer = CFRunLoopTimer::new(
|
||||
CFDate::now().abs_time() + 1f64,
|
||||
0f64,
|
||||
0,
|
||||
0,
|
||||
observe_timer_popped,
|
||||
null_mut(),
|
||||
);
|
||||
runloop.add_timer(&timer, unsafe { kCFRunLoopDefaultMode });
|
||||
|
||||
let result = unsafe {
|
||||
CFRunLoop::run_in_mode(kCFRunLoopDefaultMode, Duration::from_secs(10), false)
|
||||
};
|
||||
|
||||
assert_eq!(result, CFRunLoopRunResult::Stopped);
|
||||
|
||||
drop(tx);
|
||||
});
|
||||
|
||||
let runloop: CFRunLoop = rx.recv().unwrap();
|
||||
runloop.stop();
|
||||
}
|
||||
}
|
||||
61
third-party/vendor/core-foundation/src/set.rs
vendored
Normal file
61
third-party/vendor/core-foundation/src/set.rs
vendored
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
// 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.
|
||||
|
||||
//! An immutable bag of elements.
|
||||
|
||||
use core_foundation_sys::base::{kCFAllocatorDefault, CFRelease, CFTypeRef};
|
||||
pub use core_foundation_sys::set::*;
|
||||
|
||||
use crate::base::{CFIndexConvertible, TCFType};
|
||||
|
||||
use std::marker::PhantomData;
|
||||
use std::os::raw::c_void;
|
||||
|
||||
/// An immutable bag of elements.
|
||||
pub struct CFSet<T = *const c_void>(CFSetRef, PhantomData<T>);
|
||||
|
||||
impl<T> Drop for CFSet<T> {
|
||||
fn drop(&mut self) {
|
||||
unsafe { CFRelease(self.as_CFTypeRef()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl_TCFType!(CFSet<T>, CFSetRef, CFSetGetTypeID);
|
||||
impl_CFTypeDescription!(CFSet);
|
||||
|
||||
impl CFSet {
|
||||
/// Creates a new set from a list of `CFType` instances.
|
||||
pub fn from_slice<T>(elems: &[T]) -> CFSet<T>
|
||||
where
|
||||
T: TCFType,
|
||||
{
|
||||
unsafe {
|
||||
let elems: Vec<CFTypeRef> = elems.iter().map(|elem| elem.as_CFTypeRef()).collect();
|
||||
let set_ref = CFSetCreate(
|
||||
kCFAllocatorDefault,
|
||||
elems.as_ptr(),
|
||||
elems.len().to_CFIndex(),
|
||||
&kCFTypeSetCallBacks,
|
||||
);
|
||||
TCFType::wrap_under_create_rule(set_ref)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> CFSet<T> {
|
||||
/// Get the number of elements in the `CFSet`.
|
||||
pub fn len(&self) -> usize {
|
||||
unsafe { CFSetGetCount(self.0) as usize }
|
||||
}
|
||||
|
||||
/// Returns `true` if the set contains no elements.
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.len() == 0
|
||||
}
|
||||
}
|
||||
209
third-party/vendor/core-foundation/src/string.rs
vendored
Normal file
209
third-party/vendor/core-foundation/src/string.rs
vendored
Normal file
|
|
@ -0,0 +1,209 @@
|
|||
// 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.
|
||||
|
||||
//! Immutable strings.
|
||||
|
||||
pub use core_foundation_sys::string::*;
|
||||
|
||||
use crate::base::{CFIndexConvertible, TCFType};
|
||||
|
||||
use core_foundation_sys::base::{kCFAllocatorDefault, kCFAllocatorNull};
|
||||
use core_foundation_sys::base::{Boolean, CFIndex, CFRange};
|
||||
use std::borrow::Cow;
|
||||
use std::ffi::CStr;
|
||||
use std::fmt;
|
||||
use std::ptr;
|
||||
use std::str::{self, FromStr};
|
||||
|
||||
declare_TCFType! {
|
||||
/// An immutable string in one of a variety of encodings.
|
||||
CFString, CFStringRef
|
||||
}
|
||||
impl_TCFType!(CFString, CFStringRef, CFStringGetTypeID);
|
||||
|
||||
impl FromStr for CFString {
|
||||
type Err = ();
|
||||
|
||||
/// See also [`CFString::new()`] for a variant of this which does not return a `Result`.
|
||||
#[inline]
|
||||
fn from_str(string: &str) -> Result<CFString, ()> {
|
||||
Ok(CFString::new(string))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a str> for CFString {
|
||||
#[inline]
|
||||
fn from(string: &'a str) -> CFString {
|
||||
CFString::new(string)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a CFString> for Cow<'a, str> {
|
||||
fn from(cf_str: &'a CFString) -> Cow<'a, str> {
|
||||
unsafe {
|
||||
// Do this without allocating if we can get away with it
|
||||
let c_string = CFStringGetCStringPtr(cf_str.0, kCFStringEncodingUTF8);
|
||||
if !c_string.is_null() {
|
||||
let c_str = CStr::from_ptr(c_string);
|
||||
Cow::Borrowed(str::from_utf8_unchecked(c_str.to_bytes()))
|
||||
} else {
|
||||
let char_len = cf_str.char_len();
|
||||
|
||||
// First, ask how big the buffer ought to be.
|
||||
let mut bytes_required: CFIndex = 0;
|
||||
CFStringGetBytes(
|
||||
cf_str.0,
|
||||
CFRange {
|
||||
location: 0,
|
||||
length: char_len,
|
||||
},
|
||||
kCFStringEncodingUTF8,
|
||||
0,
|
||||
false as Boolean,
|
||||
ptr::null_mut(),
|
||||
0,
|
||||
&mut bytes_required,
|
||||
);
|
||||
|
||||
// Then, allocate the buffer and actually copy.
|
||||
let mut buffer = vec![b'\x00'; bytes_required as usize];
|
||||
|
||||
let mut bytes_used: CFIndex = 0;
|
||||
let chars_written = CFStringGetBytes(
|
||||
cf_str.0,
|
||||
CFRange {
|
||||
location: 0,
|
||||
length: char_len,
|
||||
},
|
||||
kCFStringEncodingUTF8,
|
||||
0,
|
||||
false as Boolean,
|
||||
buffer.as_mut_ptr(),
|
||||
buffer.len().to_CFIndex(),
|
||||
&mut bytes_used,
|
||||
);
|
||||
assert_eq!(chars_written, char_len);
|
||||
|
||||
// This is dangerous; we over-allocate and null-terminate the string (during
|
||||
// initialization).
|
||||
assert_eq!(bytes_used, buffer.len().to_CFIndex());
|
||||
Cow::Owned(String::from_utf8_unchecked(buffer))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for CFString {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt.write_str(&Cow::from(self))
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for CFString {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "\"{}\"", self)
|
||||
}
|
||||
}
|
||||
|
||||
impl CFString {
|
||||
/// Creates a new `CFString` instance from a Rust string.
|
||||
#[inline]
|
||||
pub fn new(string: &str) -> CFString {
|
||||
unsafe {
|
||||
let string_ref = CFStringCreateWithBytes(
|
||||
kCFAllocatorDefault,
|
||||
string.as_ptr(),
|
||||
string.len().to_CFIndex(),
|
||||
kCFStringEncodingUTF8,
|
||||
false as Boolean,
|
||||
);
|
||||
CFString::wrap_under_create_rule(string_ref)
|
||||
}
|
||||
}
|
||||
|
||||
/// Like `CFString::new`, but references a string that can be used as a backing store
|
||||
/// by virtue of being statically allocated.
|
||||
#[inline]
|
||||
pub fn from_static_string(string: &'static str) -> CFString {
|
||||
unsafe {
|
||||
let string_ref = CFStringCreateWithBytesNoCopy(
|
||||
kCFAllocatorDefault,
|
||||
string.as_ptr(),
|
||||
string.len().to_CFIndex(),
|
||||
kCFStringEncodingUTF8,
|
||||
false as Boolean,
|
||||
kCFAllocatorNull,
|
||||
);
|
||||
TCFType::wrap_under_create_rule(string_ref)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the number of characters in the string.
|
||||
#[inline]
|
||||
pub fn char_len(&self) -> CFIndex {
|
||||
unsafe { CFStringGetLength(self.0) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> PartialEq<&'a str> for CFString {
|
||||
fn eq(&self, other: &&str) -> bool {
|
||||
unsafe {
|
||||
let temp = CFStringCreateWithBytesNoCopy(
|
||||
kCFAllocatorDefault,
|
||||
other.as_ptr(),
|
||||
other.len().to_CFIndex(),
|
||||
kCFStringEncodingUTF8,
|
||||
false as Boolean,
|
||||
kCFAllocatorNull,
|
||||
);
|
||||
self.eq(&CFString::wrap_under_create_rule(temp))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> PartialEq<CFString> for &'a str {
|
||||
#[inline]
|
||||
fn eq(&self, other: &CFString) -> bool {
|
||||
other.eq(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq<CFString> for String {
|
||||
#[inline]
|
||||
fn eq(&self, other: &CFString) -> bool {
|
||||
other.eq(&self.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq<String> for CFString {
|
||||
#[inline]
|
||||
fn eq(&self, other: &String) -> bool {
|
||||
self.eq(&other.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn str_cmp() {
|
||||
let cfstr = CFString::new("hello");
|
||||
assert_eq!("hello", cfstr);
|
||||
assert_eq!(cfstr, "hello");
|
||||
assert_ne!(cfstr, "wrong");
|
||||
assert_ne!("wrong", cfstr);
|
||||
let hello = String::from("hello");
|
||||
assert_eq!(hello, cfstr);
|
||||
assert_eq!(cfstr, hello);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn string_and_back() {
|
||||
let original = "The quick brown fox jumped over the slow lazy dog.";
|
||||
let cfstr = CFString::from_static_string(original);
|
||||
let converted = cfstr.to_string();
|
||||
assert_eq!(converted, original);
|
||||
}
|
||||
99
third-party/vendor/core-foundation/src/timezone.rs
vendored
Normal file
99
third-party/vendor/core-foundation/src/timezone.rs
vendored
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
// 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.
|
||||
|
||||
//! Core Foundation time zone objects.
|
||||
|
||||
use core_foundation_sys::base::kCFAllocatorDefault;
|
||||
pub use core_foundation_sys::timezone::*;
|
||||
|
||||
use crate::base::TCFType;
|
||||
use crate::date::{CFDate, CFTimeInterval};
|
||||
use crate::string::CFString;
|
||||
|
||||
#[cfg(feature = "with-chrono")]
|
||||
use chrono::{FixedOffset, NaiveDateTime};
|
||||
|
||||
declare_TCFType! {
|
||||
/// A time zone.
|
||||
CFTimeZone, CFTimeZoneRef
|
||||
}
|
||||
impl_TCFType!(CFTimeZone, CFTimeZoneRef, CFTimeZoneGetTypeID);
|
||||
impl_CFTypeDescription!(CFTimeZone);
|
||||
|
||||
impl Default for CFTimeZone {
|
||||
fn default() -> CFTimeZone {
|
||||
unsafe {
|
||||
let tz_ref = CFTimeZoneCopyDefault();
|
||||
TCFType::wrap_under_create_rule(tz_ref)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CFTimeZone {
|
||||
#[inline]
|
||||
pub fn new(interval: CFTimeInterval) -> CFTimeZone {
|
||||
unsafe {
|
||||
let tz_ref = CFTimeZoneCreateWithTimeIntervalFromGMT(kCFAllocatorDefault, interval);
|
||||
TCFType::wrap_under_create_rule(tz_ref)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn system() -> CFTimeZone {
|
||||
unsafe {
|
||||
let tz_ref = CFTimeZoneCopySystem();
|
||||
TCFType::wrap_under_create_rule(tz_ref)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn seconds_from_gmt(&self, date: CFDate) -> CFTimeInterval {
|
||||
unsafe { CFTimeZoneGetSecondsFromGMT(self.0, date.abs_time()) }
|
||||
}
|
||||
|
||||
#[cfg(feature = "with-chrono")]
|
||||
pub fn offset_at_date(&self, date: NaiveDateTime) -> FixedOffset {
|
||||
let date = CFDate::from_naive_utc(date);
|
||||
FixedOffset::east(self.seconds_from_gmt(date) as i32)
|
||||
}
|
||||
|
||||
#[cfg(feature = "with-chrono")]
|
||||
pub fn from_offset(offset: FixedOffset) -> CFTimeZone {
|
||||
CFTimeZone::new(offset.local_minus_utc() as f64)
|
||||
}
|
||||
|
||||
/// The timezone database ID that identifies the time zone. E.g. `"America/Los_Angeles" `or
|
||||
/// `"Europe/Paris"`.
|
||||
pub fn name(&self) -> CFString {
|
||||
unsafe { CFString::wrap_under_get_rule(CFTimeZoneGetName(self.0)) }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::CFTimeZone;
|
||||
|
||||
#[cfg(feature = "with-chrono")]
|
||||
use chrono::{FixedOffset, NaiveDateTime};
|
||||
|
||||
#[test]
|
||||
fn timezone_comparison() {
|
||||
let system = CFTimeZone::system();
|
||||
let default = CFTimeZone::default();
|
||||
assert_eq!(system, default);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "with-chrono")]
|
||||
fn timezone_chrono_conversion() {
|
||||
let offset = FixedOffset::west(28800);
|
||||
let tz = CFTimeZone::from_offset(offset);
|
||||
let converted = tz.offset_at_date(NaiveDateTime::from_timestamp(0, 0));
|
||||
assert_eq!(offset, converted);
|
||||
}
|
||||
}
|
||||
184
third-party/vendor/core-foundation/src/url.rs
vendored
Normal file
184
third-party/vendor/core-foundation/src/url.rs
vendored
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
// 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.
|
||||
|
||||
//! A URL type for Core Foundation.
|
||||
|
||||
pub use core_foundation_sys::url::*;
|
||||
|
||||
use crate::base::{CFIndex, TCFType};
|
||||
use crate::string::CFString;
|
||||
|
||||
use core_foundation_sys::base::{kCFAllocatorDefault, Boolean};
|
||||
use std::fmt;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::ptr;
|
||||
|
||||
use libc::{c_char, strlen, PATH_MAX};
|
||||
|
||||
#[cfg(unix)]
|
||||
use std::ffi::OsStr;
|
||||
#[cfg(unix)]
|
||||
use std::os::unix::ffi::OsStrExt;
|
||||
|
||||
declare_TCFType!(CFURL, CFURLRef);
|
||||
impl_TCFType!(CFURL, CFURLRef, CFURLGetTypeID);
|
||||
|
||||
impl fmt::Debug for CFURL {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
unsafe {
|
||||
let string: CFString = TCFType::wrap_under_get_rule(CFURLGetString(self.0));
|
||||
write!(f, "{}", string)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CFURL {
|
||||
pub fn from_path<P: AsRef<Path>>(path: P, isDirectory: bool) -> Option<CFURL> {
|
||||
let path_bytes;
|
||||
#[cfg(unix)]
|
||||
{
|
||||
path_bytes = path.as_ref().as_os_str().as_bytes()
|
||||
}
|
||||
#[cfg(not(unix))]
|
||||
{
|
||||
// XXX: Getting non-valid UTF8 paths into CoreFoundation on Windows is going to be unpleasant
|
||||
// CFURLGetWideFileSystemRepresentation might help
|
||||
path_bytes = match path.as_ref().to_str() {
|
||||
Some(path) => path,
|
||||
None => return None,
|
||||
}
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let url_ref = CFURLCreateFromFileSystemRepresentation(
|
||||
ptr::null_mut(),
|
||||
path_bytes.as_ptr(),
|
||||
path_bytes.len() as CFIndex,
|
||||
isDirectory as u8,
|
||||
);
|
||||
if url_ref.is_null() {
|
||||
return None;
|
||||
}
|
||||
Some(TCFType::wrap_under_create_rule(url_ref))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_file_system_path(
|
||||
filePath: CFString,
|
||||
pathStyle: CFURLPathStyle,
|
||||
isDirectory: bool,
|
||||
) -> CFURL {
|
||||
unsafe {
|
||||
let url_ref = CFURLCreateWithFileSystemPath(
|
||||
kCFAllocatorDefault,
|
||||
filePath.as_concrete_TypeRef(),
|
||||
pathStyle,
|
||||
isDirectory as u8,
|
||||
);
|
||||
TCFType::wrap_under_create_rule(url_ref)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
pub fn to_path(&self) -> Option<PathBuf> {
|
||||
// implementing this on Windows is more complicated because of the different OsStr representation
|
||||
unsafe {
|
||||
let mut buf = [0u8; PATH_MAX as usize];
|
||||
let result = CFURLGetFileSystemRepresentation(
|
||||
self.0,
|
||||
true as Boolean,
|
||||
buf.as_mut_ptr(),
|
||||
buf.len() as CFIndex,
|
||||
);
|
||||
if result == false as Boolean {
|
||||
return None;
|
||||
}
|
||||
let len = strlen(buf.as_ptr() as *const c_char);
|
||||
let path = OsStr::from_bytes(&buf[0..len]);
|
||||
Some(PathBuf::from(path))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_string(&self) -> CFString {
|
||||
unsafe { TCFType::wrap_under_get_rule(CFURLGetString(self.0)) }
|
||||
}
|
||||
|
||||
pub fn get_file_system_path(&self, pathStyle: CFURLPathStyle) -> CFString {
|
||||
unsafe {
|
||||
TCFType::wrap_under_create_rule(CFURLCopyFileSystemPath(
|
||||
self.as_concrete_TypeRef(),
|
||||
pathStyle,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn absolute(&self) -> CFURL {
|
||||
unsafe { TCFType::wrap_under_create_rule(CFURLCopyAbsoluteURL(self.as_concrete_TypeRef())) }
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn file_url_from_path() {
|
||||
let path = "/usr/local/foo/";
|
||||
let cfstr_path = CFString::from_static_string(path);
|
||||
let cfurl = CFURL::from_file_system_path(cfstr_path, kCFURLPOSIXPathStyle, true);
|
||||
assert_eq!(cfurl.get_string().to_string(), "file:///usr/local/foo/");
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
#[test]
|
||||
fn non_utf8() {
|
||||
use std::ffi::OsStr;
|
||||
let path = Path::new(OsStr::from_bytes(b"/\xC0/blame"));
|
||||
let cfurl = CFURL::from_path(path, false).unwrap();
|
||||
assert_eq!(cfurl.to_path().unwrap(), path);
|
||||
let len = unsafe { CFURLGetBytes(cfurl.as_concrete_TypeRef(), ptr::null_mut(), 0) };
|
||||
assert_eq!(len, 17);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn absolute_file_url() {
|
||||
use core_foundation_sys::url::CFURLCreateWithFileSystemPathRelativeToBase;
|
||||
use std::path::PathBuf;
|
||||
|
||||
let path = "/usr/local/foo";
|
||||
let file = "bar";
|
||||
|
||||
let cfstr_path = CFString::from_static_string(path);
|
||||
let cfstr_file = CFString::from_static_string(file);
|
||||
let cfurl_base = CFURL::from_file_system_path(cfstr_path, kCFURLPOSIXPathStyle, true);
|
||||
let cfurl_relative: CFURL = unsafe {
|
||||
let url_ref = CFURLCreateWithFileSystemPathRelativeToBase(
|
||||
kCFAllocatorDefault,
|
||||
cfstr_file.as_concrete_TypeRef(),
|
||||
kCFURLPOSIXPathStyle,
|
||||
false as u8,
|
||||
cfurl_base.as_concrete_TypeRef(),
|
||||
);
|
||||
TCFType::wrap_under_create_rule(url_ref)
|
||||
};
|
||||
|
||||
let mut absolute_path = PathBuf::from(path);
|
||||
absolute_path.push(file);
|
||||
|
||||
assert_eq!(
|
||||
cfurl_relative
|
||||
.get_file_system_path(kCFURLPOSIXPathStyle)
|
||||
.to_string(),
|
||||
file
|
||||
);
|
||||
assert_eq!(
|
||||
cfurl_relative
|
||||
.absolute()
|
||||
.get_file_system_path(kCFURLPOSIXPathStyle)
|
||||
.to_string(),
|
||||
absolute_path.to_str().unwrap()
|
||||
);
|
||||
}
|
||||
100
third-party/vendor/core-foundation/src/uuid.rs
vendored
Normal file
100
third-party/vendor/core-foundation/src/uuid.rs
vendored
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
// 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.
|
||||
|
||||
//! Core Foundation UUID objects.
|
||||
|
||||
#[cfg(feature = "with-uuid")]
|
||||
extern crate uuid;
|
||||
|
||||
use core_foundation_sys::base::kCFAllocatorDefault;
|
||||
pub use core_foundation_sys::uuid::*;
|
||||
|
||||
use crate::base::TCFType;
|
||||
|
||||
#[cfg(feature = "with-uuid")]
|
||||
use self::uuid::Uuid;
|
||||
|
||||
declare_TCFType! {
|
||||
/// A UUID.
|
||||
CFUUID, CFUUIDRef
|
||||
}
|
||||
impl_TCFType!(CFUUID, CFUUIDRef, CFUUIDGetTypeID);
|
||||
impl_CFTypeDescription!(CFUUID);
|
||||
|
||||
impl CFUUID {
|
||||
#[inline]
|
||||
pub fn new() -> CFUUID {
|
||||
unsafe {
|
||||
let uuid_ref = CFUUIDCreate(kCFAllocatorDefault);
|
||||
TCFType::wrap_under_create_rule(uuid_ref)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for CFUUID {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "with-uuid")]
|
||||
impl From<CFUUID> for Uuid {
|
||||
fn from(val: CFUUID) -> Self {
|
||||
let b = unsafe { CFUUIDGetUUIDBytes(val.0) };
|
||||
let bytes = [
|
||||
b.byte0, b.byte1, b.byte2, b.byte3, b.byte4, b.byte5, b.byte6, b.byte7, b.byte8,
|
||||
b.byte9, b.byte10, b.byte11, b.byte12, b.byte13, b.byte14, b.byte15,
|
||||
];
|
||||
Uuid::from_bytes(&bytes).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "with-uuid")]
|
||||
impl From<Uuid> for CFUUID {
|
||||
fn from(uuid: Uuid) -> CFUUID {
|
||||
let b = uuid.as_bytes();
|
||||
let bytes = CFUUIDBytes {
|
||||
byte0: b[0],
|
||||
byte1: b[1],
|
||||
byte2: b[2],
|
||||
byte3: b[3],
|
||||
byte4: b[4],
|
||||
byte5: b[5],
|
||||
byte6: b[6],
|
||||
byte7: b[7],
|
||||
byte8: b[8],
|
||||
byte9: b[9],
|
||||
byte10: b[10],
|
||||
byte11: b[11],
|
||||
byte12: b[12],
|
||||
byte13: b[13],
|
||||
byte14: b[14],
|
||||
byte15: b[15],
|
||||
};
|
||||
unsafe {
|
||||
let uuid_ref = CFUUIDCreateFromUUIDBytes(kCFAllocatorDefault, bytes);
|
||||
TCFType::wrap_under_create_rule(uuid_ref)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[cfg(feature = "with-uuid")]
|
||||
mod test {
|
||||
use super::CFUUID;
|
||||
use uuid::Uuid;
|
||||
|
||||
#[test]
|
||||
fn uuid_conversion() {
|
||||
let cf_uuid = CFUUID::new();
|
||||
let uuid: Uuid = cf_uuid.clone().into();
|
||||
let converted = CFUUID::from(uuid);
|
||||
assert_eq!(cf_uuid, converted);
|
||||
}
|
||||
}
|
||||
28
third-party/vendor/core-foundation/tests/use_macro_outside_crate.rs
vendored
Normal file
28
third-party/vendor/core-foundation/tests/use_macro_outside_crate.rs
vendored
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
#[macro_use]
|
||||
extern crate core_foundation;
|
||||
|
||||
use core_foundation::base::{CFComparisonResult, TCFType};
|
||||
use std::os::raw::c_void;
|
||||
|
||||
// sys equivalent stuff that must be declared
|
||||
|
||||
#[repr(C)]
|
||||
pub struct __CFFooBar(c_void);
|
||||
|
||||
pub type CFFooBarRef = *const __CFFooBar;
|
||||
|
||||
extern "C" {
|
||||
pub fn CFFooBarGetTypeID() -> core_foundation::base::CFTypeID;
|
||||
pub fn fake_compare(
|
||||
this: CFFooBarRef,
|
||||
other: CFFooBarRef,
|
||||
context: *mut c_void,
|
||||
) -> CFComparisonResult;
|
||||
}
|
||||
|
||||
// Try to use the macros outside of the crate
|
||||
|
||||
declare_TCFType!(CFFooBar, CFFooBarRef);
|
||||
impl_TCFType!(CFFooBar, CFFooBarRef, CFFooBarGetTypeID);
|
||||
impl_CFTypeDescription!(CFFooBar);
|
||||
impl_CFComparison!(CFFooBar, fake_compare);
|
||||
Loading…
Add table
Add a link
Reference in a new issue