#![allow(clippy::float_cmp)]
#[path = "./common.rs"]
mod common;
use std::slice;
use assert2::assert;
use common::*;
use flense::prelude::*;
#[test]
fn lens_can_lens() {
fn use_lens<'a>(original: &'a Vertex, lens: LensSlice<'a, (Normal, Other, Color, Position)>) {
let (lhs, rhs) = lens.split::<(Position,), _>();
assert!(lhs.get::<Position, _>(0).unwrap() == &original.position);
assert!(rhs.get::<Color, _>(0).unwrap() == &original.color);
assert!(rhs.get::<Normal, _>(0).unwrap() == &original.normal);
}
let some_vertex = Vertex {
position: [1.0, 2.0, 3.0],
color: [4.0, 5.0, 6.0],
normal: [7, 8],
other: !0,
};
let some_vertex_slice = slice::from_ref(&some_vertex);
use_lens(&some_vertex, some_vertex_slice.lens_slice());
}
#[test]
fn split_last_element() {
let verts = [
Vertex {
position: [1.0, 2.0, 3.0],
color: [4.0, 5.0, 6.0],
normal: [7, 8],
other: 0xAA,
},
Vertex {
position: [10.0, 20.0, 30.0],
color: [40.0, 50.0, 60.0],
normal: [70, 80],
other: 0xBB,
},
];
let lens: LensSlice<'_, (Normal, Other, Color, Position)> = verts.as_slice().lens_slice();
let (lhs, rhs) = lens.split::<(Position,), _>();
for (i, v) in verts.iter().enumerate() {
assert!(lhs.get::<Position, _>(i).unwrap() == &v.position);
assert!(rhs.get::<Color, _>(i).unwrap() == &v.color);
assert!(rhs.get::<Normal, _>(i).unwrap() == &v.normal);
assert!(rhs.get::<Other, _>(i).unwrap() == &v.other);
}
assert!(lhs.len() == 2);
assert!(rhs.len() == 2);
}
#[test]
fn split_first_element() {
let verts = [
Vertex {
position: [1.0, 2.0, 3.0],
color: [4.0, 5.0, 6.0],
normal: [7, 8],
other: 0xAA,
},
Vertex {
position: [10.0, 20.0, 30.0],
color: [40.0, 50.0, 60.0],
normal: [70, 80],
other: 0xBB,
},
];
let lens: LensSlice<'_, (Normal, Other, Color, Position)> = verts.as_slice().lens_slice();
let (lhs, rhs) = lens.split::<(Normal,), _>();
for (i, v) in verts.iter().enumerate() {
assert!(lhs.get::<Normal, _>(i).unwrap() == &v.normal);
assert!(rhs.get::<Other, _>(i).unwrap() == &v.other);
assert!(rhs.get::<Color, _>(i).unwrap() == &v.color);
assert!(rhs.get::<Position, _>(i).unwrap() == &v.position);
}
}
#[test]
fn split_multi_element_non_contiguous() {
let verts = [
Vertex {
position: [1.0, 2.0, 3.0],
color: [4.0, 5.0, 6.0],
normal: [7, 8],
other: 0xAA,
},
Vertex {
position: [10.0, 20.0, 30.0],
color: [40.0, 50.0, 60.0],
normal: [70, 80],
other: 0xBB,
},
Vertex {
position: [100.0, 200.0, 300.0],
color: [400.0, 500.0, 600.0],
normal: [9, 10],
other: 0xCC,
},
];
let lens: LensSlice<'_, (Normal, Other, Color, Position)> = verts.as_slice().lens_slice();
let (lhs, rhs) = lens.split::<(Other, Position), _>();
for (i, v) in verts.iter().enumerate() {
assert!(lhs.get::<Other, _>(i).unwrap() == &v.other);
assert!(lhs.get::<Position, _>(i).unwrap() == &v.position);
assert!(rhs.get::<Normal, _>(i).unwrap() == &v.normal);
assert!(rhs.get::<Color, _>(i).unwrap() == &v.color);
}
}
#[test]
fn split_reordered_lhs() {
let v = Vertex {
position: [1.0, 2.0, 3.0],
color: [4.0, 5.0, 6.0],
normal: [7, 8],
other: 0xAA,
};
let verts = slice::from_ref(&v);
let lens: LensSlice<'_, (Normal, Other, Color, Position)> = verts.lens_slice();
let (lhs, rhs) = lens.split::<(Position, Normal), _>();
assert!(lhs.get::<Position, _>(0).unwrap() == &v.position);
assert!(lhs.get::<Normal, _>(0).unwrap() == &v.normal);
assert!(rhs.get::<Other, _>(0).unwrap() == &v.other);
assert!(rhs.get::<Color, _>(0).unwrap() == &v.color);
}
#[test]
fn split_empty_lhs() {
let v = Vertex {
position: [1.0, 2.0, 3.0],
color: [4.0, 5.0, 6.0],
normal: [7, 8],
other: 0xAA,
};
let verts = slice::from_ref(&v);
let lens: LensSlice<'_, (Normal, Other, Color, Position)> = verts.lens_slice();
let (_lhs, rhs): (LensSlice<'_, ()>, _) = lens.split::<(), _>();
assert!(rhs.get::<Normal, _>(0).unwrap() == &v.normal);
assert!(rhs.get::<Other, _>(0).unwrap() == &v.other);
assert!(rhs.get::<Color, _>(0).unwrap() == &v.color);
assert!(rhs.get::<Position, _>(0).unwrap() == &v.position);
}
#[expect(clippy::type_complexity)]
#[test]
fn split_full_lhs() {
let v = Vertex {
position: [1.0, 2.0, 3.0],
color: [4.0, 5.0, 6.0],
normal: [7, 8],
other: 0xAA,
};
let verts = slice::from_ref(&v);
let lens: LensSlice<'_, (Normal, Other, Color, Position)> = verts.lens_slice();
let (lhs, _rhs): (
LensSlice<'_, (Position, Color, Other, Normal)>,
LensSlice<'_, ()>,
) = lens.split::<(Position, Color, Other, Normal), _>();
assert!(lhs.get::<Position, _>(0).unwrap() == &v.position);
assert!(lhs.get::<Color, _>(0).unwrap() == &v.color);
assert!(lhs.get::<Other, _>(0).unwrap() == &v.other);
assert!(lhs.get::<Normal, _>(0).unwrap() == &v.normal);
}
#[test]
fn split_chained() {
let v = Vertex {
position: [1.0, 2.0, 3.0],
color: [4.0, 5.0, 6.0],
normal: [7, 8],
other: 0xAA,
};
let verts = slice::from_ref(&v);
let lens: LensSlice<'_, (Normal, Other, Color, Position)> = verts.lens_slice();
let (a, rest1) = lens.split::<(Color,), _>();
let (b, rest2) = rest1.split::<(Other,), _>();
assert!(a.get::<Color, _>(0).unwrap() == &v.color);
assert!(b.get::<Other, _>(0).unwrap() == &v.other);
assert!(rest2.get::<Normal, _>(0).unwrap() == &v.normal);
assert!(rest2.get::<Position, _>(0).unwrap() == &v.position);
}
#[test]
fn split_preserves_stride() {
let verts = [Vertex::default(); 3];
let lens: LensSlice<'_, (Normal, Other, Color, Position)> = verts.as_slice().lens_slice();
let (lhs, rhs) = lens.split::<(Other, Position), _>();
let stride = size_of::<Vertex>();
assert!(lhs.stride::<Other, _>() == stride);
assert!(lhs.stride::<Position, _>() == stride);
assert!(rhs.stride::<Normal, _>() == stride);
assert!(rhs.stride::<Color, _>() == stride);
}
#[test]
fn split_permuted_lhs_size_mismatch() {
let v = Vertex {
position: [1.0, 2.0, 3.0],
color: [4.0, 5.0, 6.0],
normal: [7, 8],
other: 0xDEAD_BEEF_CAFE_BABE,
};
let verts = slice::from_ref(&v);
let lens: LensSlice<'_, (Normal, Other, Color, Position)> = verts.lens_slice();
macro_rules! check_split {
($lens:expr, ($($lhs:ident),+ $(,)?), in_lhs: [$($l_field:ident: $l_expr:expr),* $(,)?], in_rhs: [$($r_field:ident: $r_expr:expr),* $(,)?] $(,)?) => {{
let (lhs, rhs) = $lens.split::<($($lhs,)+), _>();
$(
assert!(lhs.get::<$l_field, _>(0).unwrap() == &$l_expr);
)*
$(
assert!(rhs.get::<$r_field, _>(0).unwrap() == &$r_expr);
)*
}};
}
check_split!(lens, (Normal),
in_lhs: [Normal: v.normal],
in_rhs: [Other: v.other, Color: v.color, Position: v.position]);
check_split!(lens, (Other),
in_lhs: [Other: v.other],
in_rhs: [Normal: v.normal, Color: v.color, Position: v.position]);
check_split!(lens, (Color),
in_lhs: [Color: v.color],
in_rhs: [Normal: v.normal, Other: v.other, Position: v.position]);
check_split!(lens, (Position),
in_lhs: [Position: v.position],
in_rhs: [Normal: v.normal, Other: v.other, Color: v.color]);
check_split!(lens, (Normal, Other),
in_lhs: [Normal: v.normal, Other: v.other],
in_rhs: [Color: v.color, Position: v.position]);
check_split!(lens, (Other, Normal),
in_lhs: [Other: v.other, Normal: v.normal],
in_rhs: [Color: v.color, Position: v.position]);
check_split!(lens, (Normal, Position),
in_lhs: [Normal: v.normal, Position: v.position],
in_rhs: [Other: v.other, Color: v.color]);
check_split!(lens, (Position, Normal),
in_lhs: [Position: v.position, Normal: v.normal],
in_rhs: [Other: v.other, Color: v.color]);
check_split!(lens, (Color, Other),
in_lhs: [Color: v.color, Other: v.other],
in_rhs: [Normal: v.normal, Position: v.position]);
check_split!(lens, (Other, Color),
in_lhs: [Other: v.other, Color: v.color],
in_rhs: [Normal: v.normal, Position: v.position]);
check_split!(lens, (Color, Position),
in_lhs: [Color: v.color, Position: v.position],
in_rhs: [Normal: v.normal, Other: v.other]);
check_split!(lens, (Position, Color),
in_lhs: [Position: v.position, Color: v.color],
in_rhs: [Normal: v.normal, Other: v.other]);
check_split!(lens, (Normal, Color),
in_lhs: [Normal: v.normal, Color: v.color],
in_rhs: [Other: v.other, Position: v.position]);
check_split!(lens, (Color, Normal),
in_lhs: [Color: v.color, Normal: v.normal],
in_rhs: [Other: v.other, Position: v.position]);
check_split!(lens, (Other, Position),
in_lhs: [Other: v.other, Position: v.position],
in_rhs: [Normal: v.normal, Color: v.color]);
check_split!(lens, (Position, Other),
in_lhs: [Position: v.position, Other: v.other],
in_rhs: [Normal: v.normal, Color: v.color]);
check_split!(lens, (Position, Color, Normal),
in_lhs: [Position: v.position, Color: v.color, Normal: v.normal],
in_rhs: [Other: v.other]);
check_split!(lens, (Other, Position, Normal),
in_lhs: [Other: v.other, Position: v.position, Normal: v.normal],
in_rhs: [Color: v.color]);
check_split!(lens, (Normal, Position, Color),
in_lhs: [Normal: v.normal, Position: v.position, Color: v.color],
in_rhs: [Other: v.other]);
check_split!(lens, (Color, Normal, Other),
in_lhs: [Color: v.color, Normal: v.normal, Other: v.other],
in_rhs: [Position: v.position]);
}
#[test]
fn lens_slice_get() {
let verts = [
Vertex {
position: [1.0, 2.0, 3.0],
color: [4.0, 5.0, 6.0],
normal: [7, 8],
other: 0xAA,
},
Vertex {
position: [10.0, 20.0, 30.0],
color: [40.0, 50.0, 60.0],
normal: [70, 80],
other: 0xBB,
},
Vertex {
position: [100.0, 200.0, 300.0],
color: [400.0, 500.0, 600.0],
normal: [9, 10],
other: 0xCC,
},
];
let lens: LensSlice<'_, (Normal, Other, Color, Position)> = verts.as_slice().lens_slice();
for (i, v) in verts.iter().enumerate() {
assert!(*lens.get::<Position, _>(i).unwrap() == v.position);
assert!(*lens.get::<Color, _>(i).unwrap() == v.color);
assert!(*lens.get::<Normal, _>(i).unwrap() == v.normal);
assert!(*lens.get::<Other, _>(i).unwrap() == v.other);
}
assert!(lens.get::<Position, _>(verts.len()).is_none());
}
#[test]
fn lens_slice_get_all() {
let verts = [
Vertex {
position: [1.0, 2.0, 3.0],
color: [4.0, 5.0, 6.0],
normal: [7, 8],
other: 0xAA,
},
Vertex {
position: [10.0, 20.0, 30.0],
color: [40.0, 50.0, 60.0],
normal: [70, 80],
other: 0xBB,
},
Vertex {
position: [100.0, 200.0, 300.0],
color: [400.0, 500.0, 600.0],
normal: [9, 10],
other: 0xCC,
},
];
let lens: LensSlice<'_, (Normal, Other, Color, Position)> = verts.as_slice().lens_slice();
for (i, v) in verts.iter().enumerate() {
let lens = lens.get_all(i).unwrap();
assert!(*lens.as_ref::<Position, _>() == v.position);
assert!(*lens.as_ref::<Color, _>() == v.color);
assert!(*lens.as_ref::<Normal, _>() == v.normal);
assert!(*lens.as_ref::<Other, _>() == v.other);
}
assert!(lens.get_all(verts.len()).is_none());
}
#[test]
fn lens_slice_get_all_out_of_bounds() {
let verts: [Vertex; 0] = [];
let lens: LensSlice<'_, (Normal, Other, Color, Position)> = verts.as_slice().lens_slice();
assert!(lens.is_empty());
assert!(lens.get_all(0).is_none());
}
#[test]
fn lens_slice_get_all_after_split() {
let verts = [
Vertex {
position: [1.0, 2.0, 3.0],
color: [4.0, 5.0, 6.0],
normal: [7, 8],
other: 0xAA,
},
Vertex {
position: [10.0, 20.0, 30.0],
color: [40.0, 50.0, 60.0],
normal: [70, 80],
other: 0xBB,
},
];
let lens: LensSlice<'_, (Normal, Other, Color, Position)> = verts.as_slice().lens_slice();
let (lhs, rhs) = lens.split::<(Position,), _>();
let l = lhs.get_all(0).unwrap();
assert!(*l.as_ref::<Position, _>() == verts[0].position);
let r = rhs.get_all(1).unwrap();
assert!(*r.as_ref::<Color, _>() == verts[1].color);
assert!(*r.as_ref::<Normal, _>() == verts[1].normal);
assert!(*r.as_ref::<Other, _>() == verts[1].other);
}