我正在解析文件,每一行都转换为Data
结构。当行缩进时,其Data
表示形式将被视为前一个行的Data
表示形式的子代,缩进单元少一个。
我目前拥有的结构是将孩子直接存储在Vec
中的结构(每个孩子都是为此目的而克隆的),该结构可以工作,但是效率很低并且不适合我将来的需求。
我需要的是一种访问父级和子级的方法(例如通过children
和parent
方法),有没有一种无需克隆即可实现的方法?
我当前的代码将被彻底重构,因此我可以接受任何建议。
另外,对于给定类型struct A {b: &B}
,是否可以从B实例中检索借用它的A实例? (如果需要单独回答,请告诉我。)
这里是添加孩子的Data
方法:
pub fn add_sub(&mut self, d: &Self) {
self.subs.push(d.clone());
}
这是Data
的定义:
#[derive(Clone)]
pub struct Data {
pub(crate) nesting: usize,
pub token: Token,
pub content: String,
pub subs: Vec<Data>,
}
首先将初始输入文件解析为Vec<Data>
,缩进信息存储在nesting
字段中。然后将vec传递到此结构,它将解决父子关系:
struct DataBuilder(Vec<Data>);
impl DataBuilder {
// The entry point, takes an initial vec of Datas and produces another vec with each 'subs' vec filled
fn resolve(ds: Vec<Data>) -> Vec<Data> {
let c = Self(ds);
// This is the output vec
let mut datas = vec![];
for (i, d) in (&c.0).iter().enumerate() {
match c.outcome(i, None) {
Outcome::End | Outcome::Simple => {
datas.push(d.clone());
}
Outcome::Complex => {
datas.push(c.gather(d.clone(), i));
}
_ => (),
}
}
datas
}
// Takes a parent and its vec position and adds subsequent Datas of inferior nesting values
fn gather(&self, mut p: Data, at: usize) -> Data {
for (i, d) in (&self.0).iter().skip(at + 1).enumerate() {
match self.outcome(at + i + 1, Some(p.nesting)) {
Outcome::Out => {
break;
}
Outcome::Sub => {
p.add_sub(d);
}
_ => (),
}
}
p
}
// See the enum below
fn outcome(&self, i: usize, p: Option<usize>) -> Outcome {
if p.is_some() && self.nesting(i) <= p.unwrap() {
Outcome::Out
} else if p.is_some() && self.nesting(i) == p.unwrap() + 1 {
Outcome::Sub
} else if i == self.0.len() - 1 {
Outcome::End
} else if self.nesting(i + 1) == self.nesting(i) + 1 {
Outcome::Complex
} else {
Outcome::Simple
}
}
// Quicker access of the nesting value of a Data
fn nesting(&self, at: usize) -> usize {
self.0[at].nesting
}
}
enum Outcome {
// If the Data have no child
Simple,
// If the Data have children
Complex,
// If the Data is a child of current parent (see gather method)
Sub,
// If the Data is not a child of current parent (see gather method)
Out,
// If the Data is the last
End,
}