1

Sample code :

use serde_json::{json, Value};

fn main() {
  let a: Rc<RefCell<Value>> = Rc::new(RefCell::new(json!({"a": "value"})));
  let v: Rc<RefCell<Vec<Value>>> = Rc::new(RefCell::new(vec![]));

  // How to push a into v, but keep `a` and `v` for future uses
}

I want to push Value a into vector v (link pointer), but still be able to use a later on.

I've tried the following:

1.

v.borrow_mut().push(*a.borrow_mut());

This does not work, as Value does not implement Copy trait, thus could not be dereferenced

2.

v.borrow_mut().push(RefCell::take(&a));

This works, however a has now lost the contents. I do understand that there should only be one owner, but I'm not sure how to achieve what I need.

The Why

I have a Value which I need to modify depending on some other data which is in a tree structure. I want to recursively walk through that other data tree, and pass along this Value to be modified.

In my function, I have this Value signature as Rc<RefCell<Value>>, and depending on the case I sometimes need to add nested properties, so I may need to add a property containing a vector with a new json!({}), and pass it as a new Rc<RefCell<Value>> to sub-iterations to append data to this specific subtree.

So, if you have any advice - maybe I need to change the recursive function's signature to have this data as Rc<RefCell<&Value>> instead, to have only one owner ? That seems like an awful lot of all sorts of references stacked upon one another, not sure which is the good way

Edit1: Updated sample to include Rc<RefCell<_>>

Herohtar
  • 5,347
  • 4
  • 31
  • 41
Raywell
  • 169
  • 1
  • 8
  • You can't copy `refCell` objects, consider wrapping them in a `Rc` or `Arc` which can be copied. A `Rc>` is a sharable clonable mutable reference. – mousetail Oct 20 '22 at 06:46
  • I see, the sample code is imprecise. Say both a and v are Rc> (which actually corresponds to my usecase) – Raywell Oct 20 '22 at 06:48
  • You can `.clone()` a `Rc`, so you can use that to store multiple copies – mousetail Oct 20 '22 at 06:48
  • From what I understand, `clone()` allows indeed use the same RefCell multiple times, however if I do `RefCell::take(&a)`, all of the copies will point to a RefCell which will henceforth contain only the default value (data is lost), right ? – Raywell Oct 20 '22 at 06:54
  • You don't ever need to do that though since `RefCell` implements `Deref` – mousetail Oct 20 '22 at 07:01
  • `Deref` only works with types implementing `Copy` trait, which is not the case here with `serde_json::value::Value` type. I wouldn't want to copy all the contents though. I'm more and more thinking that I might need `Rc>` instead of `Rc>`, would you agree? – Raywell Oct 20 '22 at 07:09
  • 1
    Good thing `RefCell` implements `DerefMut` so also works for classes that don't implemenet copy. `RefCell<&T>` would make the type immutable and create some very hard to guarentee lifetime bounds. – mousetail Oct 20 '22 at 07:10
  • Oooh thats the answer !! `v.borrow_mut().push(a.borrow_mut().deref_mut().to_owned());` Works !! Thanks a lot ! You can post it as the answer that I'll accept, if you want karma :) – Raywell Oct 20 '22 at 07:14

0 Answers0