Validating Rusty Object Notation file match data structures "automagically"
⚓ Rust 📅 2026-02-06 👤 surdeus 👁️ 8I've been writing a small game (It's not really a game at the moment) and my current feature I'm trying to implement is removing hard coded data structure initialisation and instead loading these from text files (.ron files). So I can change things without having to recompile. The downside being that I now lose any kind of compile time checking that my initialisation data matches my data structures which kinda sucks since the compile time safety of rust is something that I really enjoy coming from a C background.
So I've been trying to come up with some ways to validate that all my .ron files still correctly deserialise to the data structure they are designed for but I haven't found any elegant solutions which I feel surely there is one.
Firstly some code to hopefully explain what I'm going on about
#[derive(Deserialize,Serialize)]
pub struct Drawable {
pub x: i32,
pub y: i32,
pub w: u32,
pub h: u32,
pub layer: u32,
}
#[derive(Serialize,Deserialize)]
pub struct Animation {
pub frames: Vec<Drawable>,
pub fps: f64,
pub flip_horizontal: bool,
pub flip_vertical: bool,
pub looping: bool,
}
Previously I would initialise an "Animation" like so in my rust code:
let animation_standing_up = Animation::new_with_frames(
vec![
Drawable::new(0, 272, 15, 15, layer),
],
0.0,
false,
false,
false,
);
But now instead I can load it from a .ron file which looks like so:
Animation(
frames: [
Drawable(x:16, y:272, w:15, h:15, layer:1),
],
fps: 0.0,
flip_horizontal: false,
flip_vertical: false,
looping: false,
)
With the downside that until I load the file at runtime I don't know whether its still valid.
Some of the ideas that I've bounced around with the help of gemini (yes I know....)
- Write a unit test that tries to deserialise a known list of .ron files into a known list of component types.
Why this sucks: Currently I only have very few data structures and very few .ron files. So it would be totally doable to write a test for each type and file. But it would be nicer although over engineered at the moment to automatically test all future .ron files and automatically support new component types. - Create an enum that encapsulates all component types and so that RON/serde will automagically work by having a single unit test that tries to deserialise all .ron files into the enum since you must know the type for ron deserialisation to work:
use super::*;
enum ComponentRegistry {
Animation(Animation),
Drawable(Drawable),
}
let content = load_ron_file("animation.ron");
ron::from_str<ComponentRegistry>(&content).unwrap(); //Test fails with panic on deserialisation mismatch
Good things about this: I could write a build.rs to automagically generate the ComponentRegistry enum
Why this sucks: This won't deserialise without modifying my .ron files. To match on ComponentRegistry::Animation I'd need to wrap the contents with something like `format!("Animation({})", contents);" for it to properly deserialise in the test case because serde is now trying to match on "Animation(Animation(/animation struct members/))". The problem is that RON doesn't seem to have a way to "Get me the name of the data structure" from the .ron file so I'd have to regex or do my own parsing so I could wrap it in the correct type which seems like I'm really doing something wrong at this point.
Also why this sucks: I could instead make the enum like this:
enum ComponentRegistry {
Animation {
frames: Vec<Drawable>,
fps: f64,
flip_horizontal: bool,
flip_vertical: bool,
looping: bool,
},
}
Which will totally work and I don't need to modify the .ron files in anyway, but it means I need to keep the ComponentRegistry internals structs and the original component structs in sync. I could write a build.rs to generate the ComponentRegistry which would totally work and I'm currently attempting to do this. But this is my first build.rs and code generation in rust ![]()
Anyway so I thought I'd ask if anyone has any better ideas? I feel like this is probably a solved problem and I just don't know the right keywords to type into google, similar to how I didn't know "interior mutability" was the keyword I needed in some of my previous problems or I'm just plain doing it wrong.
P.S I said earlier that I want compile time failure but in reality that's not true. I'm okay with .ron files not being correct at build time. I just want a tool I can run when I want or need to tell me "HEY YOU MESSED UP" such as a unit test. But I am interesting in knowing if I could make an invalid .ron file a compile time error. Since my plan is currently to use a build.rs which I know very little about I don't think I can have the build.rs validate the .ron files itself directly? Since it would need to discover all the .ron files, generate an enum by parsing other rust code and then write and run code based on that. Like some kind of multistep build.rs?
Anyway I appreciate any input and people taking the time to read my long rambling question.
1 post - 1 participant
🏷️ Rust_feed