Modeling layered tree in rust
I'm trying to model a structure for a UI library where there exists a ViewNode which owns a RenderNode which owns a LayoutNode. These structures should at the same time form three distinct trees. A ViewTree, a RenderTree, and a Layout tree.
Is there any way of modeling this ownership without resorting to use of Rc? I don't want to use Rc<> because the ownership is clear from my point of view, The trees should never own their children (except for ViewNode), the wrapper is the owner. Each layer should also be able to be pulled out into a library and I don't want to force users of the library to use Rc<>.
Below is what I would want to do but what doesn't work. Should I go about this in a different way perhaps?
#[derive(Debug)]
struct LayoutNode<'a> {
// .. Some fields
children: Vec<&'a LayoutNode<'a>>,
}
#[derive(Debug)]
struct RenderNode<'a> {
// .. Some fields
layout_node: LayoutNode<'a>,
children: Vec<&'a RenderNode<'a>>,
}
#[derive(Debug)]
struct ViewNode<'a> {
// .. Some fields
render_node: RenderNode<'a>,
children: Vec<ViewNode<'a>>,
}
fn make_tree<'a>() -> ViewNode<'a> {
let layout_child = LayoutNode { children: vec! };
let layout = LayoutNode { children: vec![&layout_child] };
let render_child = RenderNode { layout_node: layout_child, children: vec! };
let render = RenderNode { layout_node: layout, children: vec![&render_child] };
let view_child = ViewNode { render_node: render_child, children: vec! };
let view = ViewNode { render_node: render, children: vec![view_child] };
view
}
fn main() {
println!("{:?}", make_tree())
}
rust
add a comment |
I'm trying to model a structure for a UI library where there exists a ViewNode which owns a RenderNode which owns a LayoutNode. These structures should at the same time form three distinct trees. A ViewTree, a RenderTree, and a Layout tree.
Is there any way of modeling this ownership without resorting to use of Rc? I don't want to use Rc<> because the ownership is clear from my point of view, The trees should never own their children (except for ViewNode), the wrapper is the owner. Each layer should also be able to be pulled out into a library and I don't want to force users of the library to use Rc<>.
Below is what I would want to do but what doesn't work. Should I go about this in a different way perhaps?
#[derive(Debug)]
struct LayoutNode<'a> {
// .. Some fields
children: Vec<&'a LayoutNode<'a>>,
}
#[derive(Debug)]
struct RenderNode<'a> {
// .. Some fields
layout_node: LayoutNode<'a>,
children: Vec<&'a RenderNode<'a>>,
}
#[derive(Debug)]
struct ViewNode<'a> {
// .. Some fields
render_node: RenderNode<'a>,
children: Vec<ViewNode<'a>>,
}
fn make_tree<'a>() -> ViewNode<'a> {
let layout_child = LayoutNode { children: vec! };
let layout = LayoutNode { children: vec![&layout_child] };
let render_child = RenderNode { layout_node: layout_child, children: vec! };
let render = RenderNode { layout_node: layout, children: vec![&render_child] };
let view_child = ViewNode { render_node: render_child, children: vec! };
let view = ViewNode { render_node: render, children: vec![view_child] };
view
}
fn main() {
println!("{:?}", make_tree())
}
rust
add a comment |
I'm trying to model a structure for a UI library where there exists a ViewNode which owns a RenderNode which owns a LayoutNode. These structures should at the same time form three distinct trees. A ViewTree, a RenderTree, and a Layout tree.
Is there any way of modeling this ownership without resorting to use of Rc? I don't want to use Rc<> because the ownership is clear from my point of view, The trees should never own their children (except for ViewNode), the wrapper is the owner. Each layer should also be able to be pulled out into a library and I don't want to force users of the library to use Rc<>.
Below is what I would want to do but what doesn't work. Should I go about this in a different way perhaps?
#[derive(Debug)]
struct LayoutNode<'a> {
// .. Some fields
children: Vec<&'a LayoutNode<'a>>,
}
#[derive(Debug)]
struct RenderNode<'a> {
// .. Some fields
layout_node: LayoutNode<'a>,
children: Vec<&'a RenderNode<'a>>,
}
#[derive(Debug)]
struct ViewNode<'a> {
// .. Some fields
render_node: RenderNode<'a>,
children: Vec<ViewNode<'a>>,
}
fn make_tree<'a>() -> ViewNode<'a> {
let layout_child = LayoutNode { children: vec! };
let layout = LayoutNode { children: vec![&layout_child] };
let render_child = RenderNode { layout_node: layout_child, children: vec! };
let render = RenderNode { layout_node: layout, children: vec![&render_child] };
let view_child = ViewNode { render_node: render_child, children: vec! };
let view = ViewNode { render_node: render, children: vec![view_child] };
view
}
fn main() {
println!("{:?}", make_tree())
}
rust
I'm trying to model a structure for a UI library where there exists a ViewNode which owns a RenderNode which owns a LayoutNode. These structures should at the same time form three distinct trees. A ViewTree, a RenderTree, and a Layout tree.
Is there any way of modeling this ownership without resorting to use of Rc? I don't want to use Rc<> because the ownership is clear from my point of view, The trees should never own their children (except for ViewNode), the wrapper is the owner. Each layer should also be able to be pulled out into a library and I don't want to force users of the library to use Rc<>.
Below is what I would want to do but what doesn't work. Should I go about this in a different way perhaps?
#[derive(Debug)]
struct LayoutNode<'a> {
// .. Some fields
children: Vec<&'a LayoutNode<'a>>,
}
#[derive(Debug)]
struct RenderNode<'a> {
// .. Some fields
layout_node: LayoutNode<'a>,
children: Vec<&'a RenderNode<'a>>,
}
#[derive(Debug)]
struct ViewNode<'a> {
// .. Some fields
render_node: RenderNode<'a>,
children: Vec<ViewNode<'a>>,
}
fn make_tree<'a>() -> ViewNode<'a> {
let layout_child = LayoutNode { children: vec! };
let layout = LayoutNode { children: vec![&layout_child] };
let render_child = RenderNode { layout_node: layout_child, children: vec! };
let render = RenderNode { layout_node: layout, children: vec![&render_child] };
let view_child = ViewNode { render_node: render_child, children: vec! };
let view = ViewNode { render_node: render, children: vec![view_child] };
view
}
fn main() {
println!("{:?}", make_tree())
}
rust
rust
asked Jan 2 at 22:02
Emil SjölanderEmil Sjölander
1,12831527
1,12831527
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
You can use a memory arena that uses indices instead of reference counted pointers.
Using indextree as an example:
pub struct NodeId {
index: usize,
}
pub struct Node<T> {
parent: Option<NodeId>,
previous_sibling: Option<NodeId>,
next_sibling: Option<NodeId>,
first_child: Option<NodeId>,
last_child: Option<NodeId>,
removed: bool,
/// The actual data which will be stored within the tree
pub data: T,
}
pub struct Arena<T> {
nodes: Vec<Node<T>>,
}
The NodeId
struct is a simple integer index.
The nodes contain references to close by nodes (parent
, previous_sibling
, etc..) so to make for easy traversal.
A downside of this method is that it's very similar to manual memory management, in that you need to ensure that nodes are added/removed correctly to avoid dangling references. indextree
has a lot of error checking when adding/removing nodes in the tree for this reason.
You might also want to have a look at petgraph: While this is a Graph
instead of a Tree
you can use it as a tree.
add a comment |
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54013760%2fmodeling-layered-tree-in-rust%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
You can use a memory arena that uses indices instead of reference counted pointers.
Using indextree as an example:
pub struct NodeId {
index: usize,
}
pub struct Node<T> {
parent: Option<NodeId>,
previous_sibling: Option<NodeId>,
next_sibling: Option<NodeId>,
first_child: Option<NodeId>,
last_child: Option<NodeId>,
removed: bool,
/// The actual data which will be stored within the tree
pub data: T,
}
pub struct Arena<T> {
nodes: Vec<Node<T>>,
}
The NodeId
struct is a simple integer index.
The nodes contain references to close by nodes (parent
, previous_sibling
, etc..) so to make for easy traversal.
A downside of this method is that it's very similar to manual memory management, in that you need to ensure that nodes are added/removed correctly to avoid dangling references. indextree
has a lot of error checking when adding/removing nodes in the tree for this reason.
You might also want to have a look at petgraph: While this is a Graph
instead of a Tree
you can use it as a tree.
add a comment |
You can use a memory arena that uses indices instead of reference counted pointers.
Using indextree as an example:
pub struct NodeId {
index: usize,
}
pub struct Node<T> {
parent: Option<NodeId>,
previous_sibling: Option<NodeId>,
next_sibling: Option<NodeId>,
first_child: Option<NodeId>,
last_child: Option<NodeId>,
removed: bool,
/// The actual data which will be stored within the tree
pub data: T,
}
pub struct Arena<T> {
nodes: Vec<Node<T>>,
}
The NodeId
struct is a simple integer index.
The nodes contain references to close by nodes (parent
, previous_sibling
, etc..) so to make for easy traversal.
A downside of this method is that it's very similar to manual memory management, in that you need to ensure that nodes are added/removed correctly to avoid dangling references. indextree
has a lot of error checking when adding/removing nodes in the tree for this reason.
You might also want to have a look at petgraph: While this is a Graph
instead of a Tree
you can use it as a tree.
add a comment |
You can use a memory arena that uses indices instead of reference counted pointers.
Using indextree as an example:
pub struct NodeId {
index: usize,
}
pub struct Node<T> {
parent: Option<NodeId>,
previous_sibling: Option<NodeId>,
next_sibling: Option<NodeId>,
first_child: Option<NodeId>,
last_child: Option<NodeId>,
removed: bool,
/// The actual data which will be stored within the tree
pub data: T,
}
pub struct Arena<T> {
nodes: Vec<Node<T>>,
}
The NodeId
struct is a simple integer index.
The nodes contain references to close by nodes (parent
, previous_sibling
, etc..) so to make for easy traversal.
A downside of this method is that it's very similar to manual memory management, in that you need to ensure that nodes are added/removed correctly to avoid dangling references. indextree
has a lot of error checking when adding/removing nodes in the tree for this reason.
You might also want to have a look at petgraph: While this is a Graph
instead of a Tree
you can use it as a tree.
You can use a memory arena that uses indices instead of reference counted pointers.
Using indextree as an example:
pub struct NodeId {
index: usize,
}
pub struct Node<T> {
parent: Option<NodeId>,
previous_sibling: Option<NodeId>,
next_sibling: Option<NodeId>,
first_child: Option<NodeId>,
last_child: Option<NodeId>,
removed: bool,
/// The actual data which will be stored within the tree
pub data: T,
}
pub struct Arena<T> {
nodes: Vec<Node<T>>,
}
The NodeId
struct is a simple integer index.
The nodes contain references to close by nodes (parent
, previous_sibling
, etc..) so to make for easy traversal.
A downside of this method is that it's very similar to manual memory management, in that you need to ensure that nodes are added/removed correctly to avoid dangling references. indextree
has a lot of error checking when adding/removing nodes in the tree for this reason.
You might also want to have a look at petgraph: While this is a Graph
instead of a Tree
you can use it as a tree.
answered Jan 2 at 22:48
CetraCetra
2,14211724
2,14211724
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54013760%2fmodeling-layered-tree-in-rust%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown