Indices::push(u32) (#16014)

# Objective

Making work with `Indices` struct easier. Currently when building
indices in some quick-and-dirty code we need to do matches and handle
enum variants.

## Solution

`Indices::push` utility which works transparently with `U16` and `U32`
variants.

## Testing

Unit test added.
This commit is contained in:
Stepan Koltsov 2024-10-20 14:51:55 +01:00 committed by GitHub
parent 75096fbf97
commit 0cc53458cc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -1,4 +1,5 @@
use bevy_reflect::Reflect;
use core::iter;
use core::iter::FusedIterator;
use derive_more::derive::{Display, Error};
use wgpu::IndexFormat;
@ -98,6 +99,25 @@ impl Indices {
Indices::U32(vec) => vec.is_empty(),
}
}
/// Add an index. If the index is greater than `u16::MAX`,
/// the storage will be converted to `u32`.
pub fn push(&mut self, index: u32) {
match self {
Indices::U32(vec) => vec.push(index),
Indices::U16(vec) => match u16::try_from(index) {
Ok(index) => vec.push(index),
Err(_) => {
let new_vec = vec
.iter()
.map(|&index| u32::from(index))
.chain(iter::once(index))
.collect::<Vec<u32>>();
*self = Indices::U32(new_vec);
}
},
}
}
}
/// An Iterator for the [`Indices`].
@ -135,3 +155,30 @@ impl From<&Indices> for IndexFormat {
}
}
}
#[cfg(test)]
mod tests {
use crate::Indices;
use wgpu::IndexFormat;
#[test]
fn test_indices_push() {
let mut indices = Indices::U16(Vec::new());
indices.push(10);
assert_eq!(IndexFormat::Uint16, IndexFormat::from(&indices));
assert_eq!(vec![10], indices.iter().collect::<Vec<_>>());
// Add a value that is too large for `u16` so the storage should be converted to `U32`.
indices.push(0x10000);
assert_eq!(IndexFormat::Uint32, IndexFormat::from(&indices));
assert_eq!(vec![10, 0x10000], indices.iter().collect::<Vec<_>>());
indices.push(20);
indices.push(0x20000);
assert_eq!(IndexFormat::Uint32, IndexFormat::from(&indices));
assert_eq!(
vec![10, 0x10000, 20, 0x20000],
indices.iter().collect::<Vec<_>>()
);
}
}