I have a struct A in Rust that has 3 fields, a
, b
and c
struct A {
pub a: typeA,
pub b: typeB,
pub c: typeC
};
typeA
, typeB
and typeC
are three different types of structs themselves. typeB
and
typeC
have typeA
as depdendency. Like for example
struct typeB {
pub bb: typeA,
};
struct typeC {
pub cc: typeA,
};
And typeA
is defined below as follows:
struct typeA {
pub aa: String,
};
I can instantiate A
like this:
let instance_a = A {
a1 : typeA {aa: "a".to_string()},
b1 : typeB {bb: typeA {aa: "a".to_string()}},
c1 : typeC {cc: typeA {aa: "a".to_string()}},
};
As you can see b1
and c1
both depend on a1
here.
My question is, is there a cleaner way to make the field b1
depend on a1
directly at compile time without me having to
declare them separately in each case for b1
and c1
as shown in instance_a
?
The long term goal is to automatically update b1
and c1
as
a1
gets modified. In other words, if I want to decide to
update the value of a1
to this
a1: typeA {aa : "b".to_string()}
then b1
and c1
should automatically get updated.
I have tried approaching this problem in the following manner.
I have deduced typeA
, typeB
and typeC
as cloneable.
impl A {
pub fn create(a: &str) -> Self {
let old_instance = typeA {aa : a.to_string()};
A {
a1: old_instance.clone(),
b1: typeB {bb: old_instance.clone()},
c1: typeC {cc: old_instance.clone()},
}
}
}
So whenever I want to update whatever is happening within A
,
I just call A::create("hello_world")
. The issue with this is
I am having to clone multiple times which I would like to avoid.
CodePudding user response:
Since you want to automatically update b and c when a is modified then you either want to hold references to a or you want to have mutual ownership with Arc. Arc is read only so if you want to modify stuff you need to do it with interior mutability. There are a few ways to do all that. Here is one (if you don't need mutiple threads replace Arc with Rc)
use std::cell::RefCell;
use std::sync::Arc;
#[derive(Debug)]
struct A {
pub a: Arc<typeA>,
pub b: typeB,
pub c: typeC
}
#[derive(Debug)]
struct typeB {
pub bb: Arc<typeA>
}
#[derive(Debug)]
struct typeC {
pub cc: Arc<typeA>
}
#[derive(Debug)]
struct typeA {
pub aa: RefCell<String>
}
fn main() {
let mut aa = Arc::new(typeA { aa: RefCell::new(String::from("test1")) });
let instance_a = A {
a : aa.clone(),
b : typeB {bb: aa.clone()},
c : typeC {cc: aa.clone()},
};
println!("{:?}", instance_a);
// modify aa
*aa.aa.borrow_mut() = String::from("test2");
println!("{:?}", instance_a);
}
Output:
A { a: typeA { aa: RefCell { value: "test1" } }, b: typeB { bb: typeA { aa: RefCell { value: "test1" } } }, c: typeC { cc: typeA { aa: RefCell { value: "test1" } } } }
A { a: typeA { aa: RefCell { value: "test2" } }, b: typeB { bb: typeA { aa: RefCell { value: "test2" } } }, c: typeC { cc: typeA { aa: RefCell { value: "test2" } } } }