Correct way to design structs


#1

Hello,
I’m new to Rust and I was wondering if the structure of these structs is correct, it should map a sort of tree of maps:

enum Cell {
    Breadcrumb(BreadcrumbData),
    Object(Rc<RefCell<RenderData>>),
}

struct RenderData {
    sub_map: Rc<RefCell<Option<Rc<RefCell<Map>>>>>,
    ...
}

struct BreadcrumbData {
    breadcrumbs: Vec<Rc<RefCell<Map>>>,
}

struct Map {
    objects: Rc<RefCell<Vec<Cell>>>
    ...
}

Each map contains a vec of cells, each cell could be an object or a Breadcrumb. Each object could contains a sub map (using RenderData), and each breadcrumb contains a list of parent\ancestors. I’m not sure about how the structs are connected together. I used so many Rc\RefCell because the data is changed in multiple places, is there a way to create the same in a more clean way?

Thank you :slightly_smiling_face:


#2

I’d suggest storing the data linearly in storages:

enum Cell {
    Breadcrumb(BreadCrumbId),
    Object(RenderId),
}

struct RenderData {
    sub_map: Option<MapId>,
    ...
}

struct BreadcrumbData {
    breadcrumbs: Vec<MapId>>,
}

struct Map {
    objects: Vec<CellId>,
    ...
}

let maps = vec![];
let breadcrumb_data = vec![];
...

Now, each ID is just an index into such a Vec. With this you can safely access the data from the storages.

If you want to get multiple items at once, you might want to look at https://github.com/diwic/splitmut-rs

There’s also a pattern called ECS that is based on this idea (and also lets you delete IDs, called entities, safely).

EDIT: Note though that there’s no “correct way”. What you did is pretty much an object oriented design with references, which works fine, too.


#3

If you want to use some library, here are a couple of references you might find useful:

  • petgraph - general graph library
  • Specs - ECS library (disclaimer: maintained by me)
  • froggy - Library for graph-like data structures

The last one is probably the one that’s closest to what you have now.