Nested struct with reference - nested

I have some nested structs and cannot create a back reference to the parent struct. An example:
struct Foo<'a> {
parent: &'a Bar<'a>,
}
impl<'a> Foo<'a> {
fn new(parent: &'a Bar) -> Self {
Foo { parent: parent }
}
fn hello_world(&self) -> String {
self.parent.hello().to_owned() + " world"
}
}
struct Bar<'b> {
child: Option<Foo<'b>>,
data: &'static str,
}
impl<'b> Bar<'b> {
fn new() -> Self {
Bar {
child: None,
data: "hello",
}
}
fn hello(&self) -> &str {
self.data
}
fn get_foo(&self) -> Option<&Foo> {
self.child.as_ref()
}
}
fn main() {
let bar = Bar::new();
assert_eq!("hello", bar.hello());
match bar.get_foo() {
Some(foo) => assert_eq!("hello world", foo.hello_world()),
None => (),
}
}
How can I replace None with Some<Foo> with a reference to Bar? So far I'm not sure that it is possible.

It's not exactly a drop-in solution for your example, but I believe you can create "circular references" as you specify using Arc and RwLock. The API is not exactly the same (e.g., parent is an optional field), I renamed some objects, and it is definitely more verbose, but your tests pass!
use std::sync::{Arc, RwLock};
#[derive(Debug, Clone)]
struct Child {
parent: Option<Arc<RwLock<Parent>>>
}
impl Child {
fn new() -> Self {
Child {
parent: None
}
}
fn hello_world(&self) -> String {
let x = self.parent.as_ref().unwrap().clone();
let y = x.read().unwrap();
y.hello().to_owned() + " world"
}
}
#[derive(Debug, Clone)]
struct Parent {
child: Option<Arc<RwLock<Child>>>,
data: &'static str
}
impl Parent {
fn new() -> Self {
Parent {
child: None,
data: "hello"
}
}
fn hello(&self) -> &str {
self.data
}
fn get_child(&self) -> Option<Arc<RwLock<Child>>> {
self.child.as_ref().map(|x| x.clone() )
}
}
fn main() {
let parent = Arc::new(RwLock::new(Parent::new()));
let child = Arc::new(RwLock::new(Child::new()));
parent.write().unwrap().child = Some(child.clone());
child.write().unwrap().parent = Some(parent.clone());
assert_eq!("hello", parent.read().unwrap().hello());
{
let x = parent.read().unwrap();
match x.get_child() {
Some(child) => { assert_eq!("hello world", child.read().unwrap().hello_world()); }
None => {},
}
}
}

I have a similar problem, and am not entirely satisfied with the proposed solutions.
If your structure is really nested (i.e. you have a notion of "parent" and "child", with a unique parent for each child), then it seems natural that the parent should own the child(ren). So using Rc/Arc (which are designed to allow for multiple owners) does not look like the right solution -- all the less so because, as #Shepmaster points out, it "encourages" (or at least allows) the creation of cyclic references.
My idea was to have each child hold a raw pointer to its parent:
pub struct Node {
parent: *mut Node,
// ...
}
Since a node is owned by its parent, it can only be borrowed (resp. mutably borrowed) while its parent is being borrowed (resp. mutably borrowed). So in that context, it should be safe to cast self.parent to a &Node (resp. &mut Node, if self is mutable).
impl Node {
pub fn get_parent(&self) -> Option<&Node> {
unsafe { self.parent.as_ref() }
}
pub fn get_mut_parent(&mut self) -> Option<&mut Node> {
unsafe { self.parent.as_mut() }
}
}
However, this requires that the address of the parent node never changes (i.e. the parent is never moved). This can be achieved by only ever handling boxed nodes.
pub struct Node {
parent: *mut Node,
children: Vec<Box<Node>>,
// ..
}
impl Node {
pub fn new(data: &str) -> Box<Node> {
Box::new(Node {
parent: std::ptr::null_mut(),
children: vec![],
// ..
})
}
pub fn append_child(&mut self, mut child: Box<Node>) -> usize {
child.parent = self;
self.children.push(child);
self.children.len() - 1
}
}
I implemented a full-fledged example in the playground.

Related

How do I downgrade an Rc<RefCell<T>> into a Weak<T>?

After adding a RefCell to the inside struct, I don't know how to have a reference to only the Rc value.
In other words, I'm creating an Rc<RefCell<T>> but I only need the Rc<T> to be able to downgrade into a Weak.
use std::{
cell::RefCell,
fmt,
rc::{Rc, Weak},
};
#[derive(Debug)]
struct Field {
i: u8,
y: u8,
}
impl Field {
pub fn new() -> Self {
Self { i: 8, y: 6 }
}
}
#[derive(Debug)]
pub struct Parent {
field_1: Field,
child: RefCell<Option<Child>>,
}
impl Parent {
pub fn new() -> Rc<RefCell<Self>> {
let n = Rc::new(RefCell::new(Self {
field_1: Field::new(),
child: RefCell::new(None),
}));
*n.borrow_mut().child.borrow_mut() = Some(Child::new(&n));
n
}
pub fn modify(&mut self) {
self.field_1.i = 9;
}
pub fn to_string(&self) -> String {
format!(
"{:?} {}",
self.field_1,
self.child.borrow().as_ref().unwrap()
)
}
}
#[derive(Debug)]
pub struct Child {
parent: Weak<Parent>,
field_2: Field,
}
impl Child {
pub fn new(parent: &Rc<Parent>) -> Self {
Self {
parent: Rc::downgrade(parent),
field_2: Field::new(),
}
}
}
impl fmt::Display for Child {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.parent.upgrade().unwrap().field_1.i == 1 {
write!(f, "set: {:?}", self.field_2)
} else {
write!(f, "not set {:?}", self.field_2)
}
}
}
fn main() {
let mut parent = Parent::new();
parent.borrow_mut().modify();
println!("{}", parent.borrow().to_string());
}
Error:
Compiling playground v0.0.1 (/playground)
error[E0308]: mismatched types
--> src/main.rs:32:62
|
32 | *n.borrow_mut().child.borrow_mut() = Some(Child::new(&n));
| ^^ expected struct `Parent`, found struct `std::cell::RefCell`
|
= note: expected reference `&std::rc::Rc<Parent>`
found reference `&std::rc::Rc<std::cell::RefCell<Parent>>`
I realize that the data structure itself might be the problem, but I currently can't think of a improvement.

Is this the right way to capture a string by value?

I'm making a functional builder that configures an object such as:
struct Person
{
name: String,
position: String
}
The builder itself keeps a list of boxed closures to be applied to the object when it needs to be constructed:
struct FunctionalBuilder<TSubject>
where TSubject : Default
{
actions: Vec<Box<dyn Fn(&mut TSubject) -> ()>>
}
impl<TSubject> FunctionalBuilder<TSubject>
where TSubject : Default
{
fn build(self) -> TSubject
{
let mut subj = TSubject::default();
for action in self.actions
{
(*action)(&mut subj);
}
subj
}
}
The idea being that one can aggregate this builder and then customize it for an object such as Person. Now, let's say I want to have a builder method called() that takes a name and saves the assignment of the name in the closure. I implement it as follows:
impl PersonBuilder
{
pub fn called(mut self, name: &str) -> PersonBuilder
{
let value = name.to_string();
self.builder.actions.push(Box::new(move |x| {
x.name = value.clone();
}));
self
}
}
Is this the right way of doing things? Is there a better way that avoids the temporary variable and clone() call?
Complete working example:
#[derive(Debug, Default)]
struct Person {
name: String,
position: String,
}
struct FunctionalBuilder<TSubject>
where
TSubject: Default,
{
actions: Vec<Box<dyn Fn(&mut TSubject) -> ()>>,
}
impl<TSubject> FunctionalBuilder<TSubject>
where
TSubject: Default,
{
fn build(self) -> TSubject {
let mut subj = TSubject::default();
for action in self.actions {
(*action)(&mut subj);
}
subj
}
fn new() -> FunctionalBuilder<TSubject> {
Self {
actions: Vec::new(),
}
}
}
struct PersonBuilder {
builder: FunctionalBuilder<Person>,
}
impl PersonBuilder {
pub fn new() -> Self {
PersonBuilder {
builder: FunctionalBuilder::<Person>::new(),
}
}
pub fn called(mut self, name: &str) -> PersonBuilder {
let value = name.to_string();
self.builder.actions.push(Box::new(move |x| {
x.name = value;
}));
self
}
pub fn build(self) -> Person {
self.builder.build()
}
}
pub fn main() {
let builder = PersonBuilder::new();
let me = builder.called("Dmitri").build();
println!("{:?}", me);
}
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=27eb6283836a478d5c68aa025aa4698d
You already do it, value is owned by your closure, the problem is that you require the Fn trait. This mean that action (the function) need to be able to be called many times. This mean value need to be cloned to keep it valid inside the closure. The closure can't give away its ownership.
One way would be to use FnOnce, which would make it possible to remove the clone, but this means that the builder can only be used once. To do this, use actions: Vec<Box<dyn FnOnce(&mut TSubject) -> ()>>, and action(&mut subj);.
More:
"cannot move a value of type FnOnce" when moving a boxed function
Fn* closure traits implemented for Box<dyn Fn*>

How do I properly insert into a Rust AVL Tree?

I'm very new to rust and I'm trying to creating an AVL Tree. I used Rc because I want every node to be owned by nodes above it and RefCell to have it mutable internally.
I've started to build the "insert" method, but it isn't inserting a new node in the correct place, rather its replace the "root" node with the new node and I'm having trouble understanding why. I believe that this may be an ownership issue but I'm not sure.
use std::cell::RefCell;
use std::cmp::Ordering;
use std::rc::Rc;
#[derive(Debug)]
pub struct BaseNode {
pub key: u32,
pub left: AvlTree,
pub right: AvlTree,
}
pub type AvlNode = Rc<RefCell<BaseNode>>;
pub type AvlTree = Option<AvlNode>;
impl BaseNode {
fn new(key: u32) -> Self {
Self {
key: key,
left: None,
right: None,
}
}
}
trait AvlNodeTrait {
fn new_node(key: u32) -> Self;
}
impl AvlNodeTrait for AvlNode {
fn new_node(key: u32) -> Self {
Rc::new(RefCell::new(BaseNode::new(key)))
}
}
pub trait AvlTreeTrait {
fn new() -> Self;
fn left(&self) -> Self;
fn right(&self) -> Self;
fn insert(&mut self, key: u32);
fn dupe(&self) -> Self;
fn set(&mut self, node: AvlNode);
}
impl AvlTreeTrait for AvlTree {
fn new() -> Self {
None
}
fn left(&self) -> Self {
if let Some(node) = self {
return node.borrow().right.dupe();
}
panic!("Trying to get Left of None!")
}
fn right(&self) -> Self {
if let Some(node) = self {
return node.borrow().right.dupe();
}
panic!("Trying to get right of None!")
}
fn dupe(&self) -> Self {
match self {
Some(node) => Some(Rc::clone(&node)),
None => None,
}
}
fn set(&mut self, node: AvlNode) {
*self = Some(Rc::clone(&node));
}
fn insert(&mut self, key: u32) {
let node = AvlNode::new_node(key);
let mut curr_tree = self;
let mut curr_key = 0;
while !curr_tree.is_none() {
if let Some(node) = &curr_tree {
curr_key = node.borrow().key;
if key > curr_key {
*curr_tree = curr_tree.left()
} else if key < curr_key {
*curr_tree = curr_tree.right()
} else {
return;
}
}
}
*curr_tree = Some(Rc::clone(&node));
}
}
fn main() {
let mut tree = AvlTree::new();
println!("{:?}", tree); // None
tree.insert(5);
println!("{:?}", tree); // Some(RefCell { value: BaseNode { key: 5, left: None, right: None } })
tree.insert(56);
println!("{:?}", tree); // Some(RefCell { value: BaseNode { key: 2, left: None, right: None } })
}
I would say the use of RefCell is quite unnecessary and potentially unsafe in this context. RefCell hands over the ownership/borrow checking to the runtime instead of doing them during compile time. This can lead to your program to panic in case it violates any of the borrowing rules.
I would prefer a "recursive" type looking something like this:
struct AVLTree<T> {
val: T,
left: Option<Box<AVLTree<T>>>,
right: Option<Box<AVLTree<T>>>
}
This will of course introduce some overhead due to memory allocation.

Collection with Traits that return Self

I'm trying to have a collection of objects that implement a particular trait.
If I use a trait that returns a value, this works
use std::collections::BTreeMap;
struct World {
entities: Vec<usize>,
database: BTreeMap<usize, Box<ReadValue>>,
//database : BTreeMap<usize,Box<ReadEcs>>, // Doesn't work
}
struct SourceInputGateway {
entity_id: usize,
}
trait ReadValue {
fn read(&self) -> f32;
}
impl ReadValue for SourceInputGateway {
fn read(&self) -> f32 {
0.0
}
}
But if I want to return Self as a value then this doesn't work, either as a method template param or associated type
trait ReadEcs {
type T;
fn read(&self) -> &Self::T;
}
impl ReadEcs for SourceInputGateway {
type T = SourceInputGateway;
fn read(&self) -> &Self::T {
self
}
}
What I would like to do is have a map of types that implement ReadEcs, the concrete type of which is not important.
Further clarification edit
If I expand the example by adding
// Different sized type
struct ComputeCalculator {
entity_id : usize,
name : String,
}
impl ReadValue for ComputeCalculator {
fn read(&self) -> f32 {
1230.0
}
}
then I can do this
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn read_write() {
let mut world = World::new();
world.database.insert(0,Box::new(SourceInputGateway{ entity_id : 1}));
world.database.insert(2,Box::new(ComputeCalculator{ entity_id : 2 , name : "foo".into() }));
for (k,ref v) in world.database {
let item : &Box<ReadValue> = v;
item.read();
}
}
}
but if I change or add a trait method that returns Self, I can't do this.
I'd like to understand a way to get around it without unsafe pointers.
I thought about this a little more and I think it's possible to solve this while retaining all the advantages of type safety and contiguous storage.
Defining a entity manager with pointers to storage
struct Entities {
entities: Vec<usize>,
containers: Vec<Box<Storage>>,
}
The components themselves that store data related to behaviour
struct Position {
entity_id: usize,
position: f32,
}
struct Velocity {
entity_id: usize,
velocity: f32,
}
We will have many instances of components, so we need a contiguous memory store, accessed by an index.
struct PositionStore {
storage: Vec<Position>,
}
struct VelocityStore {
storage: Vec<Velocity>,
}
trait Storage {
// Create and delete instances of the component
fn allocate(&mut self, entity_id: usize) -> usize;
// Interface methods that would correspond to a base class in C++
fn do_this(&self);
// fn do_that(&self);
}
The trait for the store implements an arena style storage plus the methods it would pass to to the components. This would likely be in the "System" part of an ECS but is left as an exercise for later.
I would like a hint as to how to pass a Fn() that constructs a custom object to the allocate() method. I've not figured that out yet.
impl Storage for PositionStore {
fn allocate(&mut self, entity_id: usize) -> usize {
self.storage.push(Position {
entity_id,
position: 0.0,
});
self.storage.len() - 1
}
fn run(&self) {
self.storage.iter().for_each(|item| { println!("{}",item.position); });
}
}
impl Storage for VelocityStore {
fn allocate(&mut self, entity_id: usize) -> usize {
self.storage.push(Velocity {
entity_id,
velocity: 0.0,
});
self.storage.len() - 1
}
fn do_this(&self) {
self.storage.iter().for_each(|item| { println!("{}",item.velocity); });
}
}
Some boiler plate.
impl Default for PositionStore {
fn default() -> PositionStore {
PositionStore {
storage: Vec::new(),
}
}
}
impl Default for VelocityStore {
fn default() -> VelocityStore {
VelocityStore {
storage: Vec::new(),
}
}
}
I think this could be thought about a little more. It stores the relationship between the storage of the components and their position
Instead of T::default(), you may want to pass a lambda function that has a specific initialisation for each of your components
impl Entities {
fn register<T>(&mut self) -> usize
where
T: Storage + Default + 'static,
{
self.containers.push(Box::new(T::default()));
self.containers.len() - 1
}
fn create<T>(&mut self, entity_id: usize, id: usize) -> usize {
self.containers[id].allocate(entity_id)
}
fn run_loop(&self) {
self.containers.iter().for_each(|x| x.do_this());
}
}
A test case to see if this works
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn arbitary() {
let mut entities = Entities {
entities: Vec::new(),
containers: Vec::new(),
};
let velocity_store_id = entities.register::<VelocityStore>();
let position_store_id = entities.register::<PositionStore>();
let _ = entities.create::<Velocity>(123, velocity_store_id);
let _ = entities.create::<Velocity>(234, velocity_store_id);
let _ = entities.create::<Position>(234, position_store_id);
let _ = entities.create::<Position>(567, position_store_id);
entities.run_loop();
}
}

Cannot move out of borrowed content and Builder pattern

I am just learning Rust. I am trying to create a builder struct for my Game struct. Here is the code:
struct Input {
keys_pressed: HashMap<VirtualKeyCode, bool>,
}
pub struct GameBuilder {
settings: GameSettings,
input: Input,
}
impl GameBuilder {
pub fn new() -> GameBuilder {
GameBuilder {
settings: GameSettings {
window_dimensions: (800, 600),
title: "".to_string(),
},
input: Input {
keys_pressed: HashMap::new(),
}
}
}
pub fn with_dimensions(&mut self, width: u32, height: u32) -> &mut GameBuilder {
self.settings.window_dimensions = (width, height);
self
}
pub fn with_title(&mut self, title: &str) -> &mut GameBuilder {
self.settings.title = title.to_string();
self
}
pub fn game_keys(&mut self, keys: Vec<VirtualKeyCode>) -> &mut GameBuilder {
for key in keys {
self.input.keys_pressed.insert(key, false);
}
self
}
pub fn build(&self) -> Game {
let (width, height) = self.settings.window_dimensions;
Game {
display: glutin::WindowBuilder::new()
.with_dimensions(width, height)
.with_title(self.settings.title.to_string())
.build_glium()
.ok()
.expect("Error in WindowBuilder"),
state: GameState::Running,
input: self.input,
}
}
}
But this code complains in the last line input: self.input with this:
error: cannot move out of borrowed content
I think I understand why. Since the argument passed in the function is &self, I cannot take ownership of it, and that what the last line is doing.
I thought that maybe changing &self to self would work, but then the compile argues that I cannot mutate self.
There is also the Copy trait from what I know, and that maybe should solve the problem. But Input is basically a HashMap, which means that a copy could be expensive if the hash itself is too big.
How would be a nice way of solving this problem?
Edit:
I tried doing this:
#[derive(Debug, Copy, Clone)]
struct Input {
keys_pressed: HashMap<VirtualKeyCode, bool>,
}
But the compiler complains:
error: the trait `Copy` may not be implemented for this type; field `keys_pressed` does not implement `Copy`
Given how your method signatures are formulated, you appear to be aiming for chaining:
let game = GameBuilder::new().with_dimensions(...)
.with_title(...)
.build();
In Rust, this requires that GameBuilder be passed by value:
pub fn with_dimensions(self, ...) -> GameBuilder {
// ...
}
And in order to be able to mutate self within the method, you need to make it mut:
pub fn with_dimensions(mut self, ...) -> GameBuilder {
}
If you change the signature of with_dimensions, with_title, game_keys and build to take self by value (mut self if mutation is intended), then chaining should work.
Try the builder pattern with Option and take()
Example:
#[derive(PartialEq, Debug)]
struct Game {
window: Window,
}
#[derive(PartialEq, Debug)]
struct Window {
title: String,
dimensions: (u32, u32),
}
struct GameBuilder {
window_title: Option<String>,
window_dimensions: Option<(u32, u32)>,
}
impl GameBuilder {
fn new() -> Self {
Self {
window_title: None,
window_dimensions: None,
}
}
fn window_title(&mut self, window_title: &str) -> &mut Self {
self.window_title = Some(window_title.to_owned());
self
}
fn window_dimensions(&mut self, width: u32, height: u32) -> &mut Self {
self.window_dimensions = Some((width, height));
self
}
fn build(&mut self) -> Result<Game, Box<dyn std::error::Error>> {
Ok(Game {
window: Window {
// `ok_or(&str)?` works, because From<&str> is implemented for Box<dyn Error>
title: self.window_title.take().ok_or("window_title is unset")?,
dimensions: self
.window_dimensions
.take()
.ok_or("window_dimensions are unset")?,
},
})
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test() {
let mut builder = GameBuilder::new();
builder.window_title("Awesome Builder");
builder.window_dimensions(800, 600);
let game = builder.build();
assert_eq!(
game.expect("build success"),
Game {
window: Window {
title: "Awesome Builder".into(),
dimensions: (800, 600)
}
}
);
}
#[test]
fn test_1() {
let game2 = GameBuilder::new()
.window_title("Busy Builder")
.window_dimensions(1234, 123)
.build();
assert_eq!(
game2.expect("build success"),
Game {
window: Window {
title: "Busy Builder".into(),
dimensions: (1234, 123),
}
}
)
}
}

Resources