Skip to main content

bevy_mesh/
index.rs

1use bevy_reflect::Reflect;
2use core::iter;
3use core::iter::FusedIterator;
4#[cfg(feature = "serialize")]
5use serde::{Deserialize, Serialize};
6use thiserror::Error;
7use wgpu_types::IndexFormat;
8
9use crate::MeshAccessError;
10
11/// A disjunction of four iterators. This is necessary to have a well-formed type for the output
12/// of [`Mesh::triangles`](super::Mesh::triangles), which produces iterators of four different types depending on the
13/// branch taken.
14pub(crate) enum FourIterators<A, B, C, D> {
15    First(A),
16    Second(B),
17    Third(C),
18    Fourth(D),
19}
20
21impl<A, B, C, D, I> Iterator for FourIterators<A, B, C, D>
22where
23    A: Iterator<Item = I>,
24    B: Iterator<Item = I>,
25    C: Iterator<Item = I>,
26    D: Iterator<Item = I>,
27{
28    type Item = I;
29
30    fn next(&mut self) -> Option<Self::Item> {
31        match self {
32            FourIterators::First(iter) => iter.next(),
33            FourIterators::Second(iter) => iter.next(),
34            FourIterators::Third(iter) => iter.next(),
35            FourIterators::Fourth(iter) => iter.next(),
36        }
37    }
38
39    fn size_hint(&self) -> (usize, Option<usize>) {
40        match self {
41            FourIterators::First(iter) => iter.size_hint(),
42            FourIterators::Second(iter) => iter.size_hint(),
43            FourIterators::Third(iter) => iter.size_hint(),
44            FourIterators::Fourth(iter) => iter.size_hint(),
45        }
46    }
47}
48
49/// An error that occurred while trying to invert the winding of a [`Mesh`](super::Mesh).
50#[derive(#[automatically_derived]
impl ::core::fmt::Debug for MeshWindingInvertError {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            MeshWindingInvertError::WrongTopology =>
                ::core::fmt::Formatter::write_str(f, "WrongTopology"),
            MeshWindingInvertError::AbruptIndicesEnd =>
                ::core::fmt::Formatter::write_str(f, "AbruptIndicesEnd"),
            MeshWindingInvertError::MeshAccessError(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "MeshAccessError", &__self_0),
        }
    }
}Debug, fn from(source: MeshAccessError) -> Self {
    MeshWindingInvertError::MeshAccessError { 0: source }
}Error)]
51pub enum MeshWindingInvertError {
52    /// This error occurs when you try to invert the winding for a mesh with [`PrimitiveTopology::PointList`](super::PrimitiveTopology::PointList).
53    #[error("Mesh winding inversion does not work for primitive topology `PointList`")]
54    WrongTopology,
55
56    /// This error occurs when you try to invert the winding for a mesh with
57    /// * [`PrimitiveTopology::TriangleList`](super::PrimitiveTopology::TriangleList), but the indices are not in chunks of 3.
58    /// * [`PrimitiveTopology::LineList`](super::PrimitiveTopology::LineList), but the indices are not in chunks of 2.
59    #[error("Indices weren't in chunks according to topology")]
60    AbruptIndicesEnd,
61    #[error("Mesh access error: {0}")]
62    MeshAccessError(#[from] MeshAccessError),
63}
64
65/// An error that occurred while trying to extract a collection of triangles from a [`Mesh`](super::Mesh).
66#[derive(#[automatically_derived]
impl ::core::fmt::Debug for MeshTrianglesError {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            MeshTrianglesError::WrongTopology =>
                ::core::fmt::Formatter::write_str(f, "WrongTopology"),
            MeshTrianglesError::PositionsFormat =>
                ::core::fmt::Formatter::write_str(f, "PositionsFormat"),
            MeshTrianglesError::BadIndices =>
                ::core::fmt::Formatter::write_str(f, "BadIndices"),
            MeshTrianglesError::MeshAccessError(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "MeshAccessError", &__self_0),
        }
    }
}Debug, fn from(source: MeshAccessError) -> Self {
    MeshTrianglesError::MeshAccessError { 0: source }
}Error)]
67pub enum MeshTrianglesError {
68    #[error("Source mesh does not have primitive topology TriangleList or TriangleStrip")]
69    WrongTopology,
70
71    #[error("Source mesh position data is not Float32x3")]
72    PositionsFormat,
73
74    #[error("Face index data references vertices that do not exist")]
75    BadIndices,
76    #[error("mesh access error: {0}")]
77    MeshAccessError(#[from] MeshAccessError),
78}
79
80/// An array of indices into the [`VertexAttributeValues`](super::VertexAttributeValues) for a mesh.
81///
82/// It describes the order in which the vertex attributes should be joined into faces.
83#[derive(#[automatically_derived]
impl ::core::fmt::Debug for Indices {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            Indices::U16(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "U16",
                    &__self_0),
            Indices::U32(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "U32",
                    &__self_0),
        }
    }
}Debug, #[automatically_derived]
impl ::core::clone::Clone for Indices {
    #[inline]
    fn clone(&self) -> Indices {
        match self {
            Indices::U16(__self_0) =>
                Indices::U16(::core::clone::Clone::clone(__self_0)),
            Indices::U32(__self_0) =>
                Indices::U32(::core::clone::Clone::clone(__self_0)),
        }
    }
}Clone, const _: () =
    {
        impl bevy_reflect::GetTypeRegistration for Indices where  {
            fn get_type_registration() -> bevy_reflect::TypeRegistration {
                let mut registration =
                    bevy_reflect::TypeRegistration::of::<Self>();
                registration.insert::<bevy_reflect::ReflectFromPtr>(bevy_reflect::FromType::<Self>::from_type());
                registration.insert::<bevy_reflect::ReflectFromReflect>(bevy_reflect::FromType::<Self>::from_type());
                registration
            }
            #[inline(never)]
            fn register_type_dependencies(registry:
                    &mut bevy_reflect::TypeRegistry) {
                <Vec<u16> as
                        bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
                <Vec<u32> as
                        bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
            }
        }
        impl bevy_reflect::Typed for Indices where  {
            #[inline]
            fn type_info() -> &'static bevy_reflect::TypeInfo {
                static CELL: bevy_reflect::utility::NonGenericTypeInfoCell =
                    bevy_reflect::utility::NonGenericTypeInfoCell::new();
                CELL.get_or_set(||
                        {
                            bevy_reflect::TypeInfo::Enum(bevy_reflect::enums::EnumInfo::new::<Self>(&[bevy_reflect::enums::VariantInfo::Tuple(bevy_reflect::enums::TupleVariantInfo::new("U16",
                                                        &[bevy_reflect::UnnamedField::new::<Vec<u16>>(0usize)])),
                                                bevy_reflect::enums::VariantInfo::Tuple(bevy_reflect::enums::TupleVariantInfo::new("U32",
                                                        &[bevy_reflect::UnnamedField::new::<Vec<u32>>(0usize)]))]))
                        })
            }
        }
        #[allow(deprecated, reason =
        "derives on a deprecated type shouldn't be considered a usage")]
        impl bevy_reflect::TypePath for Indices where  {
            fn type_path() -> &'static str { "bevy_mesh::index::Indices" }
            fn short_type_path() -> &'static str { "Indices" }
            fn type_ident() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("Indices")
            }
            fn crate_name() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_mesh::index".split(':').next().unwrap())
            }
            fn module_path() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_mesh::index")
            }
        }
        impl bevy_reflect::Reflect for Indices where  {
            #[inline]
            fn into_any(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn ::core::any::Any> {
                self
            }
            #[inline]
            fn as_any(&self) -> &dyn ::core::any::Any { self }
            #[inline]
            fn as_any_mut(&mut self) -> &mut dyn ::core::any::Any { self }
            #[inline]
            fn into_reflect(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect> {
                self
            }
            #[inline]
            fn as_reflect(&self) -> &dyn bevy_reflect::Reflect { self }
            #[inline]
            fn as_reflect_mut(&mut self) -> &mut dyn bevy_reflect::Reflect {
                self
            }
            #[inline]
            fn set(&mut self,
                value:
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>)
                ->
                    ::core::result::Result<(),
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>> {
                *self = <dyn bevy_reflect::Reflect>::take(value)?;
                ::core::result::Result::Ok(())
            }
        }
        #[allow(non_upper_case_globals)]
        const _: () =
            {
                static __INVENTORY: ::inventory::Node =
                    ::inventory::Node {
                        value: &{
                                bevy_reflect::__macro_exports::auto_register::AutomaticReflectRegistrations(<Indices
                                        as
                                        bevy_reflect::__macro_exports::auto_register::RegisterForReflection>::__register)
                            },
                        next: ::inventory::__private::UnsafeCell::new(::inventory::__private::Option::None),
                    };
                #[link_section = ".text.startup"]
                unsafe extern "C" fn __ctor() {
                    unsafe {
                        ::inventory::ErasedNode::submit(__INVENTORY.value,
                            &__INVENTORY)
                    }
                }
                #[used]
                #[link_section = ".init_array"]
                static __CTOR: unsafe extern "C" fn() = __ctor;
            };
        impl bevy_reflect::enums::Enum for Indices where  {
            fn field(&self, __name_param: &str)
                -> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
                match self { _ => ::core::option::Option::None, }
            }
            fn field_at(&self, __index_param: usize)
                -> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
                match self {
                    Indices::U16 { 0: __value, .. } if __index_param == 0usize
                        => ::core::option::Option::Some(__value),
                    Indices::U32 { 0: __value, .. } if __index_param == 0usize
                        => ::core::option::Option::Some(__value),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_mut(&mut self, __name_param: &str)
                ->
                    ::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
                match self { _ => ::core::option::Option::None, }
            }
            fn field_at_mut(&mut self, __index_param: usize)
                ->
                    ::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
                match self {
                    Indices::U16 { 0: __value, .. } if __index_param == 0usize
                        => ::core::option::Option::Some(__value),
                    Indices::U32 { 0: __value, .. } if __index_param == 0usize
                        => ::core::option::Option::Some(__value),
                    _ => ::core::option::Option::None,
                }
            }
            fn index_of(&self, __name_param: &str)
                -> ::core::option::Option<usize> {
                match self { _ => ::core::option::Option::None, }
            }
            fn name_at(&self, __index_param: usize)
                -> ::core::option::Option<&str> {
                match self { _ => ::core::option::Option::None, }
            }
            fn iter_fields(&self) -> bevy_reflect::enums::VariantFieldIter {
                bevy_reflect::enums::VariantFieldIter::new(self)
            }
            #[inline]
            fn field_len(&self) -> usize {
                match self {
                    Indices::U16 { .. } => 1usize,
                    Indices::U32 { .. } => 1usize,
                    _ => 0,
                }
            }
            #[inline]
            fn variant_name(&self) -> &str {
                match self {
                    Indices::U16 { .. } => "U16",
                    Indices::U32 { .. } => "U32",
                    _ =>
                        ::core::panicking::panic("internal error: entered unreachable code"),
                }
            }
            #[inline]
            fn variant_index(&self) -> usize {
                match self {
                    Indices::U16 { .. } => 0usize,
                    Indices::U32 { .. } => 1usize,
                    _ =>
                        ::core::panicking::panic("internal error: entered unreachable code"),
                }
            }
            #[inline]
            fn variant_type(&self) -> bevy_reflect::enums::VariantType {
                match self {
                    Indices::U16 { .. } =>
                        bevy_reflect::enums::VariantType::Tuple,
                    Indices::U32 { .. } =>
                        bevy_reflect::enums::VariantType::Tuple,
                    _ =>
                        ::core::panicking::panic("internal error: entered unreachable code"),
                }
            }
            fn to_dynamic_enum(&self) -> bevy_reflect::enums::DynamicEnum {
                bevy_reflect::enums::DynamicEnum::from_ref::<Self>(self)
            }
        }
        impl bevy_reflect::PartialReflect for Indices where  {
            #[inline]
            fn get_represented_type_info(&self)
                -> ::core::option::Option<&'static bevy_reflect::TypeInfo> {
                ::core::option::Option::Some(<Self as
                            bevy_reflect::Typed>::type_info())
            }
            #[inline]
            fn try_apply(&mut self,
                __value_param: &dyn bevy_reflect::PartialReflect)
                -> ::core::result::Result<(), bevy_reflect::ApplyError> {
                if let bevy_reflect::ReflectRef::Enum(__value_param) =
                        bevy_reflect::PartialReflect::reflect_ref(__value_param) {
                    if bevy_reflect::enums::Enum::variant_name(self) ==
                            bevy_reflect::enums::Enum::variant_name(__value_param) {
                        match bevy_reflect::enums::Enum::variant_type(__value_param)
                            {
                            bevy_reflect::enums::VariantType::Struct => {
                                for field in
                                    bevy_reflect::enums::Enum::iter_fields(__value_param) {
                                    let name = field.name().unwrap();
                                    if let ::core::option::Option::Some(v) =
                                            bevy_reflect::enums::Enum::field_mut(self, name) {
                                        bevy_reflect::PartialReflect::try_apply(v, field.value())?;
                                    }
                                }
                            }
                            bevy_reflect::enums::VariantType::Tuple => {
                                for (index, field) in
                                    ::core::iter::Iterator::enumerate(bevy_reflect::enums::Enum::iter_fields(__value_param))
                                    {
                                    if let ::core::option::Option::Some(v) =
                                            bevy_reflect::enums::Enum::field_at_mut(self, index) {
                                        bevy_reflect::PartialReflect::try_apply(v, field.value())?;
                                    }
                                }
                            }
                            _ => {}
                        }
                    } else {
                        match bevy_reflect::enums::Enum::variant_name(__value_param)
                            {
                            "U16" => {
                                *self =
                                    Indices::U16 {
                                        0: {
                                            let __0 = __value_param.field_at(0usize);
                                            let __0 =
                                                __0.ok_or(bevy_reflect::ApplyError::MissingEnumField {
                                                            variant_name: ::core::convert::Into::into("U16"),
                                                            field_name: ::core::convert::Into::into(".0"),
                                                        })?;
                                            <Vec<u16> as
                                                            bevy_reflect::FromReflect>::from_reflect(__0).ok_or(bevy_reflect::ApplyError::MismatchedTypes {
                                                        from_type: ::core::convert::Into::into(bevy_reflect::DynamicTypePath::reflect_type_path(__0)),
                                                        to_type: ::core::convert::Into::into(<Vec<u16> as
                                                                    bevy_reflect::TypePath>::type_path()),
                                                    })?
                                        },
                                    }
                            }
                            "U32" => {
                                *self =
                                    Indices::U32 {
                                        0: {
                                            let __0 = __value_param.field_at(0usize);
                                            let __0 =
                                                __0.ok_or(bevy_reflect::ApplyError::MissingEnumField {
                                                            variant_name: ::core::convert::Into::into("U32"),
                                                            field_name: ::core::convert::Into::into(".0"),
                                                        })?;
                                            <Vec<u32> as
                                                            bevy_reflect::FromReflect>::from_reflect(__0).ok_or(bevy_reflect::ApplyError::MismatchedTypes {
                                                        from_type: ::core::convert::Into::into(bevy_reflect::DynamicTypePath::reflect_type_path(__0)),
                                                        to_type: ::core::convert::Into::into(<Vec<u32> as
                                                                    bevy_reflect::TypePath>::type_path()),
                                                    })?
                                        },
                                    }
                            }
                            name => {
                                return ::core::result::Result::Err(bevy_reflect::ApplyError::UnknownVariant {
                                            enum_name: ::core::convert::Into::into(bevy_reflect::DynamicTypePath::reflect_type_path(self)),
                                            variant_name: ::core::convert::Into::into(name),
                                        });
                            }
                        }
                    }
                } else {
                    return ::core::result::Result::Err(bevy_reflect::ApplyError::MismatchedKinds {
                                from_kind: bevy_reflect::PartialReflect::reflect_kind(__value_param),
                                to_kind: bevy_reflect::ReflectKind::Enum,
                            });
                }
                ::core::result::Result::Ok(())
            }
            fn reflect_kind(&self) -> bevy_reflect::ReflectKind {
                bevy_reflect::ReflectKind::Enum
            }
            fn reflect_ref(&self) -> bevy_reflect::ReflectRef {
                bevy_reflect::ReflectRef::Enum(self)
            }
            fn reflect_mut(&mut self) -> bevy_reflect::ReflectMut {
                bevy_reflect::ReflectMut::Enum(self)
            }
            fn reflect_owned(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                -> bevy_reflect::ReflectOwned {
                bevy_reflect::ReflectOwned::Enum(self)
            }
            #[inline]
            fn try_into_reflect(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    ::core::result::Result<bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>,
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect>> {
                ::core::result::Result::Ok(self)
            }
            #[inline]
            fn try_as_reflect(&self)
                -> ::core::option::Option<&dyn bevy_reflect::Reflect> {
                ::core::option::Option::Some(self)
            }
            #[inline]
            fn try_as_reflect_mut(&mut self)
                -> ::core::option::Option<&mut dyn bevy_reflect::Reflect> {
                ::core::option::Option::Some(self)
            }
            #[inline]
            fn into_partial_reflect(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect> {
                self
            }
            #[inline]
            fn as_partial_reflect(&self)
                -> &dyn bevy_reflect::PartialReflect {
                self
            }
            #[inline]
            fn as_partial_reflect_mut(&mut self)
                -> &mut dyn bevy_reflect::PartialReflect {
                self
            }
            fn reflect_hash(&self) -> ::core::option::Option<u64> {
                (bevy_reflect::enums::enum_hash)(self)
            }
            fn reflect_partial_eq(&self,
                value: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<bool> {
                (bevy_reflect::enums::enum_partial_eq)(self, value)
            }
            fn reflect_partial_cmp(&self,
                value: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<::core::cmp::Ordering> {
                (bevy_reflect::enums::enum_partial_cmp)(self, value)
            }
            #[inline]
            fn reflect_clone(&self)
                ->
                    ::core::result::Result<bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>,
                    bevy_reflect::ReflectCloneError> {
                ::core::result::Result::Ok(bevy_reflect::__macro_exports::alloc_utils::Box::new(::core::clone::Clone::clone(self)))
            }
        }
        impl bevy_reflect::FromReflect for Indices where  {
            fn from_reflect(__param0: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<Self> {
                if let bevy_reflect::ReflectRef::Enum(__param0) =
                        bevy_reflect::PartialReflect::reflect_ref(__param0) {
                    match bevy_reflect::enums::Enum::variant_name(__param0) {
                        "U16" =>
                            ::core::option::Option::Some(Indices::U16 {
                                    0: {
                                        let __0 = __param0.field_at(0usize);
                                        let __0 = __0?;
                                        <Vec<u16> as bevy_reflect::FromReflect>::from_reflect(__0)?
                                    },
                                }),
                        "U32" =>
                            ::core::option::Option::Some(Indices::U32 {
                                    0: {
                                        let __0 = __param0.field_at(0usize);
                                        let __0 = __0?;
                                        <Vec<u32> as bevy_reflect::FromReflect>::from_reflect(__0)?
                                    },
                                }),
                        name => ::core::option::Option::None,
                    }
                } else { ::core::option::Option::None }
            }
        }
    };Reflect, #[automatically_derived]
impl ::core::cmp::PartialEq for Indices {
    #[inline]
    fn eq(&self, other: &Indices) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (Indices::U16(__self_0), Indices::U16(__arg1_0)) =>
                    __self_0 == __arg1_0,
                (Indices::U32(__self_0), Indices::U32(__arg1_0)) =>
                    __self_0 == __arg1_0,
                _ => unsafe { ::core::intrinsics::unreachable() }
            }
    }
}PartialEq)]
84#[reflect(Clone)]
85#[cfg_attr(feature = "serialize", derive(#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications,
clippy :: absolute_paths,)]
const _: () =
    {
        #[allow(unused_extern_crates, clippy :: useless_attribute)]
        extern crate serde as _serde;
        ;
        #[automatically_derived]
        impl _serde::Serialize for Indices {
            fn serialize<__S>(&self, __serializer: __S)
                -> _serde::__private228::Result<__S::Ok, __S::Error> where
                __S: _serde::Serializer {
                match *self {
                    Indices::U16(ref __field0) =>
                        _serde::Serializer::serialize_newtype_variant(__serializer,
                            "Indices", 0u32, "U16", __field0),
                    Indices::U32(ref __field0) =>
                        _serde::Serializer::serialize_newtype_variant(__serializer,
                            "Indices", 1u32, "U32", __field0),
                }
            }
        }
    };Serialize, #[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications,
clippy :: absolute_paths,)]
const _: () =
    {
        #[allow(unused_extern_crates, clippy :: useless_attribute)]
        extern crate serde as _serde;
        ;
        #[automatically_derived]
        impl<'de> _serde::Deserialize<'de> for Indices {
            fn deserialize<__D>(__deserializer: __D)
                -> _serde::__private228::Result<Self, __D::Error> where
                __D: _serde::Deserializer<'de> {
                #[allow(non_camel_case_types)]
                #[doc(hidden)]
                enum __Field { __field0, __field1, }
                #[doc(hidden)]
                struct __FieldVisitor;
                #[automatically_derived]
                impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
                    type Value = __Field;
                    fn expecting(&self,
                        __formatter: &mut _serde::__private228::Formatter)
                        -> _serde::__private228::fmt::Result {
                        _serde::__private228::Formatter::write_str(__formatter,
                            "variant identifier")
                    }
                    fn visit_u64<__E>(self, __value: u64)
                        -> _serde::__private228::Result<Self::Value, __E> where
                        __E: _serde::de::Error {
                        match __value {
                            0u64 => _serde::__private228::Ok(__Field::__field0),
                            1u64 => _serde::__private228::Ok(__Field::__field1),
                            _ =>
                                _serde::__private228::Err(_serde::de::Error::invalid_value(_serde::de::Unexpected::Unsigned(__value),
                                        &"variant index 0 <= i < 2")),
                        }
                    }
                    fn visit_str<__E>(self, __value: &str)
                        -> _serde::__private228::Result<Self::Value, __E> where
                        __E: _serde::de::Error {
                        match __value {
                            "U16" => _serde::__private228::Ok(__Field::__field0),
                            "U32" => _serde::__private228::Ok(__Field::__field1),
                            _ => {
                                _serde::__private228::Err(_serde::de::Error::unknown_variant(__value,
                                        VARIANTS))
                            }
                        }
                    }
                    fn visit_bytes<__E>(self, __value: &[u8])
                        -> _serde::__private228::Result<Self::Value, __E> where
                        __E: _serde::de::Error {
                        match __value {
                            b"U16" => _serde::__private228::Ok(__Field::__field0),
                            b"U32" => _serde::__private228::Ok(__Field::__field1),
                            _ => {
                                let __value =
                                    &_serde::__private228::from_utf8_lossy(__value);
                                _serde::__private228::Err(_serde::de::Error::unknown_variant(__value,
                                        VARIANTS))
                            }
                        }
                    }
                }
                #[automatically_derived]
                impl<'de> _serde::Deserialize<'de> for __Field {
                    #[inline]
                    fn deserialize<__D>(__deserializer: __D)
                        -> _serde::__private228::Result<Self, __D::Error> where
                        __D: _serde::Deserializer<'de> {
                        _serde::Deserializer::deserialize_identifier(__deserializer,
                            __FieldVisitor)
                    }
                }
                #[doc(hidden)]
                struct __Visitor<'de> {
                    marker: _serde::__private228::PhantomData<Indices>,
                    lifetime: _serde::__private228::PhantomData<&'de ()>,
                }
                #[automatically_derived]
                impl<'de> _serde::de::Visitor<'de> for __Visitor<'de> {
                    type Value = Indices;
                    fn expecting(&self,
                        __formatter: &mut _serde::__private228::Formatter)
                        -> _serde::__private228::fmt::Result {
                        _serde::__private228::Formatter::write_str(__formatter,
                            "enum Indices")
                    }
                    fn visit_enum<__A>(self, __data: __A)
                        -> _serde::__private228::Result<Self::Value, __A::Error>
                        where __A: _serde::de::EnumAccess<'de> {
                        match _serde::de::EnumAccess::variant(__data)? {
                            (__Field::__field0, __variant) =>
                                _serde::__private228::Result::map(_serde::de::VariantAccess::newtype_variant::<Vec<u16>>(__variant),
                                    Indices::U16),
                            (__Field::__field1, __variant) =>
                                _serde::__private228::Result::map(_serde::de::VariantAccess::newtype_variant::<Vec<u32>>(__variant),
                                    Indices::U32),
                        }
                    }
                }
                #[doc(hidden)]
                const VARIANTS: &'static [&'static str] = &["U16", "U32"];
                _serde::Deserializer::deserialize_enum(__deserializer,
                    "Indices", VARIANTS,
                    __Visitor {
                        marker: _serde::__private228::PhantomData::<Indices>,
                        lifetime: _serde::__private228::PhantomData,
                    })
            }
        }
    };Deserialize))]
86pub enum Indices {
87    U16(Vec<u16>),
88    U32(Vec<u32>),
89}
90
91impl Indices {
92    /// Returns an iterator over the indices.
93    pub fn iter(&self) -> impl Iterator<Item = usize> + '_ {
94        match self {
95            Indices::U16(vec) => IndicesIter::U16(vec.iter()),
96            Indices::U32(vec) => IndicesIter::U32(vec.iter()),
97        }
98    }
99
100    /// Returns the number of indices.
101    pub fn len(&self) -> usize {
102        match self {
103            Indices::U16(vec) => vec.len(),
104            Indices::U32(vec) => vec.len(),
105        }
106    }
107
108    /// Returns `true` if there are no indices.
109    pub fn is_empty(&self) -> bool {
110        match self {
111            Indices::U16(vec) => vec.is_empty(),
112            Indices::U32(vec) => vec.is_empty(),
113        }
114    }
115
116    /// Add an index. If the index is greater than `u16::MAX`,
117    /// the storage will be converted to `u32`.
118    pub fn push(&mut self, index: u32) {
119        self.extend([index]);
120    }
121}
122
123/// Extend the indices with indices from an iterator.
124/// Semantically equivalent to calling [`push`](Indices::push) for each element in the iterator,
125/// but more efficient.
126///
127/// [`Indices::U16`] will be converted to [`Indices::U32`] if there is primitive restart value [`u16::MAX`] or any value greater than [`u16::MAX`].
128impl Extend<u32> for Indices {
129    fn extend<T: IntoIterator<Item = u32>>(&mut self, iter: T) {
130        let mut iter = iter.into_iter();
131        match self {
132            Indices::U32(indices) => indices.extend(iter),
133            Indices::U16(indices) => {
134                indices.reserve(iter.size_hint().0);
135                while let Some(index) = iter.next() {
136                    if index < u16::MAX as u32 {
137                        indices.push(index as u16);
138                    } else {
139                        let new_vec = indices
140                            .iter()
141                            .map(|&index| u32::from(index))
142                            .chain(iter::once(index))
143                            .chain(iter)
144                            .collect::<Vec<u32>>();
145                        *self = Indices::U32(new_vec);
146                        break;
147                    }
148                }
149            }
150        }
151    }
152}
153
154/// An Iterator for the [`Indices`].
155enum IndicesIter<'a> {
156    U16(core::slice::Iter<'a, u16>),
157    U32(core::slice::Iter<'a, u32>),
158}
159
160impl Iterator for IndicesIter<'_> {
161    type Item = usize;
162
163    fn next(&mut self) -> Option<Self::Item> {
164        match self {
165            IndicesIter::U16(iter) => iter.next().map(|val| *val as usize),
166            IndicesIter::U32(iter) => iter.next().map(|val| *val as usize),
167        }
168    }
169
170    fn size_hint(&self) -> (usize, Option<usize>) {
171        match self {
172            IndicesIter::U16(iter) => iter.size_hint(),
173            IndicesIter::U32(iter) => iter.size_hint(),
174        }
175    }
176}
177
178impl<'a> ExactSizeIterator for IndicesIter<'a> {}
179
180impl<'a> FusedIterator for IndicesIter<'a> {}
181
182impl From<&Indices> for IndexFormat {
183    fn from(indices: &Indices) -> Self {
184        match indices {
185            Indices::U16(_) => IndexFormat::Uint16,
186            Indices::U32(_) => IndexFormat::Uint32,
187        }
188    }
189}
190
191#[cfg(test)]
192mod tests {
193    use crate::Indices;
194    use wgpu_types::IndexFormat;
195
196    #[test]
197    fn test_indices_push() {
198        let mut indices = Indices::U16(Vec::new());
199        indices.push(10);
200        assert_eq!(IndexFormat::Uint16, IndexFormat::from(&indices));
201        assert_eq!(vec![10], indices.iter().collect::<Vec<_>>());
202
203        // Add a value that is too large for `u16` so the storage should be converted to `U32`.
204        indices.push(0x10000);
205        assert_eq!(IndexFormat::Uint32, IndexFormat::from(&indices));
206        assert_eq!(vec![10, 0x10000], indices.iter().collect::<Vec<_>>());
207
208        indices.push(20);
209        indices.push(0x20000);
210        assert_eq!(IndexFormat::Uint32, IndexFormat::from(&indices));
211        assert_eq!(
212            vec![10, 0x10000, 20, 0x20000],
213            indices.iter().collect::<Vec<_>>()
214        );
215    }
216
217    #[test]
218    fn test_indices_extend() {
219        let mut indices = Indices::U16(Vec::new());
220        indices.extend([10, 11]);
221        assert_eq!(IndexFormat::Uint16, IndexFormat::from(&indices));
222        assert_eq!(vec![10, 11], indices.iter().collect::<Vec<_>>());
223
224        // Add a value that is too large for `u16` so the storage should be converted to `U32`.
225        indices.extend([12, 0x10013, 0x10014]);
226        assert_eq!(IndexFormat::Uint32, IndexFormat::from(&indices));
227        assert_eq!(
228            vec![10, 11, 12, 0x10013, 0x10014],
229            indices.iter().collect::<Vec<_>>()
230        );
231
232        indices.extend([15, 0x10016]);
233        assert_eq!(IndexFormat::Uint32, IndexFormat::from(&indices));
234        assert_eq!(
235            vec![10, 11, 12, 0x10013, 0x10014, 15, 0x10016],
236            indices.iter().collect::<Vec<_>>()
237        );
238    }
239}