summaryrefslogtreecommitdiff
path: root/vendor/crunchy/build.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/crunchy/build.rs')
-rw-r--r--vendor/crunchy/build.rs253
1 files changed, 253 insertions, 0 deletions
diff --git a/vendor/crunchy/build.rs b/vendor/crunchy/build.rs
new file mode 100644
index 0000000..b9c69ae
--- /dev/null
+++ b/vendor/crunchy/build.rs
@@ -0,0 +1,253 @@
+use std::env;
+use std::fs::File;
+use std::io::Write;
+use std::path::Path;
+
+const LOWER_LIMIT: usize = 16;
+
+fn main() {
+ let limit = if cfg!(feature="limit_2048") {
+ 2048
+ } else if cfg!(feature="limit_1024") {
+ 1024
+ } else if cfg!(feature="limit_512") {
+ 512
+ } else if cfg!(feature="limit_256") {
+ 256
+ } else if cfg!(feature="limit_128") {
+ 128
+ } else {
+ 64
+ };
+
+ let out_dir = env::var("OUT_DIR").unwrap();
+ let dest_path = Path::new(&out_dir).join("lib.rs");
+ let mut f = File::create(&dest_path).unwrap();
+
+ let mut output = String::new();
+
+ output.push_str(r#"
+/// Unroll the given for loop
+///
+/// Example:
+///
+/// ```ignore
+/// unroll! {
+/// for i in 0..5 {
+/// println!("Iteration {}", i);
+/// }
+/// }
+/// ```
+///
+/// will expand into:
+///
+/// ```ignore
+/// { println!("Iteration {}", 0); }
+/// { println!("Iteration {}", 1); }
+/// { println!("Iteration {}", 2); }
+/// { println!("Iteration {}", 3); }
+/// { println!("Iteration {}", 4); }
+/// ```
+#[macro_export]
+macro_rules! unroll {
+ (for $v:ident in 0..0 $c:block) => {};
+
+ (for $v:ident < $max:tt in ($start:tt..$end:tt).step_by($val:expr) {$($c:tt)*}) => {
+ {
+ let step = $val;
+ let start = $start;
+ let end = start + ($end - start) / step;
+ unroll! {
+ for val < $max in start..end {
+ let $v: usize = ((val - start) * step) + start;
+
+ $($c)*
+ }
+ }
+ }
+ };
+
+ (for $v:ident in ($start:tt..$end:tt).step_by($val:expr) {$($c:tt)*}) => {
+ unroll! {
+ for $v < $end in ($start..$end).step_by($val) {$($c)*}
+ }
+ };
+
+ (for $v:ident in ($start:tt..$end:tt) {$($c:tt)*}) => {
+ unroll!{
+ for $v in $start..$end {$($c)*}
+ }
+ };
+
+ (for $v:ident in $start:tt..$end:tt {$($c:tt)*}) => {
+ #[allow(non_upper_case_globals)]
+ #[allow(unused_comparisons)]
+ {
+ unroll!(@$v, 0, $end, {
+ if $v >= $start {$($c)*}
+ }
+ );
+ }
+ };
+
+ (for $v:ident < $max:tt in $start:tt..$end:tt $c:block) => {
+ #[allow(non_upper_case_globals)]
+ {
+ let range = $start..$end;
+ assert!(
+ $max >= range.end,
+ "`{}` out of range `{:?}`",
+ stringify!($max),
+ range,
+ );
+ unroll!(
+ @$v,
+ 0,
+ $max,
+ {
+ if $v >= range.start && $v < range.end {
+ $c
+ }
+ }
+ );
+ }
+ };
+
+ (for $v:ident in 0..$end:tt {$($statement:tt)*}) => {
+ #[allow(non_upper_case_globals)]
+ { unroll!(@$v, 0, $end, {$($statement)*}); }
+ };
+
+"#);
+
+ for i in 0..limit + 1 {
+ output.push_str(format!(" (@$v:ident, $a:expr, {}, $c:block) => {{\n", i).as_str());
+
+ if i <= LOWER_LIMIT {
+ output.push_str(format!(" {{ const $v: usize = $a; $c }}\n").as_str());
+
+ for a in 1..i {
+ output.push_str(format!(" {{ const $v: usize = $a + {}; $c }}\n", a).as_str());
+ }
+ } else {
+ let half = i / 2;
+
+ if i % 2 == 0 {
+ output.push_str(format!(" unroll!(@$v, $a, {0}, $c);\n", half).as_str());
+ output.push_str(format!(" unroll!(@$v, $a + {0}, {0}, $c);\n", half).as_str());
+ } else {
+ if half > 1 {
+ output.push_str(format!(" unroll!(@$v, $a, {}, $c);\n", i - 1).as_str())
+ }
+
+ output.push_str(format!(" {{ const $v: usize = $a + {}; $c }}\n", i - 1).as_str());
+ }
+ }
+
+ output.push_str(" };\n\n");
+ }
+
+ output.push_str("}\n\n");
+
+ output.push_str(format!(r#"
+#[cfg(all(test, feature = "std"))]
+mod tests {{
+ #[test]
+ fn invalid_range() {{
+ let mut a: Vec<usize> = vec![];
+ unroll! {{
+ for i in (5..4) {{
+ a.push(i);
+ }}
+ }}
+ assert_eq!(a, vec![]);
+ }}
+
+ #[test]
+ fn start_at_one_with_step() {{
+ let mut a: Vec<usize> = vec![];
+ unroll! {{
+ for i in (2..4).step_by(1) {{
+ a.push(i);
+ }}
+ }}
+ assert_eq!(a, vec![2, 3]);
+ }}
+
+ #[test]
+ fn start_at_one() {{
+ let mut a: Vec<usize> = vec![];
+ unroll! {{
+ for i in 1..4 {{
+ a.push(i);
+ }}
+ }}
+ assert_eq!(a, vec![1, 2, 3]);
+ }}
+
+ #[test]
+ fn test_all() {{
+ {{
+ let a: Vec<usize> = vec![];
+ unroll! {{
+ for i in 0..0 {{
+ a.push(i);
+ }}
+ }}
+ assert_eq!(a, (0..0).collect::<Vec<usize>>());
+ }}
+ {{
+ let mut a: Vec<usize> = vec![];
+ unroll! {{
+ for i in 0..1 {{
+ a.push(i);
+ }}
+ }}
+ assert_eq!(a, (0..1).collect::<Vec<usize>>());
+ }}
+ {{
+ let mut a: Vec<usize> = vec![];
+ unroll! {{
+ for i in 0..{0} {{
+ a.push(i);
+ }}
+ }}
+ assert_eq!(a, (0..{0}).collect::<Vec<usize>>());
+ }}
+ {{
+ let mut a: Vec<usize> = vec![];
+ let start = {0} / 4;
+ let end = start * 3;
+ unroll! {{
+ for i < {0} in start..end {{
+ a.push(i);
+ }}
+ }}
+ assert_eq!(a, (start..end).collect::<Vec<usize>>());
+ }}
+ {{
+ let mut a: Vec<usize> = vec![];
+ unroll! {{
+ for i in (0..{0}).step_by(2) {{
+ a.push(i);
+ }}
+ }}
+ assert_eq!(a, (0..{0} / 2).map(|x| x * 2).collect::<Vec<usize>>());
+ }}
+ {{
+ let mut a: Vec<usize> = vec![];
+ let start = {0} / 4;
+ let end = start * 3;
+ unroll! {{
+ for i < {0} in (start..end).step_by(2) {{
+ a.push(i);
+ }}
+ }}
+ assert_eq!(a, (start..end).filter(|x| x % 2 == 0).collect::<Vec<usize>>());
+ }}
+ }}
+}}
+"#, limit).as_str());
+
+ f.write_all(output.as_bytes()).unwrap();
+}