Crate vecn

Source
Expand description

Crates.io Docs.rs MIT licensed Build Status

Provides the #[vector] macro, which transforms user-defined structs into general vector types by conditionally implementing appropriate traits and methods for them.

§Examples

Vector types can be either named structs or tuple structs, with primitive elements.

use vecn::vector;

#[vector]
pub struct Rgb(u8, u8, u8);

#[vector]
pub struct Point3 {
    pub x: f32,
    pub y: f32,
    pub z: f32,
}

Generic vector types is supported as well, but you need to manually add the num_traits crate to your Cargo.toml, as we use some num traits to properly bound methods.

It’s recommend to implement primitive vector types whenever possible, because unlike generic vector types that will cluster a bunch of bounded methods together, methods implemented for primitive vector types are concise and adequate, which means compiler won’t allow you to call a meaningless method accidentally.

use vecn::vector;

#[vector]
pub struct Vec4<T> {
   pub x: T,
   pub y: T,
   pub z: T,
   pub w: T,
}

let point1 = Vec4::new(2., 2., 2., 1.);
let point2 = Vec4::new(4., 2., 2., 1.);
let distance = point1.distance(point2);
assert_eq!(distance, 2.);

It’s possible to create a vector type with many lanes, though only a small set of methods will be implemented for it.

use vecn::vector;

#[vector]
pub struct Vec8<T>(T, T, T, T, T, T, T, T);

let v8: Vec8<u8> = (0u8, 1, 2, 3, 4, 5, 6, 7).into();
assert_eq!(v8.sum(), 28);
assert_eq!(v8.product(), 0);

§Documentation

You can view the traits and methods implemented for the annotated struct using cargo doc in your project’s workspace, if the annotated struct is public. For situations where the annotated struct cannot be public, you can look at some example vector types that generated by the #[vector] macro from vectory.

§Additional Notes

#[vector] will automatically derive Copy, Clone and PartialEq traits for the annotated struct for convenience. Many methods rely on these properties to functionally work. If you want to derive more traits for a vector type, put them below the #[vector] attribute (otherwise the compiler will yell at you), like so:

#[vector]
#[derive(Debug)]
pub struct Point3(f32, f32, f32);

Besides, it’s worth noting that vecn will only implement a suitable set of traits and methods for the annotated struct. Some traits like Display should be better implemented by users, and some methods are missing for varying reasons. Hopefully the annotated struct is totally local to user space, you are free to implement whatever methods and traits you like.

use vecn::vector;
use std::fmt;

#[vector]
pub struct Vec3(f32, f32, f32);

#[vector]
pub struct Vec4(f32, f32, f32, f32);

impl Vec4 {
    /// Shrinks a `Vec4` to a `Vec3`, with its last lane discarded.
    #[inline]
    pub fn shrink(self) -> Vec3 {
        let (x, y, z, _) = self.into();
        Vec3::new(x, y, z)
    }
}

// As we don't know the relations between vector types, `From` trait needed to implement
// manually.
impl From<Vec3> for Vec4 {
    #[inline]
    fn from(v3: Vec3) -> Vec4 {
        Vec4::new(v3.0, v3.1, v3.2, 0.)
    }
}

impl fmt::Display for Vec3 {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "({}, {}, {})", self.0, self.1, self.2)
    }
}

impl fmt::Display for Vec4 {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "({}, {}, {}, {})", self.0, self.1, self.2, self.3)
    }
}

Attribute Macros§

  • Macro that transforms user-defined structs into general vector types.