Crates.io | oors |
lib.rs | oors |
version | 0.9.2 |
created_at | 2025-09-09 01:24:25.029392+00 |
updated_at | 2025-09-16 03:15:52.849233+00 |
description | Adding cross-crate inheritance features to Rust structs |
homepage | |
repository | https://gitlab.com/eligamii/oors |
max_upload_size | |
id | 1830115 |
size | 29,205 |
A little experiment in adding cross-crate inheritance features to Rust structs
using a single #[oors::object]
macro.
crate_a
:
#[derive(Default)]
#[oors::object]
pub struct Animal { // Is a #[repr(C)] struct
age: u8,
name: String,
}
#[oors::object]
pub struct Insect {
dangerous: bool,
speed_in_kmh: usize
}
#[derive(Default)]
#[oors::object(parent = Animal)]
pub struct Dog {
// Gets a `base: Animal,` at offset 0 of self
wants_to_play: bool,
is_angry: bool,
/// Each word that the dog understand (like "come")
learnt: Vec<String>
}
#[object_impl]
impl Dog {
// Implemented for Dog
pub fn new(name: String) -> Typed<Self> {
Dog::from_value(Default::default())
.with_name(name)
.build()
}
// Implemented for IsA<Dog> (Dog and all of its children)
fn bark(&self) {
match *self.age_ref() { // <-- Access to Animal's fields
a if a < 1 => println!("Wif! Wif!"),
b if b > 1 && b < 7 => println!("Wouf!"),
c if c < 15 => println!("Waf!"),
_ => println!("Wouf...")
}
}
}
crate_b
:
// This is necessary for #[object] to work with crate_a's types
// alternatively, you can use the `#[obj_use]` macro along with the
// feature "nightly"
use crate_a::*;
#[oors::object(parent = Dog)]
pub struct Husky {
/// The number of kilometers that the dog is capable of running
energy_left: usize
}
fn main() {
let husky = Husky::builder()
.insert_value(Dog::new("Max")) // <- Equivalent to a `..Dog::new(...)` in struct expression
.with_learnt(vec!["Donne la pa-patte", "Couché", "Debout"])
.with_energy_left(usize::MAX) // <- Gets the documentation of `Husky`
.build(); // Fails if not all of its fields were implemented
let animal = husky.upcast_ref::<Animal>(); // This is a &oors::Typed<Animal>
// `husky.upcast_ref::<Insect>()` doesn't compile as Husky doesn't impl IsA<Insect>
get_genome(animal);
// Actually, `animal` is still a Husky
let still_husky = animal.try_cast_ref::<Husky>().unwrap();
still_husky.bark(); // <-- Access `Dog`'s methods
// Typed store the *actual* type of Husky and all of its parents
still_husky.try_cast_ref::<Insect>().unwrap_err();
}