summaryrefslogtreecommitdiff
path: root/ecs/build.rs
diff options
context:
space:
mode:
Diffstat (limited to 'ecs/build.rs')
-rw-r--r--ecs/build.rs98
1 files changed, 98 insertions, 0 deletions
diff --git a/ecs/build.rs b/ecs/build.rs
new file mode 100644
index 0000000..1fbde2a
--- /dev/null
+++ b/ecs/build.rs
@@ -0,0 +1,98 @@
+use std::collections::HashSet;
+use std::path::PathBuf;
+
+use itertools::Itertools;
+use proc_macro2::{Delimiter, Group, Ident};
+use quote::{format_ident, quote, ToTokens};
+
+const CNT: usize = 4;
+
+fn main()
+{
+ let out_dir = PathBuf::from(std::env::var("OUT_DIR").unwrap());
+
+ let impls = (0..CNT).flat_map(create_input_filter_impls).join("\n");
+
+ std::fs::write(out_dir.join("system_input_impls.rs"), impls).unwrap();
+}
+
+fn create_input_filter_impls(cnt: usize) -> Vec<proc_macro2::TokenStream>
+{
+ let mut present = HashSet::new();
+
+ let elements = (0..cnt)
+ .map(|_| ElementKind::Element)
+ .chain(vec![ElementKind::Excluded; cnt])
+ .permutations(cnt)
+ .filter(|combination| {
+ if present.contains(combination) {
+ return false;
+ }
+
+ present.insert(combination.clone());
+
+ true
+ })
+ .map(|elements| {
+ elements
+ .into_iter()
+ .enumerate()
+ .map(|(index, element)| match element {
+ ElementKind::Element => {
+ IdentOrTuple::Ident(format_ident!("Elem{index}"))
+ }
+ ElementKind::Excluded => IdentOrTuple::Tuple,
+ })
+ .collect::<Vec<_>>()
+ })
+ .collect::<Vec<_>>();
+
+ elements
+ .into_iter()
+ .map(create_single_input_filter_impl)
+ .collect()
+}
+
+fn create_single_input_filter_impl(
+ elements: Vec<IdentOrTuple>,
+) -> proc_macro2::TokenStream
+{
+ let ident_elements = elements
+ .iter()
+ .filter(|element| matches!(element, IdentOrTuple::Ident(_)))
+ .collect::<Vec<_>>();
+
+ quote! {
+ impl<#(#ident_elements: Input,)*> InputFilter for (#(#elements,)*) {
+ type Filtered = (#(#ident_elements,)*);
+ }
+ }
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+enum ElementKind
+{
+ Element,
+ Excluded,
+}
+
+#[derive(Debug)]
+enum IdentOrTuple
+{
+ Ident(Ident),
+ Tuple,
+}
+
+impl ToTokens for IdentOrTuple
+{
+ fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream)
+ {
+ match self {
+ Self::Ident(ident) => ident.to_tokens(tokens),
+ Self::Tuple => {
+ Group::new(Delimiter::Parenthesis, proc_macro2::TokenStream::new())
+ .to_tokens(tokens)
+ }
+ }
+ }
+}