use std::vec::Vec;
use gtup::GTup;
pub type VertexFormat = Vec<VertexComponentFormat>;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct VertexComponentFormat {
pub comp_type: Type,
pub dim: Dim,
pub unit_size: usize,
pub align: usize
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Type {
Integral,
Unsigned,
Floating,
Boolean
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Dim {
Dim1,
Dim2,
Dim3,
Dim4
}
pub unsafe trait Vertex {
fn vertex_format() -> VertexFormat;
}
pub unsafe trait CompatibleVertex<V>: Vertex where V: Vertex {}
unsafe impl<V> CompatibleVertex<V> for V where V: Vertex {}
macro_rules! impl_base {
($t:ty, $q:ty, $comp_type:ident, $dim:ident) => {
unsafe impl Vertex for $t {
fn vertex_format() -> VertexFormat {
vec![VertexComponentFormat {
comp_type: Type::$comp_type,
dim: Dim::$dim,
unit_size: ::std::mem::size_of::<$q>(),
align: ::std::mem::align_of::<$q>()
}]
}
}
};
($t:ty, $comp_type:ident, $dim:ident) => {
impl_base!($t, $t, $comp_type, $dim);
}
}
macro_rules! impl_arr {
($t:ty, $q:ident) => {
impl_base!([$t; 1], $t, $q, Dim1);
impl_base!([$t; 2], $t, $q, Dim2);
impl_base!([$t; 3], $t, $q, Dim3);
impl_base!([$t; 4], $t, $q, Dim4);
}
}
unsafe impl Vertex for () {
fn vertex_format() -> VertexFormat {
Vec::new()
}
}
impl_base!(i8, Integral, Dim1);
impl_base!(i16, Integral, Dim1);
impl_base!(i32, Integral, Dim1);
impl_base!(u8, Unsigned, Dim1);
impl_base!(u16, Unsigned, Dim1);
impl_base!(u32, Unsigned, Dim1);
impl_base!(f32, Floating, Dim1);
impl_base!(f64, Floating, Dim1);
impl_base!(bool, Floating, Dim1);
impl_arr!(i8, Integral);
impl_arr!(i16, Integral);
impl_arr!(i32, Integral);
impl_arr!(u8, Unsigned);
impl_arr!(u16, Unsigned);
impl_arr!(u32, Unsigned);
impl_arr!(f32, Floating);
impl_arr!(f64, Floating);
impl_arr!(bool, Boolean);
unsafe impl<A, B> Vertex for GTup<A, B> where A: Vertex, B: Vertex {
fn vertex_format() -> VertexFormat {
let mut t = A::vertex_format();
t.extend(B::vertex_format());
t
}
}
macro_rules! impl_vertex_for_tuple {
($($t:tt),+) => {
unsafe impl<$($t),+> Vertex for ($($t),+) where $($t: Vertex),+ {
fn vertex_format() -> VertexFormat {
<gtup!(:$($t),+) as Vertex>::vertex_format()
}
}
}
}
impl_vertex_for_tuple!(A, B);
impl_vertex_for_tuple!(A, B, C);
impl_vertex_for_tuple!(A, B, C, D);
impl_vertex_for_tuple!(A, B, C, D, E);
impl_vertex_for_tuple!(A, B, C, D, E, F);
impl_vertex_for_tuple!(A, B, C, D, E, F, G);
impl_vertex_for_tuple!(A, B, C, D, E, F, G, H);
impl_vertex_for_tuple!(A, B, C, D, E, F, G, H, I);
impl_vertex_for_tuple!(A, B, C, D, E, F, G, H, I, J);
impl_vertex_for_tuple!(A, B, C, D, E, F, G, H, I, J, K);
impl_vertex_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L);
impl_vertex_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M);
impl_vertex_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N);
impl_vertex_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O);
impl_vertex_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P);