Reputation: 47
I'm having trouble figuring out how to mutate nested structs. I have a Folder
struct that can hold File
s and other Folder
s inside it. I then want to be able to add new files and folders to those nested folders after creating them, but I keep running into errors.
Code:
type SubFolder = Vec<Box<Folder>>;
type Files = Vec<String>;
#[derive(Debug)]
struct Folder {
files: Files,
sub_folder: SubFolder
}
impl Folder {
pub fn new() -> Self {
Self {
files: Vec::new(),
sub_folder: Vec::new(),
}
}
pub fn add_file(&mut self, file: String) {
self.files.push(file);
}
pub fn add_folder(&mut self, dir: Box<Folder>) {
self.sub_folder.push(dir);
}
}
fn main() {
let mut folder_1 = Folder::new();
let mut folder_2 = Folder::new();
folder_1.add_folder(Box::new(folder_2));
folder_2.add_file(String::from("b.txt")); // Error
}
Error Message:
error[E0382]: borrow of moved value: `folder_2`
--> src/main.rs:32:5
|
29 | let mut folder_2 = Folder::new();
| ------------ move occurs because `folder_2` has type `Folder`, which does not implement the `Copy` trait
30 |
31 | folder_1.add_folder(Box::new(folder_2));
| -------- value moved here
32 | folder_2.add_file(String::from("b.txt")); // Error
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ value borrowed here after move
Is it even possible to do this? Or do I need to use unsafe code? Any resources or suggestions would be appreciated.
Upvotes: 1
Views: 791
Reputation: 1584
for your methods add_folder
and add_file
you need mut reference to self. However after folder2 has been moved you can not reference it anymore.
There are a few ways to address it.
Like so:
type SubFolder = Vec<Box<Folder>>;
type Files = Vec<String>;
#[derive(Debug)]
struct Folder {
files: Files,
sub_folder: SubFolder
}
impl Folder {
pub fn new() -> Self {
Self {
files: Vec::new(),
sub_folder: Vec::new(),
}
}
pub fn add_file(&mut self, file: String) {
self.files.push(file);
}
pub fn add_folder(&mut self, dir: Box<Folder>) {
self.sub_folder.push(dir);
}
}
fn main() {
let mut folder_1 = Folder::new();
let mut folder_2 = Folder::new();
folder_1.add_folder(Box::new(folder_2));
folder_1.sub_folder[0].add_file(String::from("b.txt")); // Ok
}
E.g.:
use std::cell::RefCell;
use std::rc::Rc;
type SubFolder = Vec<Rc<RefCell<Folder>>>;
type Files = Vec<String>;
#[derive(Debug)]
struct Folder {
files: Files,
sub_folder: SubFolder
}
impl Folder {
pub fn new() -> Self {
Self {
files: Vec::new(),
sub_folder: Vec::new()
}
}
pub fn add_file(&mut self, file: String) {
self.files.push(file);
}
pub fn add_folder(&mut self, dir: Rc<RefCell<Folder>>) {
self.sub_folder.push(dir);
}
}
fn main() {
let mut folder_1 = Folder::new();
let mut folder_2 = Rc::new((RefCell::new(Folder::new())));
folder_1.add_folder(Rc::clone(folder_2));
folder_2.borrow_mut().add_file(String::from("b.txt")); // Ok
}
Btw, with Vec you can not address subfolder or file by name. Maybe better use Hashmap?
Upvotes: 1