# This file was generated by stubgen-pyx v0.2.6 from cuda_core/cuda/core/texture/_array.pyx

from __future__ import annotations

from dataclasses import dataclass

import numpy
from cuda.bindings import cydriver
from cuda.core.typing import ArrayFormatType


@dataclass
class OpaqueArrayOptions:
    """Options for :meth:`cuda.core.Device.create_opaque_array`.

    Attributes
    ----------
    shape : tuple of int
        ``(width,)``, ``(width, height)``, or ``(width, height, depth)`` in
        elements.
    format : ArrayFormatType, str, or numpy.dtype
        Element format. Accepts an :class:`~cuda.core.typing.ArrayFormatType`,
        a plain string (e.g. ``"float32"``), or a NumPy dtype object.
    num_channels : int
        Channels per element. Must be 1, 2, or 4.
    is_surface_load_store : bool
        If True, allocate with ``CUDA_ARRAY3D_SURFACE_LDST`` so the array can be
        bound as a :class:`~cuda.core.texture.SurfaceObject` for kernel-side
        writes. Default False.

    .. versionadded:: 1.1.0
    """
    shape: tuple[int, ...]
    format: object
    num_channels: int
    is_surface_load_store: bool = False

    def __post_init__(self):
        ...

class OpaqueArray:
    """An opaque, hardware-laid-out GPU allocation for texture/surface access.

    Distinct from :class:`Buffer`: a ``CUarray`` has no exposed device pointer
    and can only be accessed from kernels through a :class:`TextureObject` or
    :class:`SurfaceObject`. Its memory layout is chosen by the driver for 2D/3D
    spatial locality.

    **Copy-only interop.** Because the layout is opaque and there is no linear
    device pointer, a ``OpaqueArray`` cannot expose ``__cuda_array_interface__`` /
    DLPack and cannot be shared zero-copy with NumPy, CuPy, numba-cuda, or
    PyTorch. Moving data in or out is therefore always a copy: use
    :meth:`copy_from` / :meth:`copy_to` against a linear :class:`Buffer` or a
    host buffer-protocol object. There is no allocation helper — allocate the
    linear :class:`Buffer` yourself (e.g. ``mr.allocate(arr.size_bytes,
    stream=s)``) and copy.

    Construct via :meth:`cuda.core.Device.create_opaque_array`. Only plain
    1D/2D/3D allocations are supported in this initial version; layered/cubemap/
    sparse variants will follow once their shape semantics are settled.

    .. versionadded:: 1.1.0
    """

    def close(self):
        """Release this object's reference to the underlying ``CUarray``.

        Destruction (``cuArrayDestroy``) happens via the handle's deleter when
        the last reference is dropped; for a non-owning handle (graphics interop
        or a mipmap-level view) nothing is destroyed. Idempotent: a second call
        (or destruction after ``close()``) is a no-op.
        """

    def __init__(self, *args, **kwargs):
        ...

    @classmethod
    def _from_handle(cls, handle: int, owning: bool, *, device_id=None):
        """Wrap an externally-allocated ``CUarray``.

        Intended for graphics interop (``cuGraphicsSubResourceGetMappedArray``)
        where the array is owned by the graphics API. With ``owning=False`` the
        underlying ``CUarray`` is never destroyed by this object. Shape, format,
        and channel count are queried from the driver.
        """

    @property
    def handle(self):
        """The underlying ``CUarray`` as an integer."""

    @property
    def shape(self):
        """Allocation shape, in elements."""

    @property
    def format(self):
        """The element :class:`~cuda.core.typing.ArrayFormatType`."""

    @property
    def num_channels(self):
        """Channels per element (1, 2, or 4)."""

    @property
    def element_bytes(self):
        """Bytes per element (format size * channels)."""

    @property
    def device(self):
        """The :class:`Device` this array was allocated on."""

    @property
    def is_surface_load_store(self):
        """True if this array was created with ``CUDA_ARRAY3D_SURFACE_LDST``
        and can be bound as a :class:`SurfaceObject`."""

    def _extent_bytes(self):
        """Return (width_bytes, height, depth) for cuMemcpy3D, with height/depth
        normalized to >=1 for lower-rank arrays."""

    def copy_from(self, src, *, stream) -> None:
        """Copy a full-array's worth of data into this array.

        Parameters
        ----------
        src : Buffer or buffer-protocol object
            Source data. Must contain at least ``self.size_bytes`` bytes
            of contiguous data.
        stream : Stream or GraphBuilder
            Stream to issue the copy on. A :class:`~cuda.core.graph.GraphBuilder`
            is accepted so the copy can be captured into a graph.
        """

    def copy_to(self, dst, *, stream):
        """Copy a full-array's worth of data out of this array.

        Parameters
        ----------
        dst : Buffer or writable buffer-protocol object
            Destination. Must have at least ``self.size_bytes`` bytes of
            writable, contiguous space.
        stream : Stream or GraphBuilder
            Stream to issue the copy on. A :class:`~cuda.core.graph.GraphBuilder`
            is accepted so the copy can be captured into a graph.

        Returns
        -------
        The ``dst`` object, for parity with :meth:`Buffer.copy_to`.
        """

    @property
    def size_bytes(self):
        """Total bytes of array storage (``prod(shape) * element_bytes``)."""

    def __enter__(self):
        ...

    def __exit__(self, exc_type, exc, tb):
        ...

    def __repr__(self):
        ...
_ARRAYFORMAT_TO_CU = {ArrayFormatType.UINT8: int(cydriver.CU_AD_FORMAT_UNSIGNED_INT8), ArrayFormatType.UINT16: int(cydriver.CU_AD_FORMAT_UNSIGNED_INT16), ArrayFormatType.UINT32: int(cydriver.CU_AD_FORMAT_UNSIGNED_INT32), ArrayFormatType.INT8: int(cydriver.CU_AD_FORMAT_SIGNED_INT8), ArrayFormatType.INT16: int(cydriver.CU_AD_FORMAT_SIGNED_INT16), ArrayFormatType.INT32: int(cydriver.CU_AD_FORMAT_SIGNED_INT32), ArrayFormatType.FLOAT16: int(cydriver.CU_AD_FORMAT_HALF), ArrayFormatType.FLOAT32: int(cydriver.CU_AD_FORMAT_FLOAT)}
_CU_TO_ARRAYFORMAT = {cu: fmt for fmt, cu in _ARRAYFORMAT_TO_CU.items()}
_NUMPY_DTYPE_TO_ARRAYFORMAT = {numpy.dtype(fmt.value): fmt for fmt in ArrayFormatType}
_FORMAT_ELEM_SIZE = {_ARRAYFORMAT_TO_CU[ArrayFormatType.UINT8]: 1, _ARRAYFORMAT_TO_CU[ArrayFormatType.INT8]: 1, _ARRAYFORMAT_TO_CU[ArrayFormatType.UINT16]: 2, _ARRAYFORMAT_TO_CU[ArrayFormatType.INT16]: 2, _ARRAYFORMAT_TO_CU[ArrayFormatType.FLOAT16]: 2, _ARRAYFORMAT_TO_CU[ArrayFormatType.UINT32]: 4, _ARRAYFORMAT_TO_CU[ArrayFormatType.INT32]: 4, _ARRAYFORMAT_TO_CU[ArrayFormatType.FLOAT32]: 4}

def _normalize_array_format(format):
    """Coerce ``format`` to an :class:`ArrayFormatType`.

    Accepts, in order of preference:

    * an :class:`ArrayFormatType`;
    * a plain ``str`` naming one of its values (e.g. ``"float32"``);
    * a NumPy dtype object (or anything ``numpy.dtype()`` accepts, such as
      ``numpy.float32``) whose canonical dtype maps 1:1 to one of the eight
      supported formats.

    Raises :class:`ValueError` on anything else."""

def _validate_format_channels(format, num_channels):
    """Validate the ``(format, num_channels)`` pair shared by the array,
    mipmap, and texture factories. Returns the normalized
    :class:`ArrayFormatType`. Raises on an invalid combination."""

def _validate_array_shape(shape):
    """Coerce ``shape`` to a tuple of ints and validate rank (1-3) and that
    every extent is >= 1. Returns the normalized tuple."""

def _create_opaque_array(options):
    """Allocate a new :class:`OpaqueArray` on the current device.

    Backs :meth:`cuda.core.Device.create_opaque_array`. ``options`` is an
    :class:`OpaqueArrayOptions` (or a mapping accepted by it); it is validated
    at construction, so ``shape`` is already a normalized tuple and ``format``
    an :class:`~cuda.core.typing.ArrayFormatType`.
    """