diff --git a/build.rs b/build.rs index 3c2e7dc..9a7b93d 100644 --- a/build.rs +++ b/build.rs @@ -6,56 +6,63 @@ use std::string::String; /// Generate the name of the swizzle function and what it returns. /// NOTE: This function assumes that variables are in ASCII format -fn gen_swizzle_nth(variables: &'static str, mut i: usize) -> (String, String) { +fn gen_swizzle_nth<'a>(variables: &'a str, mut i: usize) -> Option<(String, String)> { + debug_assert!(i > 0); // zeroth permutation is empty let mut swizzle_impl = String::new(); let mut swizzle = String::new(); - let n = variables.len(); - for _ in 0..n { - let c = variables.as_bytes()[i%n] as char; + let n = variables.len()+1; + for _ in 0..variables.len() { + if i == 0 { break; } + if i % n == 0 { return None; } + let c = variables.as_bytes()[i%n - 1] as char; swizzle.push(c); swizzle_impl.push_str(&format!("self.{}, ", c)); i = i/n; } - (swizzle, swizzle_impl) + Some((swizzle, swizzle_impl)) } -/// This script generates the swizzle operators that are included in macros.rs /// NOTE: This function assumes that variables are in ASCII format fn gen_swizzle_functions(variables: &'static str) -> String { let n = variables.len(); - let vec_type = format!("$vector_type{}", n); let mut result = String::new(); - let nn = n.pow(n as u32); - for i in 0..nn { - let (swizzle_name, swizzle_impl) = gen_swizzle_nth(variables, i); - result.push_str( - &format!(" #[inline] pub fn {0}(&self) -> {2}<$S> {{ {2}::new({1}) }}\n", - swizzle_name, swizzle_impl, vec_type)); + let nn = (n+1).pow(n as u32); + for i in 1..nn { + if let Some((swizzle_name, swizzle_impl)) = gen_swizzle_nth(variables, i) { + let vec_type = format!("$vector_type{}", swizzle_name.len()); + result.push_str( + &format!(" #[inline] pub fn {0}(&self) -> {2}<$S> {{ {2}::new({1}) }}\n", + swizzle_name, swizzle_impl, vec_type)); + } } result } +/// This script generates the macro for building swizzle operators for multidimensional +/// vectors and points. This macro is included in macros.rs fn main() { - // The following scripts generates a macro for building swizzle operators for multidimensional - // vectors or points. + // save the file to output directory let out_dir = env::var("OUT_DIR").unwrap(); let swizzle_file_path = Path::new(&out_dir).join("swizzle_operator_macro.rs"); + // This is the string representing the generated macro let data = format!( "/// Generate glm/glsl style swizzle operators macro_rules! impl_swizzle_functions {{ - ($vector_type2:ident, $S:ident, xy) => {{ + ($vector_type1:ident, $S:ident, x) => {{ +{x} + }}; + ($vector_type1:ident, $vector_type2:ident, $S:ident, xy) => {{ {xy} }}; - ($vector_type2:ident, $vector_type3:ident, $S:ident, xyz) => {{ - impl_swizzle_functions!($vector_type2, $S, xy); + ($vector_type1:ident, $vector_type2:ident, $vector_type3:ident, $S:ident, xyz) => {{ {xyz} }}; - ($vector_type2:ident, $vector_type3:ident, $vector_type4:ident, $S:ident, xyzw) => {{ - impl_swizzle_functions!($vector_type2, $vector_type3, $S, xyz); + ($vector_type1:ident, $vector_type2:ident, $vector_type3:ident, $vector_type4:ident, $S:ident, xyzw) => {{ {xyzw} }}; -}}", xy=gen_swizzle_functions("xy"), +}}", x=gen_swizzle_functions("x"), + xy=gen_swizzle_functions("xy"), xyz=gen_swizzle_functions("xyz"), xyzw=gen_swizzle_functions("xyzw")); let mut f = File::create(swizzle_file_path) diff --git a/src/point.rs b/src/point.rs index 35550e3..9436c22 100644 --- a/src/point.rs +++ b/src/point.rs @@ -69,6 +69,8 @@ impl Point1 { pub fn new(x: S) -> Point1 { Point1 { x: x } } + + impl_swizzle_functions!(Point1, S, x); } impl Point2 { @@ -76,6 +78,8 @@ impl Point2 { pub fn new(x: S, y: S) -> Point2 { Point2 { x: x, y: y } } + + impl_swizzle_functions!(Point1, Point2, S, xy); } impl Point3 { @@ -83,6 +87,8 @@ impl Point3 { pub fn new(x: S, y: S, z: S) -> Point3 { Point3 { x: x, y: y, z: z } } + + impl_swizzle_functions!(Point1, Point2, Point3, S, xyz); } impl Point3 { diff --git a/src/vector.rs b/src/vector.rs index 1b395d1..7ebf06c 100644 --- a/src/vector.rs +++ b/src/vector.rs @@ -605,6 +605,8 @@ impl Vector1 { pub fn unit_x() -> Vector1 { Vector1::new(S::one()) } + + impl_swizzle_functions!(Vector1, S, x); } impl Vector2 { @@ -632,6 +634,8 @@ impl Vector2 { pub fn extend(self, z: S) -> Vector3 { Vector3::new(self.x, self.y, z) } + + impl_swizzle_functions!(Vector1, Vector2, S, xy); } impl Vector3 { @@ -674,6 +678,8 @@ impl Vector3 { pub fn truncate(self) -> Vector2 { Vector2::new(self.x, self.y) } + + impl_swizzle_functions!(Vector1, Vector2, Vector3, S, xyz); } impl Vector4 { @@ -718,6 +724,8 @@ impl Vector4 { _ => panic!("{:?} is out of range", n), } } + + impl_swizzle_functions!(Vector1, Vector2, Vector3, Vector4, S, xyzw); } /// Dot product of two vectors.