use criterion::{Criterion, criterion_group, criterion_main};
use std::hint::black_box;
use std::io::Cursor;
#[allow(dead_code)]
fn generate_test_wmo(_size: usize) -> Vec<u8> {
let mut buffer = Vec::new();
buffer.extend_from_slice(b"REVM"); buffer.extend_from_slice(&4u32.to_le_bytes());
buffer.extend_from_slice(&[17, 0, 0, 0]);
buffer.extend_from_slice(b"DHOM"); buffer.extend_from_slice(&64u32.to_le_bytes());
let n_materials = 10u32;
let n_groups = 5u32;
let n_portals = 3u32;
let n_lights = 8u32;
let n_doodad_names = 20u32;
let n_doodad_defs = 15u32;
let n_doodad_sets = 2u32;
buffer.extend_from_slice(&n_materials.to_le_bytes());
buffer.extend_from_slice(&n_groups.to_le_bytes());
buffer.extend_from_slice(&n_portals.to_le_bytes());
buffer.extend_from_slice(&n_lights.to_le_bytes());
buffer.extend_from_slice(&n_doodad_names.to_le_bytes());
buffer.extend_from_slice(&n_doodad_defs.to_le_bytes());
buffer.extend_from_slice(&n_doodad_sets.to_le_bytes());
buffer.extend_from_slice(&[0xFF, 0xFF, 0xFF, 0xFF]); buffer.extend_from_slice(&[0x01, 0x00, 0x00, 0x00]);
buffer.extend_from_slice(&(-100.0f32).to_le_bytes());
buffer.extend_from_slice(&(-100.0f32).to_le_bytes());
buffer.extend_from_slice(&(-100.0f32).to_le_bytes());
buffer.extend_from_slice(&(100.0f32).to_le_bytes());
buffer.extend_from_slice(&(100.0f32).to_le_bytes());
buffer.extend_from_slice(&(100.0f32).to_le_bytes());
buffer.extend_from_slice(&[0, 0, 0, 0, 0, 0, 0, 0]);
buffer.extend_from_slice(b"TMOM"); buffer.extend_from_slice(&(n_materials * 40).to_le_bytes());
for _ in 0..n_materials {
let material_data = [
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, ];
buffer.extend_from_slice(&material_data);
}
let textures = [
"textures/stone1.blp\0",
"textures/stone2.blp\0",
"textures/wood1.blp\0",
"textures/roof1.blp\0",
"textures/wall1.blp\0",
];
let motx_size = textures.iter().map(|s| s.len()).sum::<usize>();
buffer.extend_from_slice(b"XTOM"); buffer.extend_from_slice(&(motx_size as u32).to_le_bytes());
for texture in &textures {
buffer.extend_from_slice(texture.as_bytes());
}
let group_names = [
"Group_0\0",
"Group_1\0",
"Group_2\0",
"Group_3\0",
"Group_4\0",
];
let mogn_size = group_names.iter().map(|s| s.len()).sum::<usize>();
buffer.extend_from_slice(b"NGOM"); buffer.extend_from_slice(&(mogn_size as u32).to_le_bytes());
for name in &group_names {
buffer.extend_from_slice(name.as_bytes());
}
buffer.extend_from_slice(b"IGOM"); buffer.extend_from_slice(&(n_groups * 32).to_le_bytes());
for i in 0..n_groups {
buffer.extend_from_slice(&[0x01, 0x00, 0x00, 0x00]);
buffer.extend_from_slice(&(-50.0f32).to_le_bytes());
buffer.extend_from_slice(&(-50.0f32).to_le_bytes());
buffer.extend_from_slice(&(-50.0f32).to_le_bytes());
buffer.extend_from_slice(&(50.0f32).to_le_bytes());
buffer.extend_from_slice(&(50.0f32).to_le_bytes());
buffer.extend_from_slice(&(50.0f32).to_le_bytes());
let offset = i * 8; buffer.extend_from_slice(&offset.to_le_bytes());
}
let n_portal_vertices = 12u32; buffer.extend_from_slice(b"VPOM"); buffer.extend_from_slice(&(n_portal_vertices * 12).to_le_bytes());
for _ in 0..n_portal_vertices {
buffer.extend_from_slice(&(0.0f32).to_le_bytes());
buffer.extend_from_slice(&(0.0f32).to_le_bytes());
buffer.extend_from_slice(&(0.0f32).to_le_bytes());
}
buffer.extend_from_slice(b"TPOM"); buffer.extend_from_slice(&(n_portals * 20).to_le_bytes());
for i in 0..n_portals {
let vertex_index = (i * 4) as u16;
buffer.extend_from_slice(&vertex_index.to_le_bytes());
buffer.extend_from_slice(&4u16.to_le_bytes()); buffer.extend_from_slice(&0u16.to_le_bytes());
buffer.extend_from_slice(&(1.0f32).to_le_bytes());
buffer.extend_from_slice(&(0.0f32).to_le_bytes());
buffer.extend_from_slice(&(0.0f32).to_le_bytes());
buffer.extend_from_slice(&(0.0f32).to_le_bytes());
}
let n_portal_refs = 6u32; buffer.extend_from_slice(b"RPOM"); buffer.extend_from_slice(&(n_portal_refs * 8).to_le_bytes());
for i in 0..n_portal_refs {
let portal_index = (i / 2) as u16;
let group_index = (i % n_groups) as u16;
let side = (i % 2) as u16;
buffer.extend_from_slice(&portal_index.to_le_bytes());
buffer.extend_from_slice(&group_index.to_le_bytes());
buffer.extend_from_slice(&side.to_le_bytes());
buffer.extend_from_slice(&0u16.to_le_bytes()); }
buffer.extend_from_slice(b"TLOM"); buffer.extend_from_slice(&(n_lights * 48).to_le_bytes());
for i in 0..n_lights {
let light_type = (i % 4) as u8; buffer.extend_from_slice(&[light_type, 0, 0, 0]);
buffer.extend_from_slice(&1u32.to_le_bytes());
buffer.extend_from_slice(&0u32.to_le_bytes());
buffer.extend_from_slice(&0u32.to_le_bytes());
buffer.extend_from_slice(&0u32.to_le_bytes());
let x = (i as f32 * 10.0) - 40.0;
buffer.extend_from_slice(&x.to_le_bytes());
buffer.extend_from_slice(&0.0f32.to_le_bytes());
buffer.extend_from_slice(&0.0f32.to_le_bytes());
buffer.extend_from_slice(&1.0f32.to_le_bytes());
buffer.extend_from_slice(&0xFFFFFFFFu32.to_le_bytes());
buffer.extend_from_slice(&5.0f32.to_le_bytes());
buffer.extend_from_slice(&100.0f32.to_le_bytes());
buffer.extend_from_slice([0u8; 20].as_slice());
}
buffer
}
#[allow(dead_code)]
fn generate_test_wmo_group(_size: usize) -> Vec<u8> {
let mut buffer = Vec::new();
buffer.extend_from_slice(b"REVM"); buffer.extend_from_slice(&4u32.to_le_bytes());
buffer.extend_from_slice(&[17, 0, 0, 0]);
buffer.extend_from_slice(b"PGOM"); buffer.extend_from_slice(&68u32.to_le_bytes());
buffer.extend_from_slice(&[0, 0, 0, 0]); buffer.extend_from_slice(&[0x01, 0x00, 0x00, 0x00]);
buffer.extend_from_slice(&(-50.0f32).to_le_bytes());
buffer.extend_from_slice(&(-50.0f32).to_le_bytes());
buffer.extend_from_slice(&(-50.0f32).to_le_bytes());
buffer.extend_from_slice(&(50.0f32).to_le_bytes());
buffer.extend_from_slice(&(50.0f32).to_le_bytes());
buffer.extend_from_slice(&(50.0f32).to_le_bytes());
buffer.extend_from_slice(&[0, 0]); buffer.extend_from_slice(&[0, 0]);
let n_vertices = 100u32;
buffer.extend_from_slice(b"TVOM"); buffer.extend_from_slice(&(n_vertices * 12).to_le_bytes());
for i in 0..n_vertices {
let x = ((i % 10) as f32 - 5.0) * 10.0;
let y = ((i / 10) as f32 - 5.0) * 10.0;
let z = 0.0f32;
buffer.extend_from_slice(&x.to_le_bytes());
buffer.extend_from_slice(&y.to_le_bytes());
buffer.extend_from_slice(&z.to_le_bytes());
}
buffer.extend_from_slice(b"RNOM"); buffer.extend_from_slice(&(n_vertices * 12).to_le_bytes());
for _ in 0..n_vertices {
buffer.extend_from_slice(&(0.0f32).to_le_bytes());
buffer.extend_from_slice(&(0.0f32).to_le_bytes());
buffer.extend_from_slice(&(1.0f32).to_le_bytes()); }
buffer.extend_from_slice(b"VTOM"); buffer.extend_from_slice(&(n_vertices * 8).to_le_bytes());
for i in 0..n_vertices {
let u = (i % 10) as f32 / 10.0;
let v = (i / 10) as f32 / 10.0;
buffer.extend_from_slice(&u.to_le_bytes());
buffer.extend_from_slice(&v.to_le_bytes());
}
let n_indices = 200u32; buffer.extend_from_slice(b"IVOM"); buffer.extend_from_slice(&(n_indices * 2).to_le_bytes());
for i in 0..n_indices {
let idx = (i % n_vertices) as u16;
buffer.extend_from_slice(&idx.to_le_bytes());
}
let n_batches = 5u32;
buffer.extend_from_slice(b"ABOM"); buffer.extend_from_slice(&(n_batches * 24).to_le_bytes());
for i in 0..n_batches {
let idx_per_batch = n_indices / n_batches;
let start_idx = i * idx_per_batch;
buffer.extend_from_slice(&[0, 0]); buffer.extend_from_slice(&[0, 0]); buffer.extend_from_slice(&start_idx.to_le_bytes()); buffer.extend_from_slice(&(idx_per_batch as u16).to_le_bytes()); buffer.extend_from_slice(&[0, 0]); buffer.extend_from_slice(&(n_vertices as u16).to_le_bytes()); buffer.extend_from_slice(&[0, 0]); buffer.extend_from_slice(&(0.0f32).to_le_bytes()); buffer.extend_from_slice(&(0.0f32).to_le_bytes()); }
buffer
}
fn bench_parse_wmo(c: &mut Criterion) {
let test_wmo = generate_test_wmo(10000);
c.bench_function("parse_wmo_medium", |b| {
b.iter(|| {
let mut cursor = Cursor::new(black_box(&test_wmo));
let _ = wow_wmo::parse_wmo(&mut cursor).unwrap();
})
});
}
criterion_group!(
benches,
bench_parse_wmo );
criterion_main!(benches);