代表相同类型实例之间的父子关系的良好做法是什么?

时间:2019-02-04 13:25:14

标签: rust smart-pointers borrowing

我正在解析文件,每一行都转换为Data结构。当行缩进时,其Data表示形式将被视为前一个行的Data表示形式的子代,缩进单元少一个。

我目前拥有的结构是将孩子直接存储在Vec中的结构(每个孩子都是为此目的而克隆的),该结构可以工作,但是效率很低并且不适合我将来的需求。

我需要的是一种访问父级和子级的方法(例如通过childrenparent方法),有没有一种无需克隆即可实现的方法? 我当前的代码将被彻底重构,因此我可以接受任何建议。

另外,对于给定类型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,
}

0 个答案:

没有答案