-
Notifications
You must be signed in to change notification settings - Fork 155
/
build.rs
101 lines (96 loc) · 3.72 KB
/
build.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
use std::env;
use std::fs::File;
use std::io::Write;
use std::path::Path;
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
#[cfg(feature = "swizzle")]
fn gen_swizzle_nth(variables: &str, mut i: usize, upto: 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() + 1;
for _ in 0..upto {
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 /= n;
}
Some((swizzle, swizzle_impl))
}
/// A function that generates swizzle functions as a string.
/// `variables`: swizzle variables (e.g. "xyz")
/// `upto`: largest output vector size (e.g. for `variables = "xy"` and `upto = 4`, `xyxy()` is a
/// valid swizzle operator.
/// NOTE: This function assumes that variables are in ASCII format
#[cfg(feature = "swizzle")]
fn gen_swizzle_functions(variables: &'static str, upto: usize) -> String {
let mut result = String::new();
let nn = (variables.len() + 1).pow(upto as u32);
for i in 1..nn {
if let Some((swizzle_name, swizzle_impl)) = gen_swizzle_nth(variables, i, upto) {
let dim = format!("{}", swizzle_name.len());
result.push_str(&format!(
"
/// Swizzle operator that creates a new type with dimension {2} from variables `{0}`.
#[inline] pub fn {0}(&self) -> $vector_type{2}<$S> {{ $vector_type{2}::new({1}) }}\n",
swizzle_name, swizzle_impl, dim
));
}
}
result
}
#[cfg(not(feature = "swizzle"))]
fn gen_swizzle_functions(_: &'static str, _: usize) -> String {
String::new()
}
/// This script generates the macro for building swizzle operators for multidimensional
/// vectors and points. This macro is included in macros.rs
fn main() {
// 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_type1:ident, $vector_type2:ident, $vector_type3:ident, $S:ident, x) => {{
{x3}
}};
($vector_type1:ident, $vector_type2:ident, $vector_type3:ident, $S:ident, xy) => {{
{xy3}
}};
($vector_type1:ident, $vector_type2:ident, $vector_type3:ident, $S:ident, xyz) => {{
{xyz3}
}};
($vector_type1:ident, $vector_type2:ident, $vector_type3:ident, $vector_type4:ident, $S:ident, x) => {{
{x4}
}};
($vector_type1:ident, $vector_type2:ident, $vector_type3:ident, $vector_type4:ident, $S:ident, xy) => {{
{xy4}
}};
($vector_type1:ident, $vector_type2:ident, $vector_type3:ident, $vector_type4:ident, $S:ident, xyz) => {{
{xyz4}
}};
($vector_type1:ident, $vector_type2:ident, $vector_type3:ident, $vector_type4:ident, $S:ident, xyzw) => {{
{xyzw4}
}};
}}", x3 = gen_swizzle_functions("x", 3),
xy3 = gen_swizzle_functions("xy", 3),
xyz3 = gen_swizzle_functions("xyz", 3),
x4 = gen_swizzle_functions("x", 4),
xy4 = gen_swizzle_functions("xy", 4),
xyz4 = gen_swizzle_functions("xyz", 4),
xyzw4 = gen_swizzle_functions("xyzw", 4));
let mut f = File::create(swizzle_file_path)
.expect("Unable to create file that defines the swizzle operator macro.");
f.write_all(data.as_bytes())
.expect("Unable to write swizzle operator macro.");
}