boseiju/ability_tree/
root.rs

1use crate::ability_tree::*;
2
3/// One or more abilities.
4///
5/// This is the root of the Magic: the Gathering texts,
6/// and can represent on its own the full text box of a card.
7#[derive(serde::Serialize, serde::Deserialize)]
8#[derive(Debug, Clone, PartialEq, Eq)]
9pub struct AbilityTree {
10    pub abilities: crate::utils::HeapArrayVec<ability::AbilityKind, MAX_CHILDREN_PER_NODE>,
11    #[cfg(feature = "spanned_tree")]
12    pub span: crate::ability_tree::span::TreeSpan,
13}
14
15impl AbilityTree {
16    pub fn empty() -> AbilityTree {
17        AbilityTree {
18            abilities: crate::utils::HeapArrayVec::new(),
19            #[cfg(feature = "spanned_tree")]
20            span: Default::default(),
21        }
22    }
23
24    pub fn display_from_root<W: std::io::Write>(&self, output: &mut W, prefix: &str) -> std::io::Result<()> {
25        let mut tree_formatter = crate::utils::TreeFormatter::new(output, 64, prefix);
26        self.display(&mut tree_formatter)
27    }
28
29    #[cfg(feature = "parser")]
30    pub fn from_oracle_text(oracle_text: &str, card_name: &str) -> Result<AbilityTree, crate::error::BoseijuError> {
31        let preprocessed = crate::lexer::preprocess(card_name, oracle_text);
32        let tokens = crate::lexer::lex(&preprocessed)?;
33        let result = crate::parser::parse(&tokens)?;
34        Ok(result)
35    }
36}
37
38impl crate::ability_tree::AbilityTreeNode for AbilityTree {
39    fn node_id(&self) -> usize {
40        use idris::Idris;
41        crate::ability_tree::NodeKind::AbilityTree.id()
42    }
43
44    fn children(&self) -> arrayvec::ArrayVec<&dyn AbilityTreeNode, MAX_CHILDREN_PER_NODE> {
45        let mut children = arrayvec::ArrayVec::new_const();
46        for child in self.abilities.iter() {
47            children.push(child as &dyn AbilityTreeNode);
48        }
49        children
50    }
51
52    fn display(&self, out: &mut crate::utils::TreeFormatter<'_>) -> std::io::Result<()> {
53        use std::io::Write;
54        write!(out, "ability tree:")?;
55        for ability in self.abilities.iter().take(self.abilities.len().saturating_sub(1)) {
56            out.push_inter_branch()?;
57            ability.display(out)?;
58            out.pop_branch();
59        }
60        if let Some(ability) = self.abilities.last() {
61            out.push_final_branch()?;
62            ability.display(out)?;
63            out.pop_branch();
64        }
65        Ok(())
66    }
67
68    fn node_tag(&self) -> &'static str {
69        "ability tree"
70    }
71
72    #[cfg(feature = "spanned_tree")]
73    fn node_span(&self) -> crate::ability_tree::span::TreeSpan {
74        self.span
75    }
76}
77
78impl Default for AbilityTree {
79    fn default() -> Self {
80        Self::empty()
81    }
82}
83
84#[cfg(feature = "parser")]
85impl crate::utils::DummyInit for AbilityTree {
86    fn dummy_init() -> Self {
87        Self {
88            abilities: crate::utils::dummy(),
89            #[cfg(feature = "spanned_tree")]
90            span: Default::default(),
91        }
92    }
93}