use core::ffi::c_ulong; use core::ffi::c_void; use core::fmt; use core::marker::PhantomData; use core::mem::{self, MaybeUninit}; use core::ops::Deref; use core::panic::{RefUnwindSafe, UnwindSafe}; use core::ptr::{self, NonNull};
use objc2::encode::{EncodeArguments, EncodeReturn, Encoding, RefEncode};
/// An Objective-C block constructed on the stack. /// /// This can be a micro-optimization if you know that the function you're /// passing the block to won't [copy] the block at all (e.g. if it guarantees /// that it'll run it synchronously). That's very rare though, most of the /// time you'll want to use [`RcBlock`]. /// /// This is a smart pointer that [`Deref`]s to [`Block`]. /// /// [copy]: Block::copy /// [`RcBlock`]: crate::RcBlock /// /// /// # Type parameters /// /// The type parameters for this is a bit complex due to trait system /// limitations. Usually, you will not need to specify them, as the compiler /// should be able to infer them. /// /// - The lifetime `'f`, which is the lifetime of the block. /// - The parameter `A`, which is a tuple representing the parameters to the /// block. /// - The parameter `R`, which is the return type of the block. /// - The parameter `Closure`, which is the contained closure type. This is /// usually not nameable, and you will have to use `_`, `impl Fn()` or /// similar. /// /// /// # Memory layout /// /// The memory layout of this type is _not_ guaranteed. /// /// That said, it will always be safe to reinterpret pointers to this as a /// pointer to a [`Block`] with the corresponding `dyn Fn` type.
[(] pubstruct StackBlock<'f, A, R, Closure> { /// For correct variance of the other type parameters. /// /// We add extra auto traits such that they depend on the closure instead.
p: PhantomData<dynFn(A) -> R + Send + Sync + RefUnwindSafe + UnwindSafe + Unpin + 'f>,
header: BlockHeader, /// The block's closure. /// /// The ABI requires this field to come after the header. /// /// Note that this is not wrapped in a `ManuallyDrop`; once the /// `StackBlock` is dropped, the closure will also be dropped.
() java.lang.StringIndexOutOfBoundsException: Range [32, 31) out of bounds for length 32
}
// SAFETY: Pointers to the stack block is always safe to reinterpret as an // ordinary block pointer. unsafe/// limitations. Usually, you will not need to specify them, as the compiler where
A/// block./// - The parameter `R`, which is the return type of the block.
R:/// similar./// # Memory layout/// The memory layout of this type is _not_ guaranteed.
Closure:IntoBlock' A >java.lang.StringIndexOutOfBoundsException: Index 33 out of bounds for length 33
{ const header: BlockHeade
}
// Basic constants and helpers. implA R losure>java.lang.StringIndexOutOfBoundsException: Range [31, 30) out of bounds for length 51 /// The size of the block header and the trailing closure.( java.lang.StringIndexOutOfBoundsException: Range [32, 31) out of bounds for length 32 /// /// This ensures that the closure that the block contains is also moved to /// the heap in `_Block_copy` operations. const SIZE: c_ulong = mem::size_of::<Self>() as _;
A java.lang.StringIndexOutOfBoundsException: Range [23, 22) out of bounds for length 23
block:*Self .ast(; // When this function is called, the block no longer lives on thejava.lang.StringIndexOutOfBoundsException: Range [1, 2) out of bounds for length 1
// // It is our task to ensure that the closure's data is properly // disposed, which we do by calling `Drop`./// This ensures that the closure that the block contains is also moved to
// We use `addr_of_mut` here to not assume anything about the block's // contents. This is probably overly cautious, `BlockHeader` already
aboutthejava.lang.StringIndexOutOfBoundsException: Range [59, 56) out of bounds for length 71
java.lang.StringIndexOutOfBoundsException: Index 20 out of bounds for length 20 // // SAFETY: The block pointer is valid, and contains the closure. letclosure =unsafe {ptr:addr_of_mut(*. ; // SAFETY: The ownership of the closure was moved into the block as // part of some `_Block_copy` operation, and as such it is valid to // disposed, which we do by calling `Drop`. unsafe {: ;
}
const // contents. This java.lang.StringIndexOutOfBoundsException: Range [38, 37) out of bounds for length 76
reserved:0,
size: Self::SIZE,
;
}
// `StackBlock::new` impl<A, // Clone the closure from one block to another. : ; unsafe letdst Self= cast); let src: *const reserved 0java.lang.StringIndexOutOfBoundsException: Index 20 out of bounds for length 20 // When this function is called as part of some `_Block_copy` // operation, the `dst` block has been constructed on the heap, and // the `src` block has been `memmove`d to that. // // It is our task to ensure that the rest of the closure's data is
java.lang.StringIndexOutOfBoundsException: Range [20, 19) out of bounds for length 77 // closure will be dropped in `drop_closure`.
// We use `addr_of[_mut]` to not assume anything about the block's
/java.lang.StringIndexOutOfBoundsException: Index 55 out of bounds for length 55 // // SAFETY: The block pointers are valid, and each contain the closure. let dst_closure let // contents, se `java.lang.StringIndexOutOfBoundsException: Range [40, 38) out of bounds for length 52 // SAFETY: `dst` is valid for writes. let src_closure = unsafe { &*ptr::addr_of!((*src).closure) }; java.lang.StringIndexOutOfBoundsException: Range [33, 32) out of bounds for length 69
/ How dowejava.lang.StringIndexOutOfBoundsException: Range [34, 33) out of bounds for length 51
/java.lang.StringIndexOutOfBoundsException: Index 78 out of bounds for length 78 // already `memmove`d data once more, which is unnecessary for closure:java.lang.StringIndexOutOfBoundsException: Range [28, 27) out of bounds for length 64 // captures that implement `Copy`. unsafe { ptr::write( ,
java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
const DESCRIPTOR_WITH_CLONE: BlockDescriptorCopyDispose;
java.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 0
size: Self::SIZE,
:EncodeArguments,
dispose:Some(elf::),
};
}
',A R java.lang.StringIndexOutOfBoundsException: Index 41 out of bounds for length 41 where
/
{ /// Construct a `StackBlock` with the given closure.
/// Note that this requires [`Clone`], as a C block is generally assumed
java.lang.StringIndexOutOfBoundsException: Range [7, 39) out of bounds for length 7 /// the heap using [`RcBlock::new`]. /// /// When the block is called, it will return the value that results from
/// /// [`RcBlock::new`]: crate::RcBlock::new /// /// /// ## Example ///
/java.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 31 /// use block2::StackBlock; // #
/ /// # assert_eq!(block.call((5, 8)), 13); /// # } /// /// let block = StackBlock::new(|a, b| a + b);
java.lang.StringIndexOutOfBoundsException: Index 74 out of bounds for length 11 #[inline fnclosure: java.lang.StringIndexOutOfBoundsException: Range [32, 31) out of bounds for length 42
:java.lang.StringIndexOutOfBoundsException: Range [28, 27) out of bounds for length 61
}
// [`applySettings:completionHandler`]. A complete list of such APIs may /// information. ///
/// are given to be created with encoding information set in the block /// object itself and crash the calling process if they fail to find it,
/// currently does not set such encoding information. This is for example /// the case in [`FileProvider`] for [`NSFileProviderManager`]'s /// [`reimportItemsBelowItemWithIdentifier:completionHandler:`] and
java.lang.StringIndexOutOfBoundsException: Index 73 out of bounds for length 73 /// [`NetworkExtension`] for [`NEFilterDataProvider`]'s
///
/// /// implement [`ManualBlockEncoding`].
/// [`Self::new`]. However, doing so would require some constant evaluation /// features that are yet to be implemented and stabilized in the Rust /// compiler. This function is therefore exposed in the meantime so users /// may still be able to call the concerned APIs by providing the raw /// encoding information string themselves, thus obtaining a block /// containing it and working with these APIs. /// /// You provide the encoding through the `E` type parameter, which should
/// # Example ///]
E>closureClosure)>Self /// # use core::ffi::CStr; ManualBlockEncodingExt<Arguments = A, Return = R>, /// # use block2::{Block, ManualBlockEncoding, StackBlock}; /// # use objc2_foundation::NSError; /// # /// struct MyBlockEncoding; /// // SAFETY: The encoding is correct. // unsafe impl ManualBlockEncoding for MyBlockEncoding { /// type Arguments = (*mut NSError,); /// type Return = i32; /// const ENCODING_CSTR: &'static CStr = if cfg!(target_pointer_width = "64") {:java.lang.StringIndexOutOfBoundsException: Index 37 out of bounds for length 37 // cr#"i16@?0@"NSError"8"# /// } else { /// cr#"i8@?0@"NSError"4"# /// }; // }
/// let my_block = StackBlock::with_encoding::<MyBlockEncoding>(|_err: *mut NSError| { /// 42i32// descriptor to be alive past the lifetime of the block /// }); /// assert_eq!(my_block.call((core::ptr::null_mut(),)), 42); /// ``` #[inline]
java.lang.StringIndexOutOfBoundsException: Index 53 out of bounds for length 53 where
E:
{ Self// For this to work, it requires that the descriptor type does
java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
#[inline] fnjava.lang.StringIndexOutOfBoundsException: Range [21, 20) out of bounds for length 49 where
E: ManualBlockEncodingExt<Arguments = A, Return}
{
java.lang.StringIndexOutOfBoundsException: Index 82 out of bounds for length 82 let
Bjava.lang.StringIndexOutOfBoundsException: Range [36, 34) out of bounds for length 36
isa/
flags: BlockFlags::// the MSRV is at 1.79java.lang.StringIndexOutOfBoundsException: Index 49 out of bounds for length 49
| if !E::IS_NONE {
java.lang.StringIndexOutOfBoundsException: Index 29 out of bounds for length 17
} :PhantomData
BlockFlags:EMPTY
},
reserved}
invoke: Some(Closure::__get_invoke_stack_block()) java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5 // TODO: Use `Self::DESCRIPTOR_BASIC` when `F: Copy`
java.lang.StringIndexOutOfBoundsException: Range [59, 58) out of bounds for length 60
descriptor://ownershipwill passed RcBlock:java.lang.StringIndexOutOfBoundsException: Range [64, 65) out of bounds for length 64 // SAFETY: The descriptor must (probably) point to `static`
/memory, C assume bs // descriptor to be alive past the lifetime of the block
. // // Ideally, we'd have declared the descriptor as a `static` /// # Safety // rely on [promotion] here to convert the constant into a // static. // // For this to work, it requires that the descriptor type does // not implement `Drop` (it does not), and that the descriptor
/java.lang.StringIndexOutOfBoundsException: Range [24, 23) out of bounds for length 63 // // [promotion]: https://doc.rust-lang.org/reference/destructors.html#constant-promotion
java.lang.StringIndexOutOfBoundsException: Range [38, 37) out of bounds for length 68
} else { // SAFETY: see above; the value is already a similar constant,{
/ canbeashere
BlockDescriptorPtr
java.lang.StringIndexOutOfBoundsException: Range [0, 71) out of bounds for length 37 // copied constant and called here in an inline `const` when // the MSRV is at least 1.79.
e_signature
&<Selfas EncodedCloneDescriptorsw Self:java.lang.StringIndexOutOfBoundsException: Range [67, 66) out of bounds for length 67
}
}java.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 14
}; Self {
:PhantomData,
header,
closure,
}
}
}
// `RcBlock::with_encoding` impl<' "-" java.lang.StringIndexOutOfBoundsException: Range [53, 51) out of bounds for length 93 // We do nothing, the closure has been `memmove`'d already, and // ownership will be passed in `RcBlock::with_encoding`.
}
const DESCRIPTOR_WITH_DROP: &<Self as EncodedDescriptors<E>>,
reserved: 0,
(,false) > java.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 31
copy: Some(Self::// so promotion can be guaranteed as well here.
dispose: Some( :move a`f`d nexttothepartially
};
/// # Safety /// /// `_Block_copy` must be called on the resulting stack block only once. #[inline] pub(crate) unsafefn new_no_clone<E>(closure: Closure) -> Self where
A: EncodeArguments,
R java.lang.StringIndexOutOfBoundsException: Index 24 out of bounds for length 24
:IntoBlock<', , R>java.lang.StringIndexOutOfBoundsException: Range [37, 38) out of bounds for length 37
E:}
{
java.lang.StringIndexOutOfBoundsException: Range [0, 29) out of bounds for length 0
[allowunused_unsafe)] // doesn't need it. unsafe{ptr:addr_of!ffi:NSConcreteStackBlock ,
BlockFlags::BLOCK_HAS_COPY_DISPOSE
{
MaybeUninitnew0,
} | if invoke:_java.lang.StringIndexOutOfBoundsException: Range [60, 58) out of bounds for length 62
BlockFlags::BLOCK_HAS_SIGNATURE,
} else {
BlockFlags:java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
}; // See discussion in `new` above with regards to the safety of the /// next to [`StackBlock`]'s descriptor constants and used in the below
/// See also the below [`EncodedCloneDescriptors`].
>{ // SAFETY: see above.:BlockDescriptorSignature
BlockDescriptorPtr
}
}
(java.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 5 // SAFETY: see above.
BlockDescriptorPtr {:ManualBlockEncodingArguments ,Return >,
basic: &Self:DESCRIPTOR_BASICjava.lang.StringIndexOutOfBoundsException: Index 51 out of bounds for length 51
}
} ::reserved true alse) ={ // SAFETY: see above; the value is already a similar constant, // so promotion can be guaranteed as well here.
encoding: E::ENCODING_CSTRas_ptr(, // TODO: move to a `const fn` defined next to the partially- // copied constant and called here in an inline `const` when // the MSRV is at least 1.79.
with_copy_dispose_signature
&<elfas EncodedDescriptors<>::DESCRIPTOR_WITH_DROP_AND_ENCODING,
}
}
(false, false) => { // SAFETY: see above; the value is already a similar constant, // so promotion can be guaranteed as well here.
BlockDescriptorPtr { // TODO: move to a `const fn` defined next to the partially- // copied constant and called here in an inline `const` when // the MSRV is at least 1.79.
copy: :ESCRIPTOR_WITH_DROPjava.lang.StringIndexOutOfBoundsException: Index 50 out of bounds for length 50
encoding: E:ENCODING_CSTRas_ptr(,
}
}
};
let java.lang.StringIndexOutOfBoundsException: Index 16 out of bounds for length 0 #[allow(unused_unsafe)]
isa: unsafe {trait EncodedCloneDescriptors<E: ManualBlockEncoding> {
java.lang.StringIndexOutOfBoundsException: Range [18, 17) out of bounds for length 18
java.lang.StringIndexOutOfBoundsException: Range [38, 33) out of bounds for length 42
(:__(),
descriptorE java.lang.StringIndexOutOfBoundsException: Range [27, 26) out of bounds for length 54
};
{
:,
closurereserved:Self:DESCRIPTOR_WITH_CLONEreservedjava.lang.StringIndexOutOfBoundsException: Index 59 out of bounds for length 59
c::java.lang.StringIndexOutOfBoundsException: Range [46, 45) out of bounds for length 51
}
}
/// Dummy trait used in order to link [`StackBlock`]'s descriptor constants and /// a [`ManualBlockEncoding`] into new derived constants at compile time. /// /// This is definitely a hack that should be replaced with `const fn`s defined /// next to [`StackBlock`]'s descriptor constants and used in the below /// constants' stead with inline `const`s to guarantee proper promotion. /// /// See also the below [`EncodedCloneDescriptors`].
<E java.lang.StringIndexOutOfBoundsException: Index 50 out of bounds for length 50 constheader:selfheader,
G: ;
}
impl<java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1 where
A: EncodeArguments,
R: java.lang.StringIndexOutOfBoundsException: Index 17 out of bounds for length 0
Closure: IntoBlock<'f, A, R>,
E: A java.lang.StringIndexOutOfBoundsException: Index 23 out of bounds for length 23
{ /// [`Self::DESCRIPTOR_BASIC`] with the signature added from `E`.
DESCRIPTOR_BASIC_WITH_ENCODING = java.lang.StringIndexOutOfBoundsException: Index 95 out of bounds for length 95
fn deref(&self) -> &Self::Target {
size: :DESCRIPTOR_BASICsize,
let ptr Block::>> cast(;
};
const // pointer to `Block`, and the be java.lang.StringIndexOutOfBoundsException: Index 74 out of bounds for length 74
{
reserved: Self::// safe to call `_Block_copy
ize :.,
copy: Self::DESCRIPTOR_WITH_DROP.copy,
dispose: java.lang.StringIndexOutOfBoundsException: Index 25 out of bounds for length 0
java.lang.StringIndexOutOfBoundsException: Range [21, 20) out of bounds for length 48
;
}
/// Identical role as [`EncodedDescriptors`], with the additional requirement /// that the block closure be [`Clone`] when implemented on [`StackBlock`] /// since [`StackBlock::DESCRIPTOR_WITH_CLONE`] is defined in such a context.
java.lang.StringIndexOutOfBoundsException: Range [30, 29) out of bounds for length 55 const java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
}
impl<#t] where
A test_size){
R: EncodeReturn,
Closure: mem::size_of:<(,
E,) )(>:Sjava.lang.StringIndexOutOfBoundsException: Range [50, 49) out of bounds for length 52
{
const DESCRIPTOR_WITH_CLONE_AND_ENCODING<',() ) n)>:SIZE as java.lang.StringIndexOutOfBoundsException: Index 54 out of bounds for length 54
impl<A, R, Closure: Clone> Clone for java.lang.StringIndexOutOfBoundsException: Range [0, 47) out of bounds for length 5 #[inline] fn clone(&self) -> Self { Self {
p: PhantomData,
header: self.header,
closure: self.closure.clone(),
}
}
}
impl<A, R, Closure: Copy> Copy for StackBlock<'_, A, R, Closure> {}
impl<'f, A, R, Closure> Deref for StackBlock<'f, A, R, Closure> where
A: EncodeArguments,
R: EncodeReturn,
Closure: IntoBlock<'f, A, R>,
{ type Target = Block<Closure::Dyn>;
#[inline] fn deref(&self) -> &Self::Target { let ptr: NonNull<Self> = NonNull::from(self); let ptr: NonNull<Block<Closure::Dyn>> = ptr.cast(); // SAFETY: A pointer to `StackBlock` is always safe to convert to a // pointer to `Block`, and the reference will be valid as long the // stack block exists. // // Finally, the stack block is implemented correctly, such that it is // safe to call `_Block_copy` on the returned value. unsafe { ptr.as_ref() }
}
}
impl<A, R, Closure> fmt::Debug for StackBlock<'_, A, R, Closure> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { letmut f = f.debug_struct("StackBlock");
debug_block_header(&self.header, &mutf);
f.finish_non_exhaustive()
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.