#![feature(const_trait_impl)]
pub extern crate vek;
trait Scalar {}
macro_rules! impl_scalar { ($($t:ty),*) => { $( impl Scalar for $t {} )* } }
impl_scalar!(
f32, f64, i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, usize, bool
);
#[const_trait]
trait ConvertFrom<Source> {
fn convert_from(src: Source) -> Self;
}
macro_rules! generate_conversions {
() => {
generate_conversions!(@impl
[u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize, f32, f64],
[u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize, f32, f64]
);
};
(@impl [], [$($dst_ty:ty),*]) => {};
(@impl [$src_ty:ty $(, $rest_src:ty)*], [$($dst_ty:ty),*]) => {
$(
impl const ConvertFrom<$src_ty> for $dst_ty {
#[inline(always)]
fn convert_from(src: $src_ty) -> $dst_ty {
src as $dst_ty
}
}
)*
generate_conversions!(@impl [$($rest_src),*], [$($dst_ty),*]);
};
}
generate_conversions!(@impl [u8,u16,u32,u64,u128,usize,i8,i16,i32,i64,i128,isize,f32,f64],[u8,u16,u32,u64,u128,usize,i8,i16,i32,i64,i128,isize,f32,f64]);
#[const_trait]
trait IntoProxy<T, const N: usize> {
fn into_proxy(self) -> [T; N];
}
impl<S, T> const IntoProxy<T, 1> for S
where
S: Scalar,
T: const ConvertFrom<S> + Scalar,
{
fn into_proxy(self) -> [T; 1] {
[T::convert_from(self)]
}
}
impl<S, T> const IntoProxy<T, 2> for S
where
S: Scalar + Copy,
T: const ConvertFrom<S> + Scalar,
{
fn into_proxy(self) -> [T; 2] {
[T::convert_from(self), T::convert_from(self)]
}
}
impl<S, T> const IntoProxy<T, 3> for S
where
S: Scalar + Copy,
T: const ConvertFrom<S> + Scalar,
{
fn into_proxy(self) -> [T; 3] {
[
T::convert_from(self),
T::convert_from(self),
T::convert_from(self),
]
}
}
impl<S, T> const IntoProxy<T, 4> for S
where
S: Scalar + Copy,
T: const ConvertFrom<S> + Scalar,
{
fn into_proxy(self) -> [T; 4] {
[
T::convert_from(self),
T::convert_from(self),
T::convert_from(self),
T::convert_from(self),
]
}
}
impl<E, T> const IntoProxy<T, 2> for vek::Vec2<E>
where
E: Copy + Scalar,
T: const ConvertFrom<E> + Scalar,
{
fn into_proxy(self) -> [T; 2] {
[T::convert_from(self.x), T::convert_from(self.y)]
}
}
impl<E, T> const IntoProxy<T, 3> for vek::Vec3<E>
where
E: Copy + Scalar,
T: const ConvertFrom<E> + Scalar,
{
fn into_proxy(self) -> [T; 3] {
[
T::convert_from(self.x),
T::convert_from(self.y),
T::convert_from(self.z),
]
}
}
impl<E, T> const IntoProxy<T, 4> for vek::Vec4<E>
where
E: Copy + Scalar,
T: const ConvertFrom<E> + Scalar,
{
fn into_proxy(self) -> [T; 4] {
[
T::convert_from(self.x),
T::convert_from(self.y),
T::convert_from(self.z),
T::convert_from(self.w),
]
}
}
#[const_trait]
pub trait BuildVec2<E> {
fn build(self) -> vek::Vec2<E>;
}
impl<E, A> const BuildVec2<E> for vek::Vec2<A>
where
A: const IntoProxy<E, 2> + Copy + const ConvertFrom<E> + Scalar,
E: Copy + const ConvertFrom<A> + Scalar,
{
fn build(self) -> vek::Vec2<E> {
let a = self.into_proxy();
vek::Vec2::new(a[0], a[1])
}
}
impl<E, S1, S2> const BuildVec2<E> for (S1, S2)
where
S1: const IntoProxy<E, 1> + Copy + Scalar,
S2: const IntoProxy<E, 1> + Copy + Scalar,
E: Copy + Default + const ConvertFrom<S1> + const ConvertFrom<S2> + Scalar,
{
fn build(self) -> vek::Vec2<E> {
let p1 = self.0.into_proxy()[0];
let p2 = self.1.into_proxy()[0];
vek::Vec2::new(p1, p2)
}
}
impl<E, S> const BuildVec2<E> for S
where
S: const IntoProxy<E, 1> + Copy + Scalar,
E: Copy + const ConvertFrom<S> + Scalar,
{
fn build(self) -> vek::Vec2<E> {
let a = self.into_proxy()[0];
vek::Vec2::new(a, a)
}
}
#[const_trait]
pub trait BuildVec3<E> {
fn build(self) -> vek::Vec3<E>;
}
impl<E, A> const BuildVec3<E> for vek::Vec3<A>
where
A: const IntoProxy<E, 3> + Copy + const ConvertFrom<E> + Scalar,
E: Copy + Scalar + const ConvertFrom<A>,
{
fn build(self) -> vek::Vec3<E> {
let a = self.into_proxy();
vek::Vec3::new(a[0], a[1], a[2])
}
}
impl<E, A, S> const BuildVec3<E> for (S, vek::Vec2<A>)
where
S: const IntoProxy<E, 1> + Copy + Scalar + const ConvertFrom<A>,
A: const IntoProxy<E, 2> + Copy + Scalar + const ConvertFrom<E>,
E: Copy + Scalar + const ConvertFrom<A>,
{
fn build(self) -> vek::Vec3<E> {
let s = self.0.into_proxy()[0];
let v = self.1.into_proxy();
vek::Vec3::new(s, v[0], v[1])
}
}
impl<E, A, S> const BuildVec3<E> for (vek::Vec2<A>, S)
where
A: const IntoProxy<E, 2> + Copy + const ConvertFrom<E> + Scalar,
S: const IntoProxy<E, 1> + Copy + const ConvertFrom<A> + Scalar,
E: Copy + const ConvertFrom<A> + Scalar,
{
fn build(self) -> vek::Vec3<E> {
let v = self.0.into_proxy();
let s = self.1.into_proxy()[0];
vek::Vec3::new(v[0], v[1], s)
}
}
impl<E, S1, S2, S3> const BuildVec3<E> for (S1, S2, S3)
where
S1: const IntoProxy<E, 1> + Copy + const ConvertFrom<E> + Scalar,
S2: const IntoProxy<E, 1> + Copy + const ConvertFrom<E> + Scalar,
S3: const IntoProxy<E, 1> + Copy + const ConvertFrom<E> + Scalar,
E: Copy + Default + Scalar,
{
fn build(self) -> vek::Vec3<E> {
let x = self.0.into_proxy()[0];
let y = self.1.into_proxy()[0];
let z = self.2.into_proxy()[0];
vek::Vec3::new(x, y, z)
}
}
impl<E, S> const BuildVec3<E> for S
where
S: const IntoProxy<E, 1> + Copy + Scalar,
E: Copy + const ConvertFrom<S> + Scalar,
{
fn build(self) -> vek::Vec3<E> {
let a = self.into_proxy()[0];
vek::Vec3::new(a, a, a)
}
}
#[const_trait]
pub trait BuildVec4<E> {
fn build(self) -> vek::Vec4<E>;
}
impl<E, A> const BuildVec4<E> for vek::Vec4<A>
where
A: const IntoProxy<E, 4> + Copy + Scalar,
E: Copy + const ConvertFrom<A> + Scalar,
{
fn build(self) -> vek::Vec4<E> {
let a = self.into_proxy();
vek::Vec4::new(a[0], a[1], a[2], a[3])
}
}
impl<E, A1, A2> const BuildVec4<E> for (vek::Vec2<A1>, vek::Vec2<A2>)
where
A1: const IntoProxy<E, 2> + Copy + Scalar,
A2: const IntoProxy<E, 2> + Copy + Scalar,
E: Copy + const ConvertFrom<A1> + const ConvertFrom<A2> + Scalar,
{
fn build(self) -> vek::Vec4<E> {
let p1 = self.0.into_proxy();
let p2 = self.1.into_proxy();
vek::Vec4::new(p1[0], p1[1], p2[0], p2[1])
}
}
impl<E, S, A> const BuildVec4<E> for (S, vek::Vec3<A>)
where
S: const IntoProxy<E, 1> + Copy + Scalar,
A: const IntoProxy<E, 3> + Copy + Scalar,
E: Copy + const ConvertFrom<A> + const ConvertFrom<S> + Scalar,
{
fn build(self) -> vek::Vec4<E> {
let s = self.0.into_proxy()[0];
let v = self.1.into_proxy();
vek::Vec4::new(s, v[0], v[1], v[2])
}
}
impl<E, A, S> const BuildVec4<E> for (vek::Vec3<A>, S)
where
A: const IntoProxy<E, 3> + Copy + Scalar,
S: const IntoProxy<E, 1> + Copy + Scalar,
E: Copy + Scalar + const ConvertFrom<A> + const ConvertFrom<S> + Scalar,
{
fn build(self) -> vek::Vec4<E> {
let v = self.0.into_proxy();
let s = self.1.into_proxy()[0];
vek::Vec4::new(v[0], v[1], v[2], s)
}
}
impl<E, S1, S2, A> const BuildVec4<E> for (S1, S2, vek::Vec2<A>)
where
S1: const IntoProxy<E, 1> + Scalar + Copy,
S2: const IntoProxy<E, 1> + Scalar + Copy,
A: const IntoProxy<E, 2> + Copy + Scalar,
E: Copy + const ConvertFrom<S1> + const ConvertFrom<S2> + const ConvertFrom<A> + Scalar,
{
fn build(self) -> vek::Vec4<E> {
let x = self.0.into_proxy()[0];
let y = self.1.into_proxy()[0];
let v = self.2.into_proxy();
vek::Vec4::new(x, y, v[0], v[1])
}
}
impl<E, S1, S2, A> const BuildVec4<E> for (S1, vek::Vec2<A>, S2)
where
S1: const IntoProxy<E, 1> + Scalar + Copy,
S2: const IntoProxy<E, 1> + Scalar + Copy,
A: const IntoProxy<E, 2> + Copy + Scalar,
E: Copy + const ConvertFrom<S1> + const ConvertFrom<S2> + const ConvertFrom<A> + Scalar,
{
fn build(self) -> vek::Vec4<E> {
let x = self.0.into_proxy()[0];
let y = self.1.into_proxy();
let v = self.2.into_proxy()[0];
vek::Vec4::new(x, y[0], y[1], v)
}
}
impl<E, S1, S2, A> const BuildVec4<E> for (vek::Vec2<A>, S1, S2)
where
S1: const IntoProxy<E, 1> + Scalar + Copy,
S2: const IntoProxy<E, 1> + Scalar + Copy,
A: const IntoProxy<E, 2> + Copy + Scalar,
E: Copy + const ConvertFrom<S1> + const ConvertFrom<S2> + const ConvertFrom<A> + Scalar,
{
fn build(self) -> vek::Vec4<E> {
let x = self.0.into_proxy();
let y = self.1.into_proxy()[0];
let v = self.2.into_proxy()[0];
vek::Vec4::new(x[0], x[1], y, v)
}
}
impl<E, S1, S2, S3, S4> const BuildVec4<E> for (S1, S2, S3, S4)
where
S1: const IntoProxy<E, 1> + Scalar + Copy,
S2: const IntoProxy<E, 1> + Scalar + Copy,
S3: const IntoProxy<E, 1> + Scalar + Copy,
S4: const IntoProxy<E, 1> + Scalar + Copy,
E: Copy
+ const ConvertFrom<S1>
+ const ConvertFrom<S2>
+ const ConvertFrom<S3>
+ const ConvertFrom<S4>,
{
fn build(self) -> vek::Vec4<E> {
let a0 = self.0.into_proxy()[0];
let a1 = self.1.into_proxy()[0];
let a2 = self.2.into_proxy()[0];
let a3 = self.3.into_proxy()[0];
vek::Vec4::new(a0, a1, a2, a3)
}
}
impl<E, S> const BuildVec4<E> for S
where
S: const IntoProxy<E, 1> + Copy + Scalar,
E: Copy + const ConvertFrom<S> + Scalar,
{
fn build(self) -> vek::Vec4<E> {
let a = self.into_proxy()[0];
vek::Vec4::new(a, a, a, a)
}
}
pub const fn vec2<E, A>(args: A) -> vek::Vec2<E>
where
A: ~const BuildVec2<E>,
{
args.build()
}
pub const fn vec3<E, A>(args: A) -> vek::Vec3<E>
where
A: ~const BuildVec3<E>,
{
args.build()
}
pub const fn vec4<E, A>(args: A) -> vek::Vec4<E>
where
A: ~const BuildVec4<E>,
{
args.build()
}
#[macro_export]
macro_rules! generate_vec_macros {
($scalar:ty, $vec2_macro:ident, $vec3_macro:ident, $vec4_macro:ident) => {
#[macro_export]
macro_rules! $vec2_macro {
($a:expr) => {
$crate::vec2::<$scalar, _>($a)
};
($a:expr, $b:expr) => {
$crate::vec2::<$scalar, _>(($a, $b))
};
}
#[macro_export]
macro_rules! $vec3_macro {
($a:expr) => {
$crate::vec3::<$scalar, _>($a)
};
($a:expr, $b:expr) => {
$crate::vec3::<$scalar, _>(($a, $b))
};
($a:expr, $b:expr, $c:expr) => {
$crate::vec3::<$scalar, _>(($a, $b, $c))
};
}
#[macro_export]
macro_rules! $vec4_macro {
($a:expr) => {
$crate::vec4::<$scalar, _>($a)
};
($a:expr, $b:expr) => {
$crate::vec4::<$scalar, _>(($a, $b))
};
($a:expr, $b:expr, $c:expr) => {
$crate::vec4::<$scalar, _>(($a, $b, $c))
};
($a:expr, $b:expr, $c:expr, $d:expr) => {
$crate::vec4::<$scalar, _>(($a, $b, $c, $d))
};
}
};
}
generate_vec_macros!(f32, vec2, vec3, vec4);
generate_vec_macros!(f64, dvec2, dvec3, dvec4);
generate_vec_macros!(i8, i8vec2, i8vec3, i8vec4);
generate_vec_macros!(i16, i16vec2, i16vec3, i16vec4);
generate_vec_macros!(i32, i32vec2, i32vec3, i32vec4);
generate_vec_macros!(i32, ivec2, ivec3, ivec4);
generate_vec_macros!(i64, i64vec2, i64vec3, i64vec4);
generate_vec_macros!(u8, u8vec2, u8vec3, u8vec4);
generate_vec_macros!(u16, u16vec2, u16vec3, u16vec4);
generate_vec_macros!(u32, u32vec2, u32vec3, u32vec4);
generate_vec_macros!(u32, uvec2, uvec3, uvec4);
generate_vec_macros!(u64, u64vec2, u64vec3, u64vec4);
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_vec2_combinations() {
assert_eq!(vec2!(1.0f32, 2.0f32), vek::Vec2::<f32>::new(1.0, 2.0));
assert_eq!(vec2!(1i8, 2i8), vek::Vec2::<f32>::new(1.0, 2.0));
assert_eq!(
vec2!(vek::Vec2::new(1i16, 2i16)),
vek::Vec2::<f32>::new(1.0, 2.0)
);
assert_eq!(vec2!(1.0f32, 2i8), vek::Vec2::<f32>::new(1.0, 2.0));
assert_eq!(vec2!(1, 2), vek::Vec2::<f32>::new(1.0, 2.0));
assert_eq!(i8vec2!(1i8, 2i8), vek::Vec2::<i8>::new(1, 2));
assert_eq!(u32vec2!(1u32, 2u32), vek::Vec2::<u32>::new(1, 2));
}
#[test]
fn test_vec3_combinations() {
assert_eq!(
vec3!(1.0f32, 2.0f32, 3.0f32),
vek::Vec3::<f32>::new(1.0, 2.0, 3.0),
);
assert_eq!(vec3!(1i8, 2i8, 3i8), vek::Vec3::<f32>::new(1.0, 2.0, 3.0));
assert_eq!(
vec3!(vek::Vec2::new(1i16, 2i16), 3i8),
vek::Vec3::<f32>::new(1.0, 2.0, 3.0),
);
assert_eq!(
vec3!(1.0f32, vek::Vec2::new(2i8, 3i8)),
vek::Vec3::<f32>::new(1.0, 2.0, 3.0),
);
assert_eq!(
vec3!(1i8, 2.0f32, 3i16),
vek::Vec3::<f32>::new(1.0, 2.0, 3.0)
);
assert_eq!(
vec3!(vek::Vec3::new(1i8, 2i8, 3i8)),
vek::Vec3::<f32>::new(1.0, 2.0, 3.0),
);
assert_eq!(i32vec3!(1, 2, 3), vek::Vec3::<i32>::new(1, 2, 3));
assert_eq!(u64vec3!(1, 2, 3), vek::Vec3::<u64>::new(1, 2, 3));
assert_eq!(dvec3!(1.0, 2.0, 3.0), vek::Vec3::<f64>::new(1.0, 2.0, 3.0));
}
#[test]
fn test_vec4_combinations() {
assert_eq!(
vec4!(1.0f32, 2.0f32, 3.0f32, 4.0f32),
vek::Vec4::<f32>::new(1.0, 2.0, 3.0, 4.0),
);
assert_eq!(
vec4!(1i8, 2i8, 3i8, 4i8),
vek::Vec4::<f32>::new(1.0, 2.0, 3.0, 4.0),
);
assert_eq!(
vec4!(vek::Vec3::new(1i16, 2i16, 3i16), 4i8),
vek::Vec4::<f32>::new(1.0, 2.0, 3.0, 4.0),
);
assert_eq!(
vec4!(1.0f32, vek::Vec3::new(2i8, 3i8, 4i8)),
vek::Vec4::<f32>::new(1.0, 2.0, 3.0, 4.0),
);
assert_eq!(
vec4!(vek::Vec2::new(1i8, 2i8), vek::Vec2::new(3i8, 4i8)),
vek::Vec4::<f32>::new(1.0, 2.0, 3.0, 4.0),
);
assert_eq!(
vec4!(vek::Vec4::new(1i8, 2i8, 3i8, 4i8)),
vek::Vec4::<f32>::new(1.0, 2.0, 3.0, 4.0),
);
assert_eq!(ivec4!(1, 2, 3, 4), vek::Vec4::<i32>::new(1, 2, 3, 4));
assert_eq!(u8vec4!(1, 2, 3, 4), vek::Vec4::<u8>::new(1, 2, 3, 4));
}
}