blockly_rust_compiler/
blockly_bridge.rs1use serde::{Deserialize, Serialize};
4use std::fs;
5use std::path::Path;
6
7pub fn load_blockly_genome(path: &Path) -> Result<BlocklyGenome, Box<dyn std::error::Error>> {
9 let content = fs::read_to_string(path)?;
10 let genome: BlocklyGenome = serde_json::from_str(&content)?;
11 Ok(genome)
12}
13
14pub fn save_blockly_genome(genome: &BlocklyGenome, path: &Path) -> Result<(), Box<dyn std::error::Error>> {
16 let json = serde_json::to_string_pretty(genome)?;
17 fs::write(path, json)?;
18 Ok(())
19}
20
21#[derive(Debug, Clone, Serialize, Deserialize)]
23pub struct BlocklyGenome {
24 pub name: String,
25 pub initial_mode: usize,
26 pub initial_orientation: Quaternion,
27 pub modes: Vec<BlocklyMode>,
28}
29
30#[derive(Debug, Clone, Serialize, Deserialize)]
31pub struct BlocklyMode {
32 pub name: String,
33 pub default_name: String,
34 pub color: Color3,
35 pub cell_type: u32,
36 pub parent_make_adhesion: bool,
37 pub split_mass: f32,
38 pub split_interval: f32,
39 pub parent_split_direction: Vec2,
40 pub max_adhesions: u32,
41 pub min_adhesions: u32,
42 pub enable_parent_angle_snapping: bool,
43 pub max_splits: i32,
44 pub mode_a_after_splits: i32,
45 pub mode_b_after_splits: i32,
46 pub child_a: ChildSettings,
47 pub child_b: ChildSettings,
48 pub adhesion_settings: AdhesionSettings,
49}
50
51#[derive(Debug, Clone, Serialize, Deserialize)]
52pub struct ChildSettings {
53 pub mode_number: usize,
54 pub orientation: Quaternion,
55 pub keep_adhesion: bool,
56 pub enable_angle_snapping: bool,
57}
58
59#[derive(Debug, Clone, Serialize, Deserialize)]
60pub struct AdhesionSettings {
61 pub can_break: bool,
62 pub break_force: f32,
63 pub rest_length: f32,
64 pub linear_spring_stiffness: f32,
65 pub linear_spring_damping: f32,
66 pub orientation_spring_stiffness: f32,
67 pub orientation_spring_damping: f32,
68 pub max_angular_deviation: f32,
69 pub twist_constraint_stiffness: f32,
70 pub twist_constraint_damping: f32,
71 pub enable_twist_constraint: bool,
72}
73
74#[derive(Debug, Clone, Serialize, Deserialize)]
75pub struct Quaternion {
76 pub x: f32,
77 pub y: f32,
78 pub z: f32,
79 pub w: f32,
80}
81
82#[derive(Debug, Clone, Serialize, Deserialize)]
83pub struct Color3 {
84 pub x: f32,
85 pub y: f32,
86 pub z: f32,
87}
88
89#[derive(Debug, Clone, Serialize, Deserialize)]
90pub struct Vec2 {
91 pub x: f32,
92 pub y: f32,
93}
94
95pub fn validate_wgsl_shader(source: &str) -> Result<(), String> {
107 if !source.contains("@compute") {
109 return Err("Missing @compute attribute".to_string());
110 }
111 if !source.contains("@workgroup_size") {
112 return Err("Missing @workgroup_size attribute".to_string());
113 }
114 Ok(())
115}
116
117pub fn load_blockly_wgsl(path: &Path) -> Result<String, Box<dyn std::error::Error>> {
118 let source = fs::read_to_string(path)?;
119 validate_wgsl_shader(&source)?;
120 Ok(source)
121}
122
123#[cfg(test)]
124mod tests {
125 use super::*;
126
127 #[test]
128 fn test_genome_serialization() {
129 let genome = BlocklyGenome {
130 name: "Test Genome".to_string(),
131 initial_mode: 0,
132 initial_orientation: Quaternion { x: 0.0, y: 0.0, z: 0.0, w: 1.0 },
133 modes: vec![],
134 };
135
136 let json = serde_json::to_string(&genome).unwrap();
137 let deserialized: BlocklyGenome = serde_json::from_str(&json).unwrap();
138
139 assert_eq!(genome.name, deserialized.name);
140 assert_eq!(genome.initial_mode, deserialized.initial_mode);
141 }
142
143 #[test]
144 fn test_wgsl_validation() {
145 let valid_shader = "@compute @workgroup_size(64) fn main() {}";
146 assert!(validate_wgsl_shader(valid_shader).is_ok());
147
148 let invalid_shader = "fn main() {}";
149 assert!(validate_wgsl_shader(invalid_shader).is_err());
150 }
151}