Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/third_party/rust/block2/src/   (Firefox Browser Version 153.0.1©)  Datei vom 27.6.2026 mit Größe 12 kB image not shown  

Quelle  abi.rs

  Sprache: Rust
 

//! The documentation for these bindings is a mix from GNUStep's and Apple's
//! sources, but the [ABI specification][ABI] is really the place you should
//! be looking!
//!
//! [ABI]: https://clang.llvm.org/docs/Block-ABI-Apple.html
#![allow(unused)]

use core::ffi::{c_char, c_int, c_ulong, c_void};
use core::fmt;
use core::mem::MaybeUninit;
use core::ops::{BitAnd, BitOr};

use alloc::format;

use crate::ffi::Class;

/// Block descriptor flags.
#[repr(transparent)]
#[derive(Clone, Copy, PartialEq, Eq)]
pub(cratestruct BlockFlags(pub(crate) c_int);

impl BlockFlags {
    pub(crateconst EMPTY: Self = Self(0);

    /// Note: Not public ABI.
    const BLOCK_DEALLOCATING: Self = Self(0x0001);

    /// Note: Not public ABI.
    const BLOCK_REFCOUNT_MASK: Self = Self(if cfg!(feature = "gnustep-1-7") {
        // Mask for the reference count in byref structure's flags field. The low
        // 3 bytes are reserved for the reference count, the top byte for the flags.
        0x00ffffff
    } else if cfg!(any(feature = "compiler-rt", feature = "unstable-objfw")) {
        0xffff
    } else if cfg!(target_vendor = "apple") {
        0xfffe // runtime
    } else {
        0
    });

    /// Note: Not public ABI.
    const BLOCK_INLINE_LAYOUT_STRING: Self = Self(1 << 21);

    /// Note: Not public ABI.
    const BLOCK_SMALL_DESCRIPTOR: Self = Self(1 << 22);

    pub(crateconst BLOCK_IS_NOESCAPE: Self = Self(1 << 23);

    /// Note: Not public ABI.
    const BLOCK_NEEDS_FREE: Self = Self(1 << 24);

    /// The block descriptor contains copy and dispose helpers.
    pub(crateconst BLOCK_HAS_COPY_DISPOSE: Self = Self(1 << 25);

    /// Helpers have C++ code.
    #[doc(alias = "BLOCK_HAS_CXX_OBJ")]
    pub(crateconst BLOCK_HAS_CTOR: Self = Self(1 << 26);

    /// Note: Not public ABI.
    const BLOCK_IS_GC: Self = Self(1 << 27);

    /// Block is stored in global memory and does not need to be copied.
    pub(crateconst BLOCK_IS_GLOBAL: Self = Self(1 << 28);

    /// Block function uses a calling convention that returns a structure via a
    /// pointer passed in by the caller.
    ///
    /// match (BLOCK_USE_STRET, BLOCK_HAS_SIGNATURE) {
    ///     (false, false) => 10.6.ABI, no signature field available
    ///     (true, false)  => 10.6.ABI, no signature field available
    ///     (false, true)  => ABI.2010.3.16, regular calling convention, presence of signature field
    ///     (true, true)   => ABI.2010.3.16, stret calling convention, presence of signature field,
    /// }
    ///
    /// See <https://clang.llvm.org/docs/Block-ABI-Apple.html#high-level>
    #[doc(alias = "BLOCK_USE_SRET")]
    #[doc(alias = "BLOCK_HAS_DESCRIPTOR")]
    pub(crateconst BLOCK_USE_STRET: Self = Self(1 << 29);

    /// Block has an Objective-C type encoding.
    pub(crateconst BLOCK_HAS_SIGNATURE: Self = Self(1 << 30);

    /// Note: Not public ABI.
    const BLOCK_HAS_EXTENDED_LAYOUT: Self = Self(1 << 31);

    /// `const` version of [`PartialEq`].
    pub(crateconst fn equals(self, other: Self) -> bool {
        self.0 == other.0
    }

    /// `const` version of [`BitOr`]: adds the flags together.
    pub(crateconst fn union(self, other: Self) -> Self {
        Self(self.0 | other.0)
    }

    /// `const` version of [`BitAnd`]: only keeps the common flags.
    pub(crateconst fn intersect(self, other: Self) -> Self {
        Self(self.0 & other.0)
    }

    /// Returns `true` if and only if all the flags from `other` are enabled,
    /// i.e. `self & other == other`.
    pub(crateconst fn has(self, other: Self) -> bool {
        self.intersect(other).equals(other)
    }
}

/// See [`BlockFlags::union`].
impl BitOr for BlockFlags {
    type Output = Self;

    fn bitor(self, other: Self) -> Self {
        self.union(other)
    }
}

/// See [`BlockFlags::intersect`].
impl BitAnd for BlockFlags {
    type Output = Self;

    fn bitand(self, other: Self) -> Self {
        self.intersect(other)
    }
}

impl fmt::Debug for BlockFlags {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        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.has(Self::$flag));
            )*)
        }
        test_flags! {
            #[cfg(target_vendor = "apple")]
            deallocating: BLOCK_DEALLOCATING;
            #[cfg(target_vendor = "apple")]
            inline_layout_string: BLOCK_INLINE_LAYOUT_STRING;
            #[cfg(target_vendor = "apple")]
            small_descriptor: BLOCK_SMALL_DESCRIPTOR;
            #[cfg(target_vendor = "apple")]
            is_noescape: BLOCK_IS_NOESCAPE;
            #[cfg(target_vendor = "apple")]
            needs_free: BLOCK_NEEDS_FREE;
            has_copy_dispose: BLOCK_HAS_COPY_DISPOSE;
            has_ctor: BLOCK_HAS_CTOR;
            #[cfg(target_vendor = "apple")]
            is_gc: BLOCK_IS_GC;
            is_global: BLOCK_IS_GLOBAL;
            use_stret: BLOCK_USE_STRET;
            has_signature: BLOCK_HAS_SIGNATURE;
            #[cfg(target_vendor = "apple")]
            has_extended_layout: BLOCK_HAS_EXTENDED_LAYOUT;
        }

        f.field("over_referenced", &self.has(Self::BLOCK_REFCOUNT_MASK));
        f.field(
            "reference_count",
            &((*self & Self::BLOCK_REFCOUNT_MASK).0 >> 1),
        );

        f.finish_non_exhaustive()
    }
}

/// The value is of some id-like type, and should be copied as an Objective-C
/// object: i.e. by sending -retain or via the GC assign functions in GC mode
/// (not yet supported).
///
/// id, NSObject, __attribute__((NSObject)), block, ...
pub(crateconst BLOCK_FIELD_IS_OBJECT: c_int = 3;

/// The field is a block.  This must be copied by the block copy functions.
///
/// a block variable
pub(crateconst BLOCK_FIELD_IS_BLOCK: c_int = 7;

/// The field is an indirect reference to a variable declared with the __block
/// storage qualifier.
///
/// the on stack structure holding the __block variable
pub(crateconst BLOCK_FIELD_IS_BYREF: c_int = 8;

/// The field is an indirect reference to a variable declared with the __block
/// storage qualifier.
///
/// declared __weak, only used in byref copy helpers
pub(crateconst BLOCK_FIELD_IS_WEAK: c_int = 16;

/// The field is an indirect reference to a variable declared with the __block
/// storage qualifier.
///
/// called from __block (byref) copy/dispose support routines.
pub(crateconst BLOCK_BYREF_CALLER: c_int = 128;

/// The expected header of every block.
#[repr(C)]
#[doc(alias = "__block_literal")]
#[doc(alias = "Block_layout")]
#[doc(alias = "Block_basic")]
#[allow(missing_debug_implementations)]
#[derive(Clone, Copy)]
pub struct BlockHeader {
    /// Class pointer.
    ///
    /// Always initialised to &_NSConcreteStackBlock for blocks that are
    /// created on the stack or &_NSConcreteGlobalBlock for blocks that are
    /// created in global storage.
    pub isa: *const Class,
    /// Flags.
    ///
    /// See the `BlockFlags` enumerated type for possible values.
    ///
    /// Contains reference count in Apple's and ObjFW's runtime.
    #[doc(alias = "Block_flags")]
    pub(crate) flags: BlockFlags,
    /// Reserved.
    ///
    /// Initialized to 0 by the compiler, but is said to be uninitialized in
    /// the specification.
    ///
    /// Used for the reference count in GNUStep's and WinObjC's runtime.
    #[doc(alias = "Block_size")]
    pub(crate) reserved: MaybeUninit<c_int>,
    /// The function that implements the block.
    ///
    /// The first parameter is a pointer to this structure, the subsequent
    /// parameters are the block's explicit parameters.
    ///
    /// If the BLOCK_USE_SRET & BLOCK_HAS_SIGNATURE flag is set, there is an
    /// additional hidden parameter, which is a pointer to the space on the
    /// stack allocated to hold the return value.
    pub invoke: Option<unsafe extern "C-unwind" fn()>,
    /// The block's descriptor.
    pub(crate) descriptor: BlockDescriptorPtr,
}

/// The type of this is:
/// ```pseudo-code
/// match (BLOCK_HAS_COPY_DISPOSE, BLOCK_HAS_SIGNATURE) {
///     (false, false) => BlockDescriptor,
///     (true, false) => BlockDescriptorCopyDispose,
///     (false, true) => BlockDescriptorSignature,
///     (true, true) => BlockDescriptorCopyDisposeSignature,
/// }
/// ```
///
/// Since all of these start with `BlockDescriptor`, it is always safe to
/// use the `basic` field.
//
// Note: We use an union on top of the pointer, since otherwise the descriptor
// would be forced to have a greater size than is actually required.
#[repr(C)]
#[derive(Clone, Copy)]
pub(crate) union BlockDescriptorPtr {
    pub(crate) basic: *const BlockDescriptor,
    pub(crate) with_copy_dispose: *const BlockDescriptorCopyDispose,
    pub(crate) with_signature: *const BlockDescriptorSignature,
    pub(crate) with_copy_dispose_signature: *const BlockDescriptorCopyDisposeSignature,
}

/// Basic block descriptor.
#[repr(C)]
#[doc(alias = "__block_descriptor")]
#[doc(alias = "Block_descriptor_1")]
#[derive(Clone, Copy, Debug)]
pub(cratestruct BlockDescriptor {
    /// Reserved for future use. Currently always 0.
    pub(crate) reserved: c_ulong,
    /// Size of the block.
    pub(crate) size: c_ulong,
}

/// Block descriptor that contains copy and dispose operations.
///
/// Requires BLOCK_HAS_COPY_DISPOSE.
#[repr(C)]
#[doc(alias = "__block_descriptor")]
#[doc(alias = "Block_descriptor_2")]
#[derive(Clone, Copy, Debug)]
pub(cratestruct BlockDescriptorCopyDispose {
    /// Reserved for future use. Currently always 0.
    pub(crate) reserved: c_ulong,
    /// Size of the block.
    pub(crate) size: c_ulong,

    /// Helper to copy the block if it contains nontrivial copy operations.
    ///
    /// This may be NULL since macOS 11.0.1 in Apple's runtime, but this
    /// should not be relied on.
    pub(crate) copy: Option<unsafe extern "C-unwind" fn(dst: *mut c_void, src: *const c_void)>,
    /// Helper to destroy the block after being copied.
    ///
    /// This may be NULL since macOS 11.0.1 in Apple's runtime, but this
    /// should not be relied on.
    pub(crate) dispose: Option<unsafe extern "C-unwind" fn(src: *mut c_void)>,
}

/// Block descriptor that has an encoding / a signature.
///
/// Requires BLOCK_HAS_SIGNATURE.
#[repr(C)]
#[doc(alias = "__block_descriptor")]
#[doc(alias = "Block_descriptor_3")]
#[derive(Clone, Copy, Debug)]
pub(cratestruct BlockDescriptorSignature {
    /// Reserved for future use. Currently always 0.
    pub(crate) reserved: c_ulong,
    /// Size of the block.
    pub(crate) size: c_ulong,

    /// Objective-C type encoding of the block.
    #[doc(alias = "signature")]
    pub(crate) encoding: *const c_char,
}

/// Block descriptor that contains copy and dispose operations, and which
/// has an encoding / a signature.
///
/// Requires BLOCK_HAS_COPY_DISPOSE and BLOCK_HAS_SIGNATURE.
#[repr(C)]
#[doc(alias = "__block_descriptor")]
#[doc(alias = "Block_descriptor_2")]
#[doc(alias = "Block_descriptor_3")]
#[derive(Clone, Copy, Debug)]
pub(cratestruct BlockDescriptorCopyDisposeSignature {
    /// Reserved for future use. Currently always 0.
    pub(crate) reserved: c_ulong,
    /// Size of the block.
    pub(crate) size: c_ulong,

    /// Helper to copy the block if it contains nontrivial copy operations.
    ///
    /// This may be NULL since macOS 11.0.1 in Apple's runtime, but this
    /// should not be relied on.
    pub(crate) copy: Option<unsafe extern "C-unwind" fn(dst: *mut c_void, src: *const c_void)>,
    /// Helper to destroy the block after being copied.
    ///
    /// This may be NULL since macOS 11.0.1 in Apple's runtime, but this
    /// should not be relied on.
    pub(crate) dispose: Option<unsafe extern "C-unwind" fn(src: *mut c_void)>,

    /// Objective-C type encoding of the block.
    #[doc(alias = "signature")]
    pub(crate) encoding: *const c_char,
}

#[cfg(test)]
mod tests {
    use super::*;

    fn assert_no_trailing_padding<T>() {
        struct AddU8<T> {
            t: T,
            extra: u8,
        }
        assert_ne!(core::mem::size_of::<T>(), core::mem::size_of::<AddU8<T>>());
    }

    #[test]
    fn no_types_have_padding() {
        assert_no_trailing_padding::<BlockHeader>();
        assert_no_trailing_padding::<BlockDescriptorPtr>();
        assert_no_trailing_padding::<BlockDescriptor>();
        assert_no_trailing_padding::<BlockDescriptorCopyDispose>();
        assert_no_trailing_padding::<BlockDescriptorSignature>();
        assert_no_trailing_padding::<BlockDescriptorCopyDisposeSignature>();
    }
}

Messung V0.5 in Prozent
C=74 H=90 G=82

¤ Dauer der Verarbeitung: 0.21 Sekunden  (vorverarbeitet am  2026-08-25) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

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.