Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  error.rs   Sprache: unbekannt

 
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Types needed to marshal [`server`](crate::server) errors back to C++ in Firefox. The main type
//! of this module is [`ErrorBuffer`](crate::server::ErrorBuffer).

use std::{
    error::Error,
    fmt::{self, Display, Formatter},
    os::raw::c_char,
    ptr,
};

use serde::{Deserialize, Serialize};

/// A non-owning representation of `mozilla::webgpu::ErrorBuffer` in C++, passed as an argument to
/// other functions in [this module](self).
///
/// C++ callers of Rust functions (presumably in `WebGPUParent.cpp`) that expect one of these
/// structs can create a `mozilla::webgpu::ErrorBuffer` object, and call its `ToFFI` method to
/// construct a value of this type, available to C++ as `mozilla::webgpu::ffi::WGPUErrorBuffer`. If
/// we catch a `Result::Err` in other functions of [this module](self), the error is converted to
/// this type.
#[repr(C)]
pub struct ErrorBuffer {
    /// The type of error that `string` is associated with. If this location is set to
    /// [`ErrorBufferType::None`] after being passed as an argument to a function in [this module](self),
    /// then the remaining fields are guaranteed to not have been altered by that function from
    /// their original state.
    r#type: *mut ErrorBufferType,
    /// The (potentially truncated) message associated with this error. A fixed-capacity,
    /// null-terminated UTF-8 string buffer owned by C++.
    ///
    /// When we convert WGPU errors to this type, we render the error as a string, copying into
    /// `message` up to `capacity - 1`, and null-terminate it.
    message: *mut c_char,
    message_capacity: usize,
}

impl ErrorBuffer {
    /// Fill this buffer with the textual representation of `error`.
    ///
    /// If the error message is too long, truncate it to `self.capacity`. In either case, the error
    /// message is always terminated by a zero byte.
    ///
    /// Note that there is no explicit indication of the message's length, only the terminating zero
    /// byte. If the textual form of `error` itself includes a zero byte (as Rust strings can), then
    /// the C++ code receiving this error message has no way to distinguish that from the
    /// terminating zero byte, and will see the message as shorter than it is.
    pub(crate) fn init(&mut self, error: impl HasErrorBufferType) {
        use std::fmt::Write;

        let mut message = format!("{}", error);
        let mut e = error.source();
        while let Some(source) = e {
            write!(message, ", caused by: {}", source).unwrap();
            e = source.source();
        }

        let err_ty = error.error_type();
        // SAFETY: We presume the pointer provided by the caller is safe to write to.
        unsafe { *self.r#type = err_ty };

        if matches!(err_ty, ErrorBufferType::None) {
            log::warn!("{message}");
            return;
        }

        assert_ne!(self.message_capacity, 0);
        // Since we need to store a nul terminator after the content, the
        // content length must always be strictly less than the buffer's
        // capacity.
        let length = if message.len() >= self.message_capacity {
            // Thanks to the structure of UTF-8, `std::is_char_boundary` is
            // O(1), so this should examine a few bytes at most.
            //
            // The largest value in this range is `self.message_capacity - 1`,
            // which is a safe length.
            let truncated_length = (0..self.message_capacity)
                .rfind(|&offset| message.is_char_boundary(offset))
                .unwrap_or(0);
            log::warn!(
                "Error message's length {} reached capacity {}, truncating to {}",
                message.len(),
                self.message_capacity,
                truncated_length,
            );
            truncated_length
        } else {
            message.len()
        };
        unsafe {
            ptr::copy_nonoverlapping(message.as_ptr(), self.message as *mut u8, length);
            *self.message.add(length) = 0;
        }
    }
}

/// Corresponds to an optional discriminant of [`GPUError`] type in the WebGPU API. Strongly
/// correlates to [`GPUErrorFilter`]s.
///
/// [`GPUError`]: https://gpuweb.github.io/gpuweb/#gpuerror
/// [`GPUErrorFilter`]: https://gpuweb.github.io/gpuweb/#enumdef-gpuerrorfilter
#[repr(u8)]
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub(crate) enum ErrorBufferType {
    None = 0,
    DeviceLost = 1,
    Internal = 2,
    OutOfMemory = 3,
    Validation = 4,
}

/// A trait for querying the [`ErrorBufferType`] classification of an error. Used by
/// [`ErrorBuffer::init`](crate::server::ErrorBuffer::init).
pub(crate) trait HasErrorBufferType: Error {
    fn error_type(&self) -> ErrorBufferType;
}

/// Representation an error whose error message is already rendered as a [`&str`], and has no error
/// sources. Used for convenience in [`server`](crate::server) code.
#[derive(Clone, Debug)]
pub(crate) struct ErrMsg<'a> {
    pub(crate) message: &'a str,
    pub(crate) r#type: ErrorBufferType,
}

impl Display for ErrMsg<'_> {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        let Self { message, r#type: _ } = self;
        write!(f, "{message}")
    }
}

impl Error for ErrMsg<'_> {}

impl HasErrorBufferType for ErrMsg<'_> {
    fn error_type(&self) -> ErrorBufferType {
        self.r#type
    }
}

/// Encapsulates implementations of [`HasErrorType`] for [`wgpu_core`] types.
mod foreign {
    use wgc::{
        binding_model::{
            CreateBindGroupError, CreateBindGroupLayoutError, CreatePipelineLayoutError,
            GetBindGroupLayoutError,
        },
        command::{
            ClearError, CommandEncoderError, ComputePassError, CopyError, CreateRenderBundleError,
            QueryError, QueryUseError, RenderBundleError, RenderPassError, ResolveError,
            TransferError,
        },
        device::{
            queue::{QueueSubmitError, QueueWriteError},
            DeviceError,
        },
        instance::{RequestAdapterError, RequestDeviceError},
        pipeline::{
            CreateComputePipelineError, CreateRenderPipelineError, CreateShaderModuleError,
        },
        resource::{
            BufferAccessError, CreateBufferError, CreateQuerySetError, CreateSamplerError,
            CreateTextureError, CreateTextureViewError, DestroyError,
        },
    };

    use super::{ErrorBufferType, HasErrorBufferType};

    impl HasErrorBufferType for RequestAdapterError {
        fn error_type(&self) -> ErrorBufferType {
            match self {
                RequestAdapterError::NotFound => ErrorBufferType::Validation,

                // N.B: forced non-exhaustiveness
                _ => ErrorBufferType::Validation,
            }
        }
    }

    impl HasErrorBufferType for RequestDeviceError {
        fn error_type(&self) -> ErrorBufferType {
            match self {
                RequestDeviceError::Device(e) => e.error_type(),

                RequestDeviceError::UnsupportedFeature(_)
                | RequestDeviceError::LimitsExceeded(_) => ErrorBufferType::Validation,

                // N.B: forced non-exhaustiveness
                _ => ErrorBufferType::Validation,
            }
        }
    }

    impl HasErrorBufferType for CreateBufferError {
        fn error_type(&self) -> ErrorBufferType {
            match self {
                CreateBufferError::Device(e) => e.error_type(),
                CreateBufferError::AccessError(e) => e.error_type(),

                CreateBufferError::UnalignedSize
                | CreateBufferError::InvalidUsage(_)
                | CreateBufferError::UsageMismatch(_)
                | CreateBufferError::MaxBufferSize { .. }
                | CreateBufferError::MissingDownlevelFlags(_) => ErrorBufferType::Validation,

                // N.B: forced non-exhaustiveness
                _ => ErrorBufferType::Validation,
            }
        }
    }

    impl HasErrorBufferType for BufferAccessError {
        fn error_type(&self) -> ErrorBufferType {
            match self {
                BufferAccessError::Device(e) => e.error_type(),

                BufferAccessError::Failed
                | BufferAccessError::InvalidResource(_)
                | BufferAccessError::DestroyedResource(_)
                | BufferAccessError::AlreadyMapped
                | BufferAccessError::MapAlreadyPending
                | BufferAccessError::MissingBufferUsage(_)
                | BufferAccessError::NotMapped
                | BufferAccessError::UnalignedRange
                | BufferAccessError::UnalignedOffset { .. }
                | BufferAccessError::UnalignedRangeSize { .. }
                | BufferAccessError::OutOfBoundsUnderrun { .. }
                | BufferAccessError::OutOfBoundsOverrun { .. }
                | BufferAccessError::NegativeRange { .. }
                | BufferAccessError::MapAborted => ErrorBufferType::Validation,

                // N.B: forced non-exhaustiveness
                _ => ErrorBufferType::Validation,
            }
        }
    }

    impl HasErrorBufferType for CreateTextureError {
        fn error_type(&self) -> ErrorBufferType {
            match self {
                CreateTextureError::Device(e) => e.error_type(),

                CreateTextureError::InvalidUsage(_)
                | CreateTextureError::InvalidDimension(_)
                | CreateTextureError::InvalidDepthDimension(_, _)
                | CreateTextureError::InvalidCompressedDimension(_, _)
                | CreateTextureError::InvalidMipLevelCount { .. }
                | CreateTextureError::InvalidFormatUsages(_, _, _)
                | CreateTextureError::InvalidViewFormat(_, _)
                | CreateTextureError::InvalidDimensionUsages(_, _)
                | CreateTextureError::InvalidMultisampledStorageBinding
                | CreateTextureError::InvalidMultisampledFormat(_)
                | CreateTextureError::InvalidSampleCount(..)
                | CreateTextureError::MultisampledNotRenderAttachment
                | CreateTextureError::MissingFeatures(_, _)
                | CreateTextureError::MissingDownlevelFlags(_) => ErrorBufferType::Validation,

                // N.B: forced non-exhaustiveness
                _ => ErrorBufferType::Validation,
            }
        }
    }

    impl HasErrorBufferType for CreateSamplerError {
        fn error_type(&self) -> ErrorBufferType {
            match self {
                CreateSamplerError::Device(e) => e.error_type(),

                CreateSamplerError::InvalidLodMinClamp(_)
                | CreateSamplerError::InvalidLodMaxClamp { .. }
                | CreateSamplerError::InvalidAnisotropy(_)
                | CreateSamplerError::InvalidFilterModeWithAnisotropy { .. }
                | CreateSamplerError::MissingFeatures(_) => ErrorBufferType::Validation,

                // N.B: forced non-exhaustiveness
                _ => ErrorBufferType::Validation,
            }
        }
    }

    impl HasErrorBufferType for CreateBindGroupLayoutError {
        fn error_type(&self) -> ErrorBufferType {
            match self {
                CreateBindGroupLayoutError::Device(e) => e.error_type(),

                CreateBindGroupLayoutError::ConflictBinding(_)
                | CreateBindGroupLayoutError::Entry { .. }
                | CreateBindGroupLayoutError::TooManyBindings(_)
                | CreateBindGroupLayoutError::InvalidBindingIndex { .. }
                | CreateBindGroupLayoutError::InvalidVisibility(_) => ErrorBufferType::Validation,

                // N.B: forced non-exhaustiveness
                _ => ErrorBufferType::Validation,
            }
        }
    }

    impl HasErrorBufferType for CreatePipelineLayoutError {
        fn error_type(&self) -> ErrorBufferType {
            match self {
                CreatePipelineLayoutError::Device(e) => e.error_type(),

                CreatePipelineLayoutError::InvalidResource(_)
                | CreatePipelineLayoutError::MisalignedPushConstantRange { .. }
                | CreatePipelineLayoutError::MissingFeatures(_)
                | CreatePipelineLayoutError::MoreThanOnePushConstantRangePerStage { .. }
                | CreatePipelineLayoutError::PushConstantRangeTooLarge { .. }
                | CreatePipelineLayoutError::TooManyBindings(_)
                | CreatePipelineLayoutError::TooManyGroups { .. } => ErrorBufferType::Validation,

                // N.B: forced non-exhaustiveness
                _ => ErrorBufferType::Validation,
            }
        }
    }

    impl HasErrorBufferType for CreateBindGroupError {
        fn error_type(&self) -> ErrorBufferType {
            match self {
                CreateBindGroupError::Device(e) => e.error_type(),

                CreateBindGroupError::InvalidResource(_)
                | CreateBindGroupError::BindingArrayPartialLengthMismatch { .. }
                | CreateBindGroupError::BindingArrayLengthMismatch { .. }
                | CreateBindGroupError::BindingArrayZeroLength
                | CreateBindGroupError::BindingRangeTooLarge { .. }
                | CreateBindGroupError::BindingSizeTooSmall { .. }
                | CreateBindGroupError::BindingZeroSize(_)
                | CreateBindGroupError::BindingsNumMismatch { .. }
                | CreateBindGroupError::DuplicateBinding(_)
                | CreateBindGroupError::MissingBindingDeclaration(_)
                | CreateBindGroupError::MissingBufferUsage(_)
                | CreateBindGroupError::MissingTextureUsage(_)
                | CreateBindGroupError::SingleBindingExpected
                | CreateBindGroupError::UnalignedBufferOffset(_, _, _)
                | CreateBindGroupError::BufferRangeTooLarge { .. }
                | CreateBindGroupError::WrongBindingType { .. }
                | CreateBindGroupError::InvalidTextureMultisample { .. }
                | CreateBindGroupError::InvalidTextureSampleType { .. }
                | CreateBindGroupError::InvalidTextureDimension { .. }
                | CreateBindGroupError::InvalidStorageTextureFormat { .. }
                | CreateBindGroupError::InvalidStorageTextureMipLevelCount { .. }
                | CreateBindGroupError::WrongSamplerComparison { .. }
                | CreateBindGroupError::WrongSamplerFiltering { .. }
                | CreateBindGroupError::DepthStencilAspect
                | CreateBindGroupError::StorageReadNotSupported(_)
                | CreateBindGroupError::ResourceUsageCompatibility(_)
                | CreateBindGroupError::DestroyedResource(_) => ErrorBufferType::Validation,

                // N.B: forced non-exhaustiveness
                _ => ErrorBufferType::Validation,
            }
        }
    }

    impl HasErrorBufferType for CreateShaderModuleError {
        fn error_type(&self) -> ErrorBufferType {
            match self {
                CreateShaderModuleError::Device(e) => e.error_type(),

                CreateShaderModuleError::Generation => ErrorBufferType::Internal,

                CreateShaderModuleError::Parsing(_)
                | CreateShaderModuleError::Validation(_)
                | CreateShaderModuleError::MissingFeatures(_)
                | CreateShaderModuleError::InvalidGroupIndex { .. } => ErrorBufferType::Validation,

                // N.B: forced non-exhaustiveness
                _ => ErrorBufferType::Validation,
            }
        }
    }

    impl HasErrorBufferType for CreateComputePipelineError {
        fn error_type(&self) -> ErrorBufferType {
            match self {
                CreateComputePipelineError::Device(e) => e.error_type(),

                CreateComputePipelineError::Internal(_) => ErrorBufferType::Internal,

                CreateComputePipelineError::InvalidResource(_)
                | CreateComputePipelineError::Implicit(_)
                | CreateComputePipelineError::Stage(_)
                | CreateComputePipelineError::MissingDownlevelFlags(_) => {
                    ErrorBufferType::Validation
                }

                // N.B: forced non-exhaustiveness
                _ => ErrorBufferType::Validation,
            }
        }
    }

    impl HasErrorBufferType for CreateRenderPipelineError {
        fn error_type(&self) -> ErrorBufferType {
            match self {
                CreateRenderPipelineError::Device(e) => e.error_type(),

                CreateRenderPipelineError::Internal { .. } => ErrorBufferType::Internal,

                CreateRenderPipelineError::ColorAttachment(_)
                | CreateRenderPipelineError::InvalidResource(_)
                | CreateRenderPipelineError::Implicit(_)
                | CreateRenderPipelineError::ColorState(_, _)
                | CreateRenderPipelineError::DepthStencilState(_)
                | CreateRenderPipelineError::InvalidSampleCount(_)
                | CreateRenderPipelineError::TooManyVertexBuffers { .. }
                | CreateRenderPipelineError::TooManyVertexAttributes { .. }
                | CreateRenderPipelineError::VertexStrideTooLarge { .. }
                | CreateRenderPipelineError::UnalignedVertexStride { .. }
                | CreateRenderPipelineError::InvalidVertexAttributeOffset { .. }
                | CreateRenderPipelineError::ShaderLocationClash(_)
                | CreateRenderPipelineError::StripIndexFormatForNonStripTopology { .. }
                | CreateRenderPipelineError::ConservativeRasterizationNonFillPolygonMode
                | CreateRenderPipelineError::MissingFeatures(_)
                | CreateRenderPipelineError::MissingDownlevelFlags(_)
                | CreateRenderPipelineError::Stage { .. }
                | CreateRenderPipelineError::UnalignedShader { .. } => ErrorBufferType::Validation,

                // N.B: forced non-exhaustiveness
                _ => ErrorBufferType::Validation,
            }
        }
    }

    impl HasErrorBufferType for RenderBundleError {
        fn error_type(&self) -> ErrorBufferType {
            // We can't classify this ourselves, because inner error classification is private. May
            // need some upstream work to do this properly.
            ErrorBufferType::Validation
        }
    }

    impl HasErrorBufferType for DeviceError {
        fn error_type(&self) -> ErrorBufferType {
            match self {
                DeviceError::Invalid(_) | DeviceError::DeviceMismatch(_) => {
                    ErrorBufferType::Validation
                }
                DeviceError::Lost => ErrorBufferType::DeviceLost,
                DeviceError::OutOfMemory => ErrorBufferType::OutOfMemory,
                DeviceError::ResourceCreationFailed => ErrorBufferType::Internal,
                _ => ErrorBufferType::Internal,
            }
        }
    }

    impl HasErrorBufferType for CreateTextureViewError {
        fn error_type(&self) -> ErrorBufferType {
            match self {
                CreateTextureViewError::InvalidTextureViewDimension { .. }
                | CreateTextureViewError::InvalidResource(_)
                | CreateTextureViewError::InvalidMultisampledTextureViewDimension(_)
                | CreateTextureViewError::InvalidCubemapTextureDepth { .. }
                | CreateTextureViewError::InvalidCubemapArrayTextureDepth { .. }
                | CreateTextureViewError::InvalidCubeTextureViewSize
                | CreateTextureViewError::ZeroMipLevelCount
                | CreateTextureViewError::ZeroArrayLayerCount
                | CreateTextureViewError::TooManyMipLevels { .. }
                | CreateTextureViewError::TooManyArrayLayers { .. }
                | CreateTextureViewError::InvalidArrayLayerCount { .. }
                | CreateTextureViewError::InvalidAspect { .. }
                | CreateTextureViewError::FormatReinterpretation { .. }
                | CreateTextureViewError::DestroyedResource(_) => ErrorBufferType::Validation,

                // N.B: forced non-exhaustiveness
                _ => ErrorBufferType::Validation,
            }
        }
    }

    impl HasErrorBufferType for CopyError {
        fn error_type(&self) -> ErrorBufferType {
            match self {
                CopyError::Encoder(e) => e.error_type(),
                CopyError::Transfer(e) => e.error_type(),

                CopyError::InvalidResource(_) => ErrorBufferType::Validation,

                // N.B: forced non-exhaustiveness
                _ => ErrorBufferType::Validation,
            }
        }
    }

    impl HasErrorBufferType for TransferError {
        fn error_type(&self) -> ErrorBufferType {
            match self {
                TransferError::MemoryInitFailure(e) => e.error_type(),

                TransferError::SameSourceDestinationBuffer
                | TransferError::BufferOverrun { .. }
                | TransferError::TextureOverrun { .. }
                | TransferError::InvalidTextureAspect { .. }
                | TransferError::InvalidTextureMipLevel { .. }
                | TransferError::InvalidDimensionExternal
                | TransferError::UnalignedBufferOffset(_)
                | TransferError::UnalignedCopySize(_)
                | TransferError::UnalignedCopyWidth
                | TransferError::UnalignedCopyHeight
                | TransferError::UnalignedCopyOriginX
                | TransferError::UnalignedCopyOriginY
                | TransferError::UnalignedBytesPerRow
                | TransferError::UnspecifiedBytesPerRow
                | TransferError::UnspecifiedRowsPerImage
                | TransferError::InvalidBytesPerRow
                | TransferError::InvalidRowsPerImage
                | TransferError::CopySrcMissingAspects
                | TransferError::CopyDstMissingAspects
                | TransferError::CopyAspectNotOne
                | TransferError::CopyFromForbiddenTextureFormat { .. }
                | TransferError::CopyToForbiddenTextureFormat { .. }
                | TransferError::ExternalCopyToForbiddenTextureFormat(_)
                | TransferError::TextureFormatsNotCopyCompatible { .. }
                | TransferError::MissingDownlevelFlags(_)
                | TransferError::InvalidSampleCount { .. }
                | TransferError::InvalidMipLevel { .. } => ErrorBufferType::Validation,

                // N.B: forced non-exhaustiveness
                _ => ErrorBufferType::Validation,
            }
        }
    }

    impl HasErrorBufferType for ComputePassError {
        fn error_type(&self) -> ErrorBufferType {
            // We can't classify this ourselves, because inner error classification is private. We
            // may need some upstream work to do this properly. For now, we trust that this opaque
            // type only ever represents `Validation`.
            ErrorBufferType::Validation
        }
    }

    impl HasErrorBufferType for QueryError {
        fn error_type(&self) -> ErrorBufferType {
            match self {
                QueryError::Encoder(e) => e.error_type(),
                QueryError::Use(e) => e.error_type(),
                QueryError::Resolve(e) => e.error_type(),

                QueryError::InvalidResource(_) => ErrorBufferType::Validation,

                // N.B: forced non-exhaustiveness
                _ => ErrorBufferType::Validation,
            }
        }
    }

    impl HasErrorBufferType for QueryUseError {
        fn error_type(&self) -> ErrorBufferType {
            // We can't classify this ourselves, because inner error classification is private. We
            // may need some upstream work to do this properly. For now, we trust that this opaque
            // type only ever represents `Validation`.
            ErrorBufferType::Validation
        }
    }

    impl HasErrorBufferType for ResolveError {
        fn error_type(&self) -> ErrorBufferType {
            // We can't classify this ourselves, because inner error classification is private. We
            // may need some upstream work to do this properly. For now, we trust that this opaque
            // type only ever represents `Validation`.
            ErrorBufferType::Validation
        }
    }

    impl HasErrorBufferType for RenderPassError {
        fn error_type(&self) -> ErrorBufferType {
            // TODO: This type's `inner` member has an `OutOfMemory` variant. We definitely need to
            // expose this upstream, or move this implementation upstream.
            //
            // Bug for tracking: https://bugzilla.mozilla.org/show_bug.cgi?id=1840926
            ErrorBufferType::Validation
        }
    }

    impl HasErrorBufferType for ClearError {
        fn error_type(&self) -> ErrorBufferType {
            // We can't classify this ourselves, because inner error classification is private. We
            // may need some upstream work to do this properly. For now, we trust that this opaque
            // type only ever represents `Validation`.
            ErrorBufferType::Validation
        }
    }

    impl HasErrorBufferType for CommandEncoderError {
        fn error_type(&self) -> ErrorBufferType {
            // We can't classify this ourselves, because inner error classification is private. We
            // may need some upstream work to do this properly. For now, we trust that this opaque
            // type only ever represents `Validation`.
            ErrorBufferType::Validation
        }
    }

    impl HasErrorBufferType for QueueSubmitError {
        fn error_type(&self) -> ErrorBufferType {
            match self {
                QueueSubmitError::Queue(e) => e.error_type(),
                QueueSubmitError::Unmap(e) => e.error_type(),

                QueueSubmitError::DestroyedResource(_)
                | QueueSubmitError::BufferStillMapped(_)
                | QueueSubmitError::InvalidResource(_) => ErrorBufferType::Validation,

                // N.B: forced non-exhaustiveness
                _ => ErrorBufferType::Validation,
            }
        }
    }

    impl HasErrorBufferType for QueueWriteError {
        fn error_type(&self) -> ErrorBufferType {
            match self {
                QueueWriteError::Queue(e) => e.error_type(),
                QueueWriteError::Transfer(e) => e.error_type(),
                QueueWriteError::MemoryInitFailure(e) => e.error_type(),

                // N.B: forced non-exhaustiveness
                _ => ErrorBufferType::Validation,
            }
        }
    }

    impl HasErrorBufferType for GetBindGroupLayoutError {
        fn error_type(&self) -> ErrorBufferType {
            // We can't classify this ourselves, because inner error classification is private. We
            // may need some upstream work to do this properly. For now, we trust that this opaque
            // type only ever represents `Validation`.
            ErrorBufferType::Validation
        }
    }

    impl HasErrorBufferType for CreateRenderBundleError {
        fn error_type(&self) -> ErrorBufferType {
            // We can't classify this ourselves, because inner error classification is private. We
            // may need some upstream work to do this properly. For now, we trust that this opaque
            // type only ever represents `Validation`.
            ErrorBufferType::Validation
        }
    }

    impl HasErrorBufferType for DestroyError {
        fn error_type(&self) -> ErrorBufferType {
            ErrorBufferType::Validation
        }
    }

    impl HasErrorBufferType for CreateQuerySetError {
        fn error_type(&self) -> ErrorBufferType {
            match self {
                CreateQuerySetError::Device(e) => e.error_type(),
                CreateQuerySetError::ZeroCount
                | CreateQuerySetError::TooManyQueries { .. }
                | CreateQuerySetError::MissingFeatures(..) => ErrorBufferType::Validation,
                // N.B: forced non-exhaustiveness
                _ => ErrorBufferType::Validation,
            }
        }
    }
}

[ 0.44Quellennavigators  Projekt   ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge