Vendor things
This commit is contained in:
parent
5deceec006
commit
977e3c17e5
19434 changed files with 10682014 additions and 0 deletions
1
third-party/vendor/block2/.cargo-checksum.json
vendored
Normal file
1
third-party/vendor/block2/.cargo-checksum.json
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"files":{"CHANGELOG.md":"286ba5ef14c3199cfc510c4693aa8dbf660543d4b016e2a00fcd190cca7390ae","Cargo.toml":"4569ac021d9983cef708a827f5d6437fea5be84df2dbb51622b1d9a51019a638","README.md":"38470ee1aaa43e6436c23f62bf05788dd23c7dad92669b69a7dc8d4868d4bdef","src/block.rs":"16aa845511ed2e2dbd259da62e6beb9bbb51cf544b6c10d48341931b132ee063","src/concrete_block.rs":"9ad053ebad2e5747d3397b74a95381f3bda2866918d1bff4abd714180ea7f431","src/debug.rs":"c25742c777ffde5c0d7bb4bb1c78e935a16c2775951ea031655cb995302742db","src/global.rs":"460b807f90421899814fe61a35e909fb494b8d90c2f7349dbbf4b76fb5906604","src/lib.rs":"c54c67952867c2c62581d11573712976c46f988793120653b5692872c893baa3","src/rc_block.rs":"58504e8660547d379c93f03c5368b48b09fa37ea91d26f9fcf529b9186f309f4"},"package":"8dd9e63c1744f755c2f60332b88de39d341e5e86239014ad839bd71c106dec42"}
|
||||
164
third-party/vendor/block2/CHANGELOG.md
vendored
Normal file
164
third-party/vendor/block2/CHANGELOG.md
vendored
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
# Changelog
|
||||
|
||||
Notable changes to this crate will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||
|
||||
## Unreleased - YYYY-MM-DD
|
||||
|
||||
## 0.2.0-alpha.6 - 2022-08-28
|
||||
|
||||
### Changed
|
||||
* **BREAKING**: Updated `objc2-encode` to `v2.0.0-pre.2`.
|
||||
* Updated `ffi` module to `block-sys v0.1.0-beta.1`.
|
||||
|
||||
### Fixed
|
||||
* **BREAKING**: Cleaned up `BlockArguments` trait, it is now sealed and a
|
||||
subtrait of `EncodeArguments`.
|
||||
* **BREAKING**: Cleaned up `IntoConcreteBlock` trait, it is now sealed and the
|
||||
associated output type has been renamed to `Output`.
|
||||
|
||||
## 0.2.0-alpha.5 - 2022-07-19
|
||||
|
||||
### Added
|
||||
* Implemented `Debug` for `Block`, `ConcreteBlock`, `RcBlock` and
|
||||
`GlobalBlock`.
|
||||
|
||||
### Changed
|
||||
* **BREAKING**: Updated `objc2-encode` to `v2.0.0-pre.1`.
|
||||
* Updated `ffi` module to `block-sys v0.1.0-beta.0`.
|
||||
|
||||
|
||||
## 0.2.0-alpha.4 - 2022-06-13
|
||||
|
||||
### Changed
|
||||
* **BREAKING**: Updated `objc2-encode` to `v2.0.0-pre.0`.
|
||||
* **BREAKING**: Updated `ffi` module to `block-sys v0.0.4`.
|
||||
|
||||
### Removed
|
||||
* **BREAKING**: Removed `DerefMut` implementation for `ConcreteBlock`.
|
||||
|
||||
|
||||
## 0.2.0-alpha.3 - 2022-01-03
|
||||
|
||||
### Changed
|
||||
* Changed `global_block!` macro to take an optional semicolon at the end.
|
||||
* Improved documentation.
|
||||
* **BREAKING**: Updated `ffi` module to `block-sys v0.0.3`.
|
||||
|
||||
|
||||
## 0.2.0-alpha.2 - 2021-12-22
|
||||
|
||||
### Added
|
||||
* `GlobalBlock` and corresponding `global_block!` macro, allowing statically
|
||||
creating blocks that don't reference their environment.
|
||||
|
||||
### Changed
|
||||
* **BREAKING**: Updated `ffi` module to `block-sys v0.0.2`
|
||||
|
||||
|
||||
## 0.2.0-alpha.1 - 2021-11-22
|
||||
|
||||
### Added
|
||||
* Proper GNUStep support using `block-sys`. See that crate for usage.
|
||||
* Export `block-sys` as `ffi` module.
|
||||
|
||||
### Removed
|
||||
* Dependency on `objc_test_utils`.
|
||||
|
||||
### Fixed
|
||||
* `ConcreteBlock` no longer allocates block descriptors on the heap.
|
||||
* Better unwind safety in `ConcreteBlock::copy`.
|
||||
|
||||
|
||||
## 0.2.0-alpha.0 - 2021-10-28
|
||||
|
||||
### Added
|
||||
* **BREAKING**: Blocks now require that arguments and return type implement
|
||||
`objc2_encode::Encode`. This is a safety measure to prevent creating blocks
|
||||
with invalid arguments.
|
||||
* Blocks now implements `objc2_encode::RefEncode` (and as such can be used in
|
||||
Objective-C message sends).
|
||||
* Update to 2018 edition.
|
||||
|
||||
### Changed
|
||||
* **BREAKING**: Forked the project, so it is now available under the name
|
||||
`block2`.
|
||||
|
||||
### Fixed
|
||||
* Soundness issues with using empty enums over FFI.
|
||||
|
||||
|
||||
## [0.1.6] (`block` crate) - 2016-05-08
|
||||
|
||||
### Added
|
||||
* Support for linking to `libBlocksRuntime`.
|
||||
|
||||
|
||||
## [0.1.5] (`block` crate) - 2016-04-04
|
||||
|
||||
### Changed
|
||||
* Minor code changes
|
||||
|
||||
|
||||
## [0.1.4] (`block` crate) - 2015-11-12
|
||||
|
||||
### Removed
|
||||
* `libc` dependency.
|
||||
|
||||
|
||||
## [0.1.3] (`block` crate) - 2015-11-07
|
||||
|
||||
### Changed
|
||||
* Updated `libc` dependency.
|
||||
|
||||
|
||||
## [0.1.2] (`block` crate) - 2015-10-10
|
||||
|
||||
### Fixed
|
||||
* `improper_ctypes` warning.
|
||||
|
||||
|
||||
## [0.1.1] (`block` crate) - 2015-09-03
|
||||
|
||||
### Fixed
|
||||
* Missing `Sized` bounds on traits.
|
||||
|
||||
|
||||
## [0.1.0] (`block` crate) - 2015-05-18
|
||||
|
||||
### Added
|
||||
* `Clone` implementation for `RcBlock`.
|
||||
* Improved documentation.
|
||||
|
||||
### Changed
|
||||
* **BREAKING**: Rename `IdBlock` to `RcBlock`.
|
||||
* **BREAKING**: Make `Block::call` take self immutably and make it `unsafe`.
|
||||
* **BREAKING**: Make `BlockArguments::call_block` `unsafe`.
|
||||
|
||||
### Removed
|
||||
* **BREAKING**: `DerefMut` on `RcBlock`.
|
||||
* `objc` dependency.
|
||||
* `Foundation` dependency in tests.
|
||||
|
||||
|
||||
## [0.0.2] (`block` crate) - 2015-05-02
|
||||
|
||||
### Changed
|
||||
* Use `objc_id`.
|
||||
|
||||
|
||||
## [0.0.1] (`block` crate) - 2015-04-17
|
||||
|
||||
Initial version.
|
||||
|
||||
|
||||
[0.1.6]: https://github.com/madsmtm/objc2/compare/block-0.1.5...block-0.1.6
|
||||
[0.1.5]: https://github.com/madsmtm/objc2/compare/block-0.1.4...block-0.1.5
|
||||
[0.1.4]: https://github.com/madsmtm/objc2/compare/block-0.1.3...block-0.1.4
|
||||
[0.1.3]: https://github.com/madsmtm/objc2/compare/block-0.1.2...block-0.1.3
|
||||
[0.1.2]: https://github.com/madsmtm/objc2/compare/block-0.1.1...block-0.1.2
|
||||
[0.1.1]: https://github.com/madsmtm/objc2/compare/block-0.1.0...block-0.1.1
|
||||
[0.1.0]: https://github.com/madsmtm/objc2/compare/block-0.0.2...block-0.1.0
|
||||
[0.0.2]: https://github.com/madsmtm/objc2/compare/block-0.0.1...block-0.0.2
|
||||
[0.0.1]: https://github.com/madsmtm/objc2/releases/tag/block-0.0.1
|
||||
103
third-party/vendor/block2/Cargo.toml
vendored
Normal file
103
third-party/vendor/block2/Cargo.toml
vendored
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
# 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 = "2021"
|
||||
name = "block2"
|
||||
version = "0.2.0-alpha.6"
|
||||
authors = [
|
||||
"Steven Sheldon",
|
||||
"Mads Marquart <mads@marquart.dk>",
|
||||
]
|
||||
description = "Apple's C language extension of blocks"
|
||||
documentation = "https://docs.rs/block2/"
|
||||
readme = "README.md"
|
||||
keywords = [
|
||||
"objective-c",
|
||||
"macos",
|
||||
"ios",
|
||||
"blocks",
|
||||
]
|
||||
categories = [
|
||||
"api-bindings",
|
||||
"development-tools::ffi",
|
||||
"os::macos-apis",
|
||||
]
|
||||
license = "MIT"
|
||||
repository = "https://github.com/madsmtm/objc2"
|
||||
resolver = "2"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
default-target = "x86_64-apple-darwin"
|
||||
targets = [
|
||||
"x86_64-apple-darwin",
|
||||
"aarch64-apple-darwin",
|
||||
"aarch64-apple-ios",
|
||||
"x86_64-apple-ios",
|
||||
"x86_64-unknown-linux-gnu",
|
||||
"i686-unknown-linux-gnu",
|
||||
"x86_64-pc-windows-msvc",
|
||||
]
|
||||
|
||||
[dependencies.block-sys]
|
||||
version = "=0.1.0-beta.1"
|
||||
default-features = false
|
||||
|
||||
[dependencies.objc2-encode]
|
||||
version = "=2.0.0-pre.2"
|
||||
default-features = false
|
||||
|
||||
[features]
|
||||
alloc = [
|
||||
"objc2-encode/alloc",
|
||||
"block-sys/alloc",
|
||||
]
|
||||
apple = [
|
||||
"block-sys/apple",
|
||||
"objc2-encode/apple",
|
||||
]
|
||||
compiler-rt = [
|
||||
"block-sys/compiler-rt",
|
||||
"objc2-encode/apple",
|
||||
]
|
||||
default = [
|
||||
"std",
|
||||
"apple",
|
||||
]
|
||||
gnustep-1-7 = [
|
||||
"block-sys/gnustep-1-7",
|
||||
"objc2-encode/gnustep-1-7",
|
||||
]
|
||||
gnustep-1-8 = [
|
||||
"gnustep-1-7",
|
||||
"block-sys/gnustep-1-8",
|
||||
"objc2-encode/gnustep-1-8",
|
||||
]
|
||||
gnustep-1-9 = [
|
||||
"gnustep-1-8",
|
||||
"block-sys/gnustep-1-9",
|
||||
"objc2-encode/gnustep-1-9",
|
||||
]
|
||||
gnustep-2-0 = [
|
||||
"gnustep-1-9",
|
||||
"block-sys/gnustep-2-0",
|
||||
"objc2-encode/gnustep-2-0",
|
||||
]
|
||||
gnustep-2-1 = [
|
||||
"gnustep-2-0",
|
||||
"block-sys/gnustep-2-1",
|
||||
"objc2-encode/gnustep-2-1",
|
||||
]
|
||||
std = [
|
||||
"alloc",
|
||||
"objc2-encode/std",
|
||||
"block-sys/std",
|
||||
]
|
||||
16
third-party/vendor/block2/README.md
vendored
Normal file
16
third-party/vendor/block2/README.md
vendored
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
# `block2`
|
||||
|
||||
[](https://crates.io/crates/block2)
|
||||
[](../LICENSE.txt)
|
||||
[](https://docs.rs/block2/)
|
||||
[](https://github.com/madsmtm/objc2/actions/workflows/ci.yml)
|
||||
|
||||
Apple's C language extension of blocks in Rust.
|
||||
|
||||
This crate provides functionality for interracting with C blocks, effectively
|
||||
the C-equivalent of Rust's closures.
|
||||
|
||||
See [the docs](https://docs.rs/block2/) for a more thorough overview.
|
||||
|
||||
This crate is part of the [`objc2` project](https://github.com/madsmtm/objc2),
|
||||
see that for related crates.
|
||||
118
third-party/vendor/block2/src/block.rs
vendored
Normal file
118
third-party/vendor/block2/src/block.rs
vendored
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
use core::marker::PhantomData;
|
||||
use core::mem;
|
||||
|
||||
use objc2_encode::{Encode, EncodeArguments, Encoding, RefEncode};
|
||||
|
||||
use crate::ffi;
|
||||
|
||||
/// Types that may be used as the arguments of an Objective-C block.
|
||||
///
|
||||
/// This is implemented for tuples of up to 12 arguments, where each argument
|
||||
/// implements [`Encode`].
|
||||
///
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This is a sealed trait, and should not need to be implemented. Open an
|
||||
/// issue if you know a use-case where this restrition should be lifted!
|
||||
pub unsafe trait BlockArguments: EncodeArguments + Sized {
|
||||
/// Calls the given method the block and arguments.
|
||||
#[doc(hidden)]
|
||||
unsafe fn __call_block<R: Encode>(
|
||||
invoke: unsafe extern "C" fn(),
|
||||
block: *mut Block<Self, R>,
|
||||
args: Self,
|
||||
) -> R;
|
||||
}
|
||||
|
||||
macro_rules! block_args_impl {
|
||||
($($a:ident: $t:ident),*) => (
|
||||
unsafe impl<$($t: Encode),*> BlockArguments for ($($t,)*) {
|
||||
#[inline]
|
||||
unsafe fn __call_block<R: Encode>(invoke: unsafe extern "C" fn(), block: *mut Block<Self, R>, ($($a,)*): Self) -> R {
|
||||
// Very similar to `MessageArguments::__invoke`
|
||||
let invoke: unsafe extern "C" fn(*mut Block<Self, R> $(, $t)*) -> R = unsafe {
|
||||
mem::transmute(invoke)
|
||||
};
|
||||
|
||||
unsafe { invoke(block $(, $a)*) }
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
block_args_impl!();
|
||||
block_args_impl!(a: A);
|
||||
block_args_impl!(a: A, b: B);
|
||||
block_args_impl!(a: A, b: B, c: C);
|
||||
block_args_impl!(a: A, b: B, c: C, d: D);
|
||||
block_args_impl!(a: A, b: B, c: C, d: D, e: E);
|
||||
block_args_impl!(a: A, b: B, c: C, d: D, e: E, f: F);
|
||||
block_args_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G);
|
||||
block_args_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H);
|
||||
block_args_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I);
|
||||
block_args_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J);
|
||||
block_args_impl!(
|
||||
a: A,
|
||||
b: B,
|
||||
c: C,
|
||||
d: D,
|
||||
e: E,
|
||||
f: F,
|
||||
g: G,
|
||||
h: H,
|
||||
i: I,
|
||||
j: J,
|
||||
k: K
|
||||
);
|
||||
block_args_impl!(
|
||||
a: A,
|
||||
b: B,
|
||||
c: C,
|
||||
d: D,
|
||||
e: E,
|
||||
f: F,
|
||||
g: G,
|
||||
h: H,
|
||||
i: I,
|
||||
j: J,
|
||||
k: K,
|
||||
l: L
|
||||
);
|
||||
|
||||
/// An Objective-C block that takes arguments of `A` when called and
|
||||
/// returns a value of `R`.
|
||||
#[repr(C)]
|
||||
pub struct Block<A, R> {
|
||||
_inner: [u8; 0],
|
||||
// We effectively store `Block_layout` + a bit more, but `Block` has to
|
||||
// remain an empty type otherwise the compiler thinks we only have
|
||||
// provenance over `Block_layout`.
|
||||
_layout: PhantomData<ffi::Block_layout>,
|
||||
// To get correct variance on args and return types
|
||||
_p: PhantomData<fn(A) -> R>,
|
||||
}
|
||||
|
||||
unsafe impl<A: BlockArguments, R: Encode> RefEncode for Block<A, R> {
|
||||
const ENCODING_REF: Encoding = Encoding::Block;
|
||||
}
|
||||
|
||||
impl<A: BlockArguments, R: Encode> Block<A, R> {
|
||||
/// Call self with the given arguments.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This invokes foreign code that the caller must verify doesn't violate
|
||||
/// any of Rust's safety rules.
|
||||
///
|
||||
/// For example, if this block is shared with multiple references, the
|
||||
/// caller must ensure that calling it will not cause a data race.
|
||||
pub unsafe fn call(&self, args: A) -> R {
|
||||
let ptr: *const Self = self;
|
||||
let layout = unsafe { ptr.cast::<ffi::Block_layout>().as_ref().unwrap_unchecked() };
|
||||
// TODO: Is `invoke` actually ever null?
|
||||
let invoke = layout.invoke.unwrap();
|
||||
|
||||
unsafe { A::__call_block(invoke, ptr as *mut Self, args) }
|
||||
}
|
||||
}
|
||||
254
third-party/vendor/block2/src/concrete_block.rs
vendored
Normal file
254
third-party/vendor/block2/src/concrete_block.rs
vendored
Normal file
|
|
@ -0,0 +1,254 @@
|
|||
use core::ffi::c_void;
|
||||
use core::marker::PhantomData;
|
||||
use core::mem::{self, ManuallyDrop};
|
||||
use core::ops::Deref;
|
||||
use core::ptr;
|
||||
use std::os::raw::c_ulong;
|
||||
|
||||
use objc2_encode::{Encode, Encoding, RefEncode};
|
||||
|
||||
use crate::{ffi, Block, BlockArguments, RcBlock};
|
||||
|
||||
mod private {
|
||||
pub trait Sealed<A> {}
|
||||
}
|
||||
|
||||
/// Types that may be converted into a [`ConcreteBlock`].
|
||||
///
|
||||
/// This is implemented for [`Fn`] closures of up to 12 arguments, where each
|
||||
/// argument and the return type implements [`Encode`].
|
||||
///
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This is a sealed trait, and should not need to be implemented. Open an
|
||||
/// issue if you know a use-case where this restrition should be lifted!
|
||||
pub unsafe trait IntoConcreteBlock<A: BlockArguments>: private::Sealed<A> + Sized {
|
||||
/// The return type of the resulting `ConcreteBlock`.
|
||||
type Output: Encode;
|
||||
|
||||
#[doc(hidden)]
|
||||
fn __into_concrete_block(self) -> ConcreteBlock<A, Self::Output, Self>;
|
||||
}
|
||||
|
||||
macro_rules! concrete_block_impl {
|
||||
($f:ident) => (
|
||||
concrete_block_impl!($f,);
|
||||
);
|
||||
($f:ident, $($a:ident : $t:ident),*) => (
|
||||
impl<$($t: Encode,)* R: Encode, X> private::Sealed<($($t,)*)> for X
|
||||
where
|
||||
X: Fn($($t,)*) -> R,
|
||||
{}
|
||||
|
||||
unsafe impl<$($t: Encode,)* R: Encode, X> IntoConcreteBlock<($($t,)*)> for X
|
||||
where
|
||||
X: Fn($($t,)*) -> R,
|
||||
{
|
||||
type Output = R;
|
||||
|
||||
fn __into_concrete_block(self) -> ConcreteBlock<($($t,)*), R, X> {
|
||||
extern "C" fn $f<$($t,)* R, X>(
|
||||
block: &ConcreteBlock<($($t,)*), R, X>,
|
||||
$($a: $t,)*
|
||||
) -> R
|
||||
where
|
||||
X: Fn($($t,)*) -> R,
|
||||
{
|
||||
(block.closure)($($a),*)
|
||||
}
|
||||
|
||||
let f: extern "C" fn(&ConcreteBlock<($($t,)*), R, X>, $($a: $t,)*) -> R = $f;
|
||||
let f: unsafe extern "C" fn() = unsafe { mem::transmute(f) };
|
||||
unsafe { ConcreteBlock::with_invoke(f, self) }
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
concrete_block_impl!(concrete_block_invoke_args0);
|
||||
concrete_block_impl!(concrete_block_invoke_args1, a: A);
|
||||
concrete_block_impl!(concrete_block_invoke_args2, a: A, b: B);
|
||||
concrete_block_impl!(concrete_block_invoke_args3, a: A, b: B, c: C);
|
||||
concrete_block_impl!(concrete_block_invoke_args4, a: A, b: B, c: C, d: D);
|
||||
concrete_block_impl!(concrete_block_invoke_args5, a: A, b: B, c: C, d: D, e: E);
|
||||
concrete_block_impl!(
|
||||
concrete_block_invoke_args6,
|
||||
a: A,
|
||||
b: B,
|
||||
c: C,
|
||||
d: D,
|
||||
e: E,
|
||||
f: F
|
||||
);
|
||||
concrete_block_impl!(
|
||||
concrete_block_invoke_args7,
|
||||
a: A,
|
||||
b: B,
|
||||
c: C,
|
||||
d: D,
|
||||
e: E,
|
||||
f: F,
|
||||
g: G
|
||||
);
|
||||
concrete_block_impl!(
|
||||
concrete_block_invoke_args8,
|
||||
a: A,
|
||||
b: B,
|
||||
c: C,
|
||||
d: D,
|
||||
e: E,
|
||||
f: F,
|
||||
g: G,
|
||||
h: H
|
||||
);
|
||||
concrete_block_impl!(
|
||||
concrete_block_invoke_args9,
|
||||
a: A,
|
||||
b: B,
|
||||
c: C,
|
||||
d: D,
|
||||
e: E,
|
||||
f: F,
|
||||
g: G,
|
||||
h: H,
|
||||
i: I
|
||||
);
|
||||
concrete_block_impl!(
|
||||
concrete_block_invoke_args10,
|
||||
a: A,
|
||||
b: B,
|
||||
c: C,
|
||||
d: D,
|
||||
e: E,
|
||||
f: F,
|
||||
g: G,
|
||||
h: H,
|
||||
i: I,
|
||||
j: J
|
||||
);
|
||||
concrete_block_impl!(
|
||||
concrete_block_invoke_args11,
|
||||
a: A,
|
||||
b: B,
|
||||
c: C,
|
||||
d: D,
|
||||
e: E,
|
||||
f: F,
|
||||
g: G,
|
||||
h: H,
|
||||
i: I,
|
||||
j: J,
|
||||
k: K
|
||||
);
|
||||
concrete_block_impl!(
|
||||
concrete_block_invoke_args12,
|
||||
a: A,
|
||||
b: B,
|
||||
c: C,
|
||||
d: D,
|
||||
e: E,
|
||||
f: F,
|
||||
g: G,
|
||||
h: H,
|
||||
i: I,
|
||||
j: J,
|
||||
k: K,
|
||||
l: L
|
||||
);
|
||||
|
||||
/// An Objective-C block whose size is known at compile time and may be
|
||||
/// constructed on the stack.
|
||||
#[repr(C)]
|
||||
pub struct ConcreteBlock<A, R, F> {
|
||||
p: PhantomData<Block<A, R>>,
|
||||
pub(crate) layout: ffi::Block_layout,
|
||||
pub(crate) closure: F,
|
||||
}
|
||||
|
||||
unsafe impl<A: BlockArguments, R: Encode, F> RefEncode for ConcreteBlock<A, R, F> {
|
||||
const ENCODING_REF: Encoding = Encoding::Block;
|
||||
}
|
||||
|
||||
impl<A, R, F> ConcreteBlock<A, R, F>
|
||||
where
|
||||
A: BlockArguments,
|
||||
R: Encode,
|
||||
F: IntoConcreteBlock<A, Output = R>,
|
||||
{
|
||||
/// Constructs a `ConcreteBlock` with the given closure.
|
||||
/// When the block is called, it will return the value that results from
|
||||
/// calling the closure.
|
||||
pub fn new(closure: F) -> Self {
|
||||
closure.__into_concrete_block()
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, R, F> ConcreteBlock<A, R, F> {
|
||||
// TODO: Use new ABI with BLOCK_HAS_SIGNATURE
|
||||
const FLAGS: ffi::block_flags = ffi::BLOCK_HAS_COPY_DISPOSE;
|
||||
|
||||
const DESCRIPTOR: ffi::Block_descriptor = ffi::Block_descriptor {
|
||||
header: ffi::Block_descriptor_header {
|
||||
reserved: 0,
|
||||
size: mem::size_of::<Self>() as c_ulong,
|
||||
},
|
||||
copy: Some(block_context_copy::<Self>),
|
||||
dispose: Some(block_context_dispose::<Self>),
|
||||
};
|
||||
|
||||
/// Constructs a `ConcreteBlock` with the given invoke function and closure.
|
||||
/// Unsafe because the caller must ensure the invoke function takes the
|
||||
/// correct arguments.
|
||||
unsafe fn with_invoke(invoke: unsafe extern "C" fn(), closure: F) -> Self {
|
||||
let layout = ffi::Block_layout {
|
||||
isa: unsafe { &ffi::_NSConcreteStackBlock },
|
||||
flags: Self::FLAGS,
|
||||
reserved: 0,
|
||||
invoke: Some(invoke),
|
||||
descriptor: &Self::DESCRIPTOR as *const ffi::Block_descriptor as *mut c_void,
|
||||
};
|
||||
Self {
|
||||
p: PhantomData,
|
||||
layout,
|
||||
closure,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, R, F: 'static> ConcreteBlock<A, R, F> {
|
||||
/// Copy self onto the heap as an `RcBlock`.
|
||||
pub fn copy(self) -> RcBlock<A, R> {
|
||||
// Our copy helper will run so the block will be moved to the heap
|
||||
// and we can forget the original block because the heap block will
|
||||
// drop in our dispose helper. TODO: Verify this.
|
||||
let mut block = ManuallyDrop::new(self);
|
||||
let ptr: *mut Self = &mut *block;
|
||||
unsafe { RcBlock::copy(ptr.cast()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, R, F: Clone> Clone for ConcreteBlock<A, R, F> {
|
||||
fn clone(&self) -> Self {
|
||||
unsafe { Self::with_invoke(self.layout.invoke.unwrap(), self.closure.clone()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, R, F> Deref for ConcreteBlock<A, R, F> {
|
||||
type Target = Block<A, R>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
let ptr: *const Self = self;
|
||||
let ptr: *const Block<A, R> = ptr.cast();
|
||||
// TODO: SAFETY
|
||||
unsafe { ptr.as_ref().unwrap_unchecked() }
|
||||
}
|
||||
}
|
||||
|
||||
unsafe extern "C" fn block_context_dispose<B>(block: *mut c_void) {
|
||||
unsafe { ptr::drop_in_place(block.cast::<B>()) };
|
||||
}
|
||||
|
||||
unsafe extern "C" fn block_context_copy<B>(_dst: *mut c_void, _src: *mut c_void) {
|
||||
// The runtime memmoves the src block into the dst block, nothing to do
|
||||
}
|
||||
242
third-party/vendor/block2/src/debug.rs
vendored
Normal file
242
third-party/vendor/block2/src/debug.rs
vendored
Normal file
|
|
@ -0,0 +1,242 @@
|
|||
use alloc::format;
|
||||
use core::ffi::c_void;
|
||||
use core::fmt::{Debug, DebugStruct, Error, Formatter};
|
||||
use core::ptr;
|
||||
use std::ffi::CStr;
|
||||
|
||||
use crate::{ffi, Block, ConcreteBlock, GlobalBlock, RcBlock};
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
struct Isa(*const ffi::Class);
|
||||
|
||||
impl Isa {
|
||||
fn is_global(self) -> bool {
|
||||
ptr::eq(unsafe { &ffi::_NSConcreteGlobalBlock }, self.0)
|
||||
}
|
||||
|
||||
fn is_stack(self) -> bool {
|
||||
ptr::eq(unsafe { &ffi::_NSConcreteStackBlock }, self.0)
|
||||
}
|
||||
|
||||
fn is_malloc(self) -> bool {
|
||||
ptr::eq(unsafe { &ffi::_NSConcreteMallocBlock }, self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Isa {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
|
||||
if self.is_global() {
|
||||
f.write_str("_NSConcreteGlobalBlock")
|
||||
} else if self.is_stack() {
|
||||
f.write_str("_NSConcreteStackBlock")
|
||||
} else if self.is_malloc() {
|
||||
f.write_str("_NSConcreteMallocBlock")
|
||||
} else {
|
||||
write!(f, "{:?}", self.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn debug_block_layout(layout: &ffi::Block_layout, f: &mut DebugStruct<'_, '_>) {
|
||||
f.field("isa", &Isa(layout.isa));
|
||||
f.field("flags", &BlockFlags(layout.flags));
|
||||
f.field("reserved", &layout.reserved);
|
||||
f.field("invoke", &layout.invoke);
|
||||
f.field(
|
||||
"descriptor",
|
||||
&BlockDescriptor {
|
||||
has_copy_dispose: layout.flags & ffi::BLOCK_HAS_COPY_DISPOSE != 0,
|
||||
has_signature: layout.flags & ffi::BLOCK_HAS_SIGNATURE != 0,
|
||||
descriptor: layout.descriptor,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
impl<A, R> Debug for Block<A, R> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
|
||||
let mut f = f.debug_struct("Block");
|
||||
let ptr: *const Self = self;
|
||||
let layout = unsafe { ptr.cast::<ffi::Block_layout>().as_ref().unwrap() };
|
||||
debug_block_layout(layout, &mut f);
|
||||
f.finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, R> Debug for RcBlock<A, R> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
|
||||
let mut f = f.debug_struct("RcBlock");
|
||||
let layout = unsafe { self.ptr.cast::<ffi::Block_layout>().as_ref().unwrap() };
|
||||
debug_block_layout(layout, &mut f);
|
||||
f.finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, R, F: Debug> Debug for ConcreteBlock<A, R, F> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
|
||||
let mut f = f.debug_struct("ConcreteBlock");
|
||||
debug_block_layout(&self.layout, &mut f);
|
||||
f.field("closure", &self.closure);
|
||||
f.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, R> Debug for GlobalBlock<A, R> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
|
||||
let mut f = f.debug_struct("GlobalBlock");
|
||||
debug_block_layout(&self.layout, &mut f);
|
||||
f.finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
struct BlockFlags(ffi::block_flags);
|
||||
|
||||
impl Debug for BlockFlags {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
|
||||
let mut f = f.debug_struct("BlockFlags");
|
||||
f.field("value", &format!("{:032b}", self.0));
|
||||
|
||||
macro_rules! test_flags {
|
||||
{$(
|
||||
$(#[$m:meta])?
|
||||
$name:ident: $flag:ident
|
||||
);* $(;)?} => ($(
|
||||
$(#[$m])?
|
||||
f.field(stringify!($name), &(self.0 & ffi::$flag != 0));
|
||||
)*)
|
||||
}
|
||||
test_flags! {
|
||||
#[cfg(feature = "apple")]
|
||||
deallocating: BLOCK_DEALLOCATING;
|
||||
#[cfg(feature = "apple")]
|
||||
inline_layout_string: BLOCK_INLINE_LAYOUT_STRING;
|
||||
#[cfg(feature = "apple")]
|
||||
small_descriptor: BLOCK_SMALL_DESCRIPTOR;
|
||||
#[cfg(feature = "apple")]
|
||||
is_noescape: BLOCK_IS_NOESCAPE;
|
||||
#[cfg(feature = "apple")]
|
||||
needs_free: BLOCK_NEEDS_FREE;
|
||||
has_copy_dispose: BLOCK_HAS_COPY_DISPOSE;
|
||||
has_ctor: BLOCK_HAS_CTOR;
|
||||
#[cfg(feature = "apple")]
|
||||
is_gc: BLOCK_IS_GC;
|
||||
is_global: BLOCK_IS_GLOBAL;
|
||||
use_stret: BLOCK_USE_STRET;
|
||||
has_signature: BLOCK_HAS_SIGNATURE;
|
||||
#[cfg(feature = "apple")]
|
||||
has_extended_layout: BLOCK_HAS_EXTENDED_LAYOUT;
|
||||
}
|
||||
|
||||
f.field(
|
||||
"over_referenced",
|
||||
&(self.0 & ffi::BLOCK_REFCOUNT_MASK == ffi::BLOCK_REFCOUNT_MASK),
|
||||
);
|
||||
f.field(
|
||||
"reference_count",
|
||||
&((self.0 & ffi::BLOCK_REFCOUNT_MASK) >> 1),
|
||||
);
|
||||
f.finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
struct BlockDescriptor {
|
||||
has_copy_dispose: bool,
|
||||
has_signature: bool,
|
||||
descriptor: *const c_void,
|
||||
}
|
||||
|
||||
impl Debug for BlockDescriptor {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
|
||||
if self.descriptor.is_null() {
|
||||
return f.write_str("(null)");
|
||||
}
|
||||
|
||||
let mut f = f.debug_struct("BlockDescriptor");
|
||||
|
||||
let header = unsafe {
|
||||
self.descriptor
|
||||
.cast::<ffi::Block_descriptor_header>()
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
};
|
||||
|
||||
f.field("reserved", &header.reserved);
|
||||
f.field("size", &header.size);
|
||||
|
||||
match (self.has_copy_dispose, self.has_signature) {
|
||||
(false, false) => {}
|
||||
(true, false) => {
|
||||
let descriptor = unsafe {
|
||||
self.descriptor
|
||||
.cast::<ffi::Block_descriptor>()
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
};
|
||||
f.field("copy", &descriptor.copy);
|
||||
f.field("dispose", &descriptor.dispose);
|
||||
}
|
||||
(false, true) => {
|
||||
let descriptor = unsafe {
|
||||
self.descriptor
|
||||
.cast::<ffi::Block_descriptor_basic>()
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
};
|
||||
f.field(
|
||||
"encoding",
|
||||
&if descriptor.encoding.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(unsafe { CStr::from_ptr(descriptor.encoding) })
|
||||
},
|
||||
);
|
||||
}
|
||||
(true, true) => {
|
||||
let descriptor = unsafe {
|
||||
self.descriptor
|
||||
.cast::<ffi::Block_descriptor_with_signature>()
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
};
|
||||
f.field("copy", &descriptor.copy);
|
||||
f.field("dispose", &descriptor.dispose);
|
||||
f.field(
|
||||
"encoding",
|
||||
&if descriptor.encoding.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(unsafe { CStr::from_ptr(descriptor.encoding) })
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
f.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_isa() {
|
||||
let isa = Isa(unsafe { &ffi::_NSConcreteGlobalBlock });
|
||||
assert!(isa.is_global());
|
||||
assert!(!isa.is_stack());
|
||||
assert!(!isa.is_malloc());
|
||||
let isa = Isa(unsafe { &ffi::_NSConcreteStackBlock });
|
||||
assert!(!isa.is_global());
|
||||
assert!(isa.is_stack());
|
||||
assert!(!isa.is_malloc());
|
||||
let isa = Isa(unsafe { &ffi::_NSConcreteMallocBlock });
|
||||
assert!(!isa.is_global());
|
||||
assert!(!isa.is_stack());
|
||||
assert!(isa.is_malloc());
|
||||
let isa = Isa(ptr::null());
|
||||
assert!(!isa.is_global());
|
||||
assert!(!isa.is_stack());
|
||||
assert!(!isa.is_malloc());
|
||||
}
|
||||
}
|
||||
274
third-party/vendor/block2/src/global.rs
vendored
Normal file
274
third-party/vendor/block2/src/global.rs
vendored
Normal file
|
|
@ -0,0 +1,274 @@
|
|||
use core::ffi::c_void;
|
||||
use core::marker::PhantomData;
|
||||
use core::mem;
|
||||
use core::ops::Deref;
|
||||
use core::ptr;
|
||||
use std::os::raw::c_ulong;
|
||||
|
||||
use objc2_encode::Encode;
|
||||
|
||||
use super::{ffi, Block};
|
||||
use crate::BlockArguments;
|
||||
|
||||
// TODO: Should this be a static to help the compiler deduplicating them?
|
||||
const GLOBAL_DESCRIPTOR: ffi::Block_descriptor_header = ffi::Block_descriptor_header {
|
||||
reserved: 0,
|
||||
size: mem::size_of::<ffi::Block_layout>() as c_ulong,
|
||||
};
|
||||
|
||||
/// An Objective-C block that does not capture its environment.
|
||||
///
|
||||
/// This is effectively just a glorified function pointer, and can created and
|
||||
/// stored in static memory using the [`global_block!`] macro.
|
||||
///
|
||||
/// If [`ConcreteBlock`] is the [`Fn`]-block equivalent, this is likewise the
|
||||
/// [`fn`]-block equivalent.
|
||||
///
|
||||
/// [`ConcreteBlock`]: crate::ConcreteBlock
|
||||
/// [`global_block!`]: crate::global_block
|
||||
#[repr(C)]
|
||||
pub struct GlobalBlock<A, R = ()> {
|
||||
pub(crate) layout: ffi::Block_layout,
|
||||
p: PhantomData<(A, R)>,
|
||||
}
|
||||
|
||||
unsafe impl<A, R> Sync for GlobalBlock<A, R>
|
||||
where
|
||||
A: BlockArguments,
|
||||
R: Encode,
|
||||
{
|
||||
}
|
||||
unsafe impl<A, R> Send for GlobalBlock<A, R>
|
||||
where
|
||||
A: BlockArguments,
|
||||
R: Encode,
|
||||
{
|
||||
}
|
||||
|
||||
// Note: We can't put correct bounds on A and R because we have a const fn!
|
||||
//
|
||||
// Fortunately, we don't need them, since they're present on `Sync`, so
|
||||
// constructing the static in `global_block!` with an invalid `GlobalBlock`
|
||||
// triggers an error.
|
||||
impl<A, R> GlobalBlock<A, R> {
|
||||
// TODO: Use new ABI with BLOCK_HAS_SIGNATURE
|
||||
const FLAGS: ffi::block_flags = ffi::BLOCK_IS_GLOBAL | ffi::BLOCK_USE_STRET;
|
||||
|
||||
#[doc(hidden)]
|
||||
pub const __DEFAULT_LAYOUT: ffi::Block_layout = ffi::Block_layout {
|
||||
// Populated in `global_block!`
|
||||
isa: ptr::null_mut(),
|
||||
flags: Self::FLAGS,
|
||||
reserved: 0,
|
||||
// Populated in `global_block!`
|
||||
invoke: None,
|
||||
descriptor: &GLOBAL_DESCRIPTOR as *const ffi::Block_descriptor_header as *mut c_void,
|
||||
};
|
||||
|
||||
/// Use the [`global_block`] macro instead.
|
||||
#[doc(hidden)]
|
||||
pub const unsafe fn from_layout(layout: ffi::Block_layout) -> Self {
|
||||
Self {
|
||||
layout,
|
||||
p: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, R> Deref for GlobalBlock<A, R>
|
||||
where
|
||||
A: BlockArguments,
|
||||
R: Encode,
|
||||
{
|
||||
type Target = Block<A, R>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
let ptr: *const Self = self;
|
||||
let ptr: *const Block<A, R> = ptr.cast();
|
||||
// TODO: SAFETY
|
||||
unsafe { ptr.as_ref().unwrap_unchecked() }
|
||||
}
|
||||
}
|
||||
|
||||
/// Construct a static [`GlobalBlock`].
|
||||
///
|
||||
/// The syntax is similar to a static closure (except that all types have to
|
||||
/// be specified). Note that the block cannot capture its environment, and
|
||||
/// its argument types and return type must be [`Encode`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use block2::global_block;
|
||||
/// global_block! {
|
||||
/// static MY_BLOCK = || -> i32 {
|
||||
/// 42
|
||||
/// };
|
||||
/// }
|
||||
/// assert_eq!(unsafe { MY_BLOCK.call(()) }, 42);
|
||||
/// ```
|
||||
///
|
||||
/// ```
|
||||
/// use block2::global_block;
|
||||
/// global_block! {
|
||||
/// static ADDER_BLOCK = |x: i32, y: i32| -> i32 {
|
||||
/// x + y
|
||||
/// };
|
||||
/// }
|
||||
/// assert_eq!(unsafe { ADDER_BLOCK.call((5, 7)) }, 12);
|
||||
/// ```
|
||||
///
|
||||
/// ```
|
||||
/// use block2::global_block;
|
||||
/// global_block! {
|
||||
/// pub static MUTATING_BLOCK = |x: &mut i32| {
|
||||
/// *x = *x + 42;
|
||||
/// };
|
||||
/// }
|
||||
/// let mut x = 5;
|
||||
/// unsafe { MUTATING_BLOCK.call((&mut x,)) };
|
||||
/// assert_eq!(x, 47);
|
||||
/// ```
|
||||
///
|
||||
/// The following does not compile because [`Box`] is not [`Encode`]:
|
||||
///
|
||||
/// ```compile_fail
|
||||
/// use block2::global_block;
|
||||
/// global_block! {
|
||||
/// pub static BLOCK = |b: Box<i32>| {};
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// There is also no way to get a block function that's generic over its
|
||||
/// arguments. One could imagine the following syntax would work, but it can't
|
||||
/// due to implementation limitations:
|
||||
///
|
||||
/// ```compile_fail
|
||||
/// use block2::global_block;
|
||||
/// global_block! {
|
||||
/// pub static BLOCK<T: Encode> = |b: T| {};
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// [`Box`]: std::boxed::Box
|
||||
#[macro_export]
|
||||
macro_rules! global_block {
|
||||
// `||` is parsed as one token
|
||||
(
|
||||
$(#[$m:meta])*
|
||||
$vis:vis static $name:ident = || $(-> $r:ty)? $body:block $(;)?
|
||||
) => {
|
||||
$crate::global_block!(
|
||||
$(#[$m])*
|
||||
$vis static $name = |,| $(-> $r)? $body
|
||||
);
|
||||
};
|
||||
(
|
||||
$(#[$m:meta])*
|
||||
$vis:vis static $name:ident = |$($a:ident: $t:ty),* $(,)?| $(-> $r:ty)? $body:block $(;)?
|
||||
) => {
|
||||
$(#[$m])*
|
||||
#[allow(unused_unsafe)]
|
||||
$vis static $name: $crate::GlobalBlock<($($t,)*) $(, $r)?> = unsafe {
|
||||
let mut layout = $crate::GlobalBlock::<($($t,)*) $(, $r)?>::__DEFAULT_LAYOUT;
|
||||
layout.isa = &$crate::ffi::_NSConcreteGlobalBlock;
|
||||
layout.invoke = ::core::option::Option::Some({
|
||||
unsafe extern "C" fn inner(_: *mut $crate::ffi::Block_layout, $($a: $t),*) $(-> $r)? {
|
||||
$body
|
||||
}
|
||||
let inner: unsafe extern "C" fn(*mut $crate::ffi::Block_layout, $($a: $t),*) $(-> $r)? = inner;
|
||||
|
||||
// TODO: SAFETY
|
||||
::core::mem::transmute(inner)
|
||||
});
|
||||
$crate::GlobalBlock::from_layout(layout)
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use alloc::format;
|
||||
|
||||
global_block! {
|
||||
/// Test comments and visibility
|
||||
pub(super) static NOOP_BLOCK = || {};
|
||||
}
|
||||
|
||||
global_block! {
|
||||
/// Multiple arguments + trailing comma
|
||||
#[allow(unused)]
|
||||
static BLOCK = |x: i32, y: i32, z: i32, w: i32,| -> i32 {
|
||||
x + y + z + w
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_noop_block() {
|
||||
unsafe { NOOP_BLOCK.call(()) };
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_defined_in_function() {
|
||||
global_block!(static MY_BLOCK = || -> i32 {
|
||||
42
|
||||
});
|
||||
assert_eq!(unsafe { MY_BLOCK.call(()) }, 42);
|
||||
}
|
||||
|
||||
#[cfg(feature = "apple")]
|
||||
const DEBUG_BLOCKFLAGS: &str = r#"BlockFlags {
|
||||
value: "00110000000000000000000000000000",
|
||||
deallocating: false,
|
||||
inline_layout_string: false,
|
||||
small_descriptor: false,
|
||||
is_noescape: false,
|
||||
needs_free: false,
|
||||
has_copy_dispose: false,
|
||||
has_ctor: false,
|
||||
is_gc: false,
|
||||
is_global: true,
|
||||
use_stret: true,
|
||||
has_signature: false,
|
||||
has_extended_layout: false,
|
||||
over_referenced: false,
|
||||
reference_count: 0,
|
||||
..
|
||||
}"#;
|
||||
|
||||
#[cfg(not(feature = "apple"))]
|
||||
const DEBUG_BLOCKFLAGS: &str = r#"BlockFlags {
|
||||
value: "00110000000000000000000000000000",
|
||||
has_copy_dispose: false,
|
||||
has_ctor: false,
|
||||
is_global: true,
|
||||
use_stret: true,
|
||||
has_signature: false,
|
||||
over_referenced: false,
|
||||
reference_count: 0,
|
||||
..
|
||||
}"#;
|
||||
|
||||
#[test]
|
||||
fn test_debug() {
|
||||
let invoke = NOOP_BLOCK.layout.invoke.unwrap();
|
||||
let size = mem::size_of::<ffi::Block_layout>();
|
||||
let expected = format!(
|
||||
"GlobalBlock {{
|
||||
isa: _NSConcreteGlobalBlock,
|
||||
flags: {DEBUG_BLOCKFLAGS},
|
||||
reserved: 0,
|
||||
invoke: Some(
|
||||
{invoke:#?},
|
||||
),
|
||||
descriptor: BlockDescriptor {{
|
||||
reserved: 0,
|
||||
size: {size},
|
||||
}},
|
||||
..
|
||||
}}"
|
||||
);
|
||||
assert_eq!(format!("{:#?}", NOOP_BLOCK), expected);
|
||||
}
|
||||
}
|
||||
109
third-party/vendor/block2/src/lib.rs
vendored
Normal file
109
third-party/vendor/block2/src/lib.rs
vendored
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
//! # Apple's C language extension of blocks
|
||||
//!
|
||||
//! C Blocks are effectively the C-equivalent of Rust's closures, in that they
|
||||
//! have the ability to capture their environments.
|
||||
//!
|
||||
//! This crate provides capabilities to create and invoke these blocks, in an
|
||||
//! ergonomic "Rust-centric" fashion.
|
||||
//!
|
||||
//! For more information on the specifics of the block implementation, see the
|
||||
//! [C language specification][lang] and the [ABI specification][ABI].
|
||||
//!
|
||||
//! (Note that while this library can be used separately from Objective-C,
|
||||
//! they're most commonly used together).
|
||||
//!
|
||||
//! ## Invoking blocks
|
||||
//!
|
||||
//! The [`Block`] struct is used for invoking blocks from Objective-C. For
|
||||
//! example, consider this Objective-C function that takes a block as a
|
||||
//! parameter, executes the block with some arguments, and returns the result:
|
||||
//!
|
||||
//! ```objc
|
||||
//! #include <stdint.h>
|
||||
//! #include <Block.h>
|
||||
//! int32_t run_block(int32_t (^block)(int32_t, int32_t)) {
|
||||
//! return block(5, 8);
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! We could write the equivalent function in Rust like this:
|
||||
//!
|
||||
//! ```
|
||||
//! use block2::Block;
|
||||
//! unsafe fn run_block(block: &Block<(i32, i32), i32>) -> i32 {
|
||||
//! block.call((5, 8))
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! Note the extra parentheses in the `call` method, since the arguments must
|
||||
//! be passed as a tuple.
|
||||
//!
|
||||
//! ## Creating blocks
|
||||
//!
|
||||
//! Creating a block to pass to Objective-C can be done with the
|
||||
//! [`ConcreteBlock`] struct. For example, to create a block that adds two
|
||||
//! integers, we could write:
|
||||
//!
|
||||
//! ```
|
||||
//! use block2::ConcreteBlock;
|
||||
//! let block = ConcreteBlock::new(|a: i32, b: i32| a + b);
|
||||
//! let block = block.copy();
|
||||
//! assert_eq!(unsafe { block.call((5, 8)) }, 13);
|
||||
//! ```
|
||||
//!
|
||||
//! It is important to copy your block to the heap (with the [`copy`] method)
|
||||
//! before passing it to Objective-C; this is because our [`ConcreteBlock`] is
|
||||
//! only meant to be copied once, and we can enforce this in Rust, but if
|
||||
//! Objective-C code were to copy it twice we could have a double free.
|
||||
//!
|
||||
//! [`copy`]: ConcreteBlock::copy
|
||||
//!
|
||||
//! As an optimization if your block doesn't capture any variables, you can
|
||||
//! use the [`global_block!`] macro to create a static block:
|
||||
//!
|
||||
//! ```
|
||||
//! use block2::global_block;
|
||||
//! global_block! {
|
||||
//! static MY_BLOCK = || -> f32 {
|
||||
//! 10.0
|
||||
//! };
|
||||
//! }
|
||||
//! assert_eq!(unsafe { MY_BLOCK.call(()) }, 10.0);
|
||||
//! ```
|
||||
//!
|
||||
//! [lang]: https://clang.llvm.org/docs/BlockLanguageSpec.html
|
||||
//! [ABI]: http://clang.llvm.org/docs/Block-ABI-Apple.html
|
||||
|
||||
#![no_std]
|
||||
#![warn(elided_lifetimes_in_paths)]
|
||||
#![warn(missing_docs)]
|
||||
#![deny(non_ascii_idents)]
|
||||
#![warn(unreachable_pub)]
|
||||
#![deny(unsafe_op_in_unsafe_fn)]
|
||||
#![warn(clippy::cargo)]
|
||||
#![warn(clippy::ptr_as_ptr)]
|
||||
// Update in Cargo.toml as well.
|
||||
#![doc(html_root_url = "https://docs.rs/block2/0.2.0-alpha.6")]
|
||||
|
||||
extern crate alloc;
|
||||
extern crate std;
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
compile_error!("The `std` feature currently must be enabled.");
|
||||
|
||||
#[cfg(doctest)]
|
||||
#[doc = include_str!("../README.md")]
|
||||
extern "C" {}
|
||||
|
||||
pub use block_sys as ffi;
|
||||
|
||||
mod block;
|
||||
mod concrete_block;
|
||||
mod debug;
|
||||
mod global;
|
||||
mod rc_block;
|
||||
|
||||
pub use block::{Block, BlockArguments};
|
||||
pub use concrete_block::{ConcreteBlock, IntoConcreteBlock};
|
||||
pub use global::GlobalBlock;
|
||||
pub use rc_block::RcBlock;
|
||||
59
third-party/vendor/block2/src/rc_block.rs
vendored
Normal file
59
third-party/vendor/block2/src/rc_block.rs
vendored
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
use core::ops::Deref;
|
||||
|
||||
use crate::{ffi, Block};
|
||||
|
||||
/// A reference-counted Objective-C block.
|
||||
pub struct RcBlock<A, R> {
|
||||
pub(crate) ptr: *mut Block<A, R>,
|
||||
}
|
||||
|
||||
impl<A, R> RcBlock<A, R> {
|
||||
/// Construct an `RcBlock` for the given block without copying it.
|
||||
/// The caller must ensure the block has a +1 reference count.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The given pointer must point to a valid `Block` and must have a +1
|
||||
/// reference count or it will be overreleased when the `RcBlock` is
|
||||
/// dropped.
|
||||
pub unsafe fn new(ptr: *mut Block<A, R>) -> Self {
|
||||
RcBlock { ptr }
|
||||
}
|
||||
|
||||
/// Constructs an `RcBlock` by copying the given block.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The given pointer must point to a valid `Block`.
|
||||
pub unsafe fn copy(ptr: *mut Block<A, R>) -> Self {
|
||||
// SAFETY: The caller ensures the pointer is valid.
|
||||
let ptr: *mut Block<A, R> = unsafe { ffi::_Block_copy(ptr.cast()) }.cast();
|
||||
// SAFETY: We just copied the block, so the reference count is +1
|
||||
//
|
||||
// TODO: Does _Block_copy always returns a valid pointer?
|
||||
unsafe { Self::new(ptr) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, R> Clone for RcBlock<A, R> {
|
||||
fn clone(&self) -> RcBlock<A, R> {
|
||||
// SAFETY: The pointer is valid, since the only way to get an RcBlock
|
||||
// in the first place is through unsafe functions.
|
||||
unsafe { RcBlock::copy(self.ptr) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, R> Deref for RcBlock<A, R> {
|
||||
type Target = Block<A, R>;
|
||||
|
||||
fn deref(&self) -> &Block<A, R> {
|
||||
// SAFETY: The pointer is ensured valid by creator functions.
|
||||
unsafe { self.ptr.as_ref().unwrap_unchecked() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, R> Drop for RcBlock<A, R> {
|
||||
fn drop(&mut self) {
|
||||
unsafe { ffi::_Block_release(self.ptr.cast()) };
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue