|
| 1 | +use pyo3_introspection::model::{Argument, Arguments, Expr, Function, Module}; |
1 | 2 | use pyo3_introspection::{introspect_cdylib, module_stub_files}; |
2 | 3 | use std::path::{Path, PathBuf}; |
3 | 4 | use std::{env, fs}; |
4 | 5 |
|
| 6 | +const SWIZZLE_CHARS: [char; 4] = ['x', 'y', 'z', 'w']; |
| 7 | + |
| 8 | +fn swizzle_props(dim: usize) -> Vec<Function> { |
| 9 | + let chars = &SWIZZLE_CHARS[..dim]; |
| 10 | + let mut out = Vec::new(); |
| 11 | + for length in 2..=4 { |
| 12 | + let count = chars.len().pow(length as u32); |
| 13 | + for n in 0..count { |
| 14 | + let mut name = String::with_capacity(length); |
| 15 | + let mut idx = n; |
| 16 | + for _ in 0..length { |
| 17 | + name.push(chars[idx % chars.len()]); |
| 18 | + idx /= chars.len(); |
| 19 | + } |
| 20 | + out.push(Function { |
| 21 | + name, |
| 22 | + decorators: vec![Expr::Name { |
| 23 | + id: "property".into(), |
| 24 | + }], |
| 25 | + arguments: Arguments { |
| 26 | + positional_only_arguments: vec![Argument { |
| 27 | + name: "self".into(), |
| 28 | + default_value: None, |
| 29 | + annotation: None, |
| 30 | + }], |
| 31 | + arguments: vec![], |
| 32 | + vararg: None, |
| 33 | + keyword_only_arguments: vec![], |
| 34 | + kwarg: None, |
| 35 | + }, |
| 36 | + returns: Some(Expr::Attribute { |
| 37 | + value: Box::new(Expr::Name { |
| 38 | + id: "mewnala.math".into(), |
| 39 | + }), |
| 40 | + attr: format!("Vec{length}"), |
| 41 | + }), |
| 42 | + is_async: false, |
| 43 | + docstring: None, |
| 44 | + }); |
| 45 | + } |
| 46 | + } |
| 47 | + out |
| 48 | +} |
| 49 | + |
| 50 | +fn inject_swizzles(module: &mut Module) { |
| 51 | + for math in module.modules.iter_mut().filter(|m| m.name == "math") { |
| 52 | + for cls in math.classes.iter_mut() { |
| 53 | + let dim = match cls.name.as_str() { |
| 54 | + "Vec2" => 2, |
| 55 | + "Vec3" => 3, |
| 56 | + "Vec4" => 4, |
| 57 | + _ => continue, |
| 58 | + }; |
| 59 | + let existing: std::collections::HashSet<String> = |
| 60 | + cls.methods.iter().map(|m| m.name.clone()).collect(); |
| 61 | + cls.methods.extend( |
| 62 | + swizzle_props(dim) |
| 63 | + .into_iter() |
| 64 | + .filter(|m| !existing.contains(&m.name)), |
| 65 | + ); |
| 66 | + } |
| 67 | + } |
| 68 | +} |
| 69 | + |
5 | 70 | fn workspace_root() -> &'static Path { |
6 | 71 | Path::new(env!("CARGO_MANIFEST_DIR")) |
7 | 72 | .parent() |
@@ -45,6 +110,7 @@ fn main() { |
45 | 110 | introspect_cdylib(&cdylib_path, "mewnala").expect("Failed to introspect cdylib"); |
46 | 111 |
|
47 | 112 | module.incomplete = false; |
| 113 | + inject_swizzles(&mut module); |
48 | 114 |
|
49 | 115 | let stubs = module_stub_files(&module); |
50 | 116 |
|
|
0 commit comments