我正在尝试构建一个解析器,该解析器可以从根目录(由用户传递)开始递归搜索文件系统,并解析其中的文件/目录。
我有一个Directory结构,其中包含对已解析对象的引用。解析的对象保存在HashMaps中,而HashMaps是State结构的一部分。
pub struct Directory<'a> {
pub pathname: String,
pub child_dirs: Vec<&'a Directory<'a>>,
pub child_files: Vec<&'a File>,
pub child_templates: Vec<&'a Template>,
}
我有一个app_state结构,它保存所有哈希映射,例如这样(为简洁起见,省略了一些哈希映射:]
pub struct State<'a> {
pub directory_hash: HashMap<OsString, Directory<'a>>,
pub file_hash: HashMap<PathBuf, File>,
pub template_hash: HashMap<PathBuf, Template>,
}
Parser::parse
签名如下:
pub fn parse<'a>(root: &'a PathBuf, app_state: &'a mut app_state::State<'a>)
。
调用Parser :: parse时,将为根目录传递&PathBuf。将用两种可能性查看根目录中的每个条目:
该条目是一个目录:===> 1)创建一个新的目录对象。 2)将目录对象保存到正确的directory_hash
中。 3)通过再次调用Parser::parse
并将其作为根目录来解析目录,并传递我们当前正在使用的app_state。
该条目是某种类型的文件:===> 1)将文件解析为正确类型的对象。 2)将文件保存到app_state上正确的哈希图中。 3)将对它的引用保存到当前目录对象的Vector中。
问题:因为深度大于1的任何东西都会被递归调用,所以我无法再次将app_state可变地传递给Parser::parse
方法。
cannot borrow `*app_state` as mutable more than once at a time
mutable borrow starts here in previous iteration of looprustc(E0499)
我最受困扰的地方:仅当我尝试将REFERENCES存储在Directory结构上的向量中时,才会发生这种情况。如果我要存储这些对象的实际实例,则此递归调用不会出错。但是我想将所有内容存储在主对象app_state
中,并且仅从其他位置引用其余内容。
这是我的Parser::parse
代码如下:
pub fn parse<'a>(root: &'a PathBuf, app_state: &'a mut app_state::State<'a>) {
// Create a new directory object from the root
let root_dir = Directory::new(root);
// insert it into the directory hash
let hash_key = root.clone().into_os_string();
app_state.directory_hash.insert(hash_key, root_dir);
// recurse over all entries in the directory
let readable_dir = fs::read_dir(root);
let readable_dir = match readable_dir {
Ok(dir) => dir,
Err(_e) => return, // handle errors that could occur
};
for item in readable_dir {
let fpath = match item {
Ok(file_path) => file_path,
_ => continue, // handle errors that could occur
};
// if they are a directory, parse that directory
if fpath.path().is_dir() {
Self::parse(&fpath.path(), app_state);
} else {
// if not a directory, parse them according to their type
let file_type = get_file_type(&fpath.path());
Self::update_state(file_type, &fpath, app_state);
}
}
}
有人可以帮我解决这个问题吗?我尝试了编译器给出的建议,即增加了一些生存时间,这些生存时间在我所理解的更简单的情况下是可以的,但是在这里,我要么遇到“寿命不足”,要么“不能多次多变地借用”错误。
有人可以阐明正在发生的事情,以便我更好地理解吗?
此方法本质上是内存不安全的:例如,随着directory_hash
的增长,在某些时候它的哈希表将使用Directory
条目的不同物理位置重建,这将在child_dirs
中留下悬挂的引用条目。 Rust不允许这样做,因此无法通过添加/修改生命周期注释来解决此问题。相反,需要一种不同的数据结构方式。