boseiju/ability_tree/card_layout/
token_layout.rs

1use crate::ability_tree::AbilityTreeNode;
2use crate::ability_tree::MAX_CHILDREN_PER_NODE;
3
4/// Layout of a token
5#[derive(Debug, Clone, PartialEq, Eq)]
6#[derive(serde::Serialize, serde::Deserialize)]
7pub struct TokenLayout {
8    pub name: String,
9    pub card_type: crate::ability_tree::type_line::TypeLine,
10    pub colors: crate::ability_tree::colors::Colors,
11    pub abilities: crate::AbilityTree,
12    #[cfg(feature = "spanned_tree")]
13    pub span: crate::ability_tree::span::TreeSpan,
14}
15
16impl AbilityTreeNode for TokenLayout {
17    fn node_id(&self) -> usize {
18        use idris::Idris;
19        crate::ability_tree::NodeKind::TokenLayout.id()
20    }
21
22    fn children(&self) -> arrayvec::ArrayVec<&dyn AbilityTreeNode, MAX_CHILDREN_PER_NODE> {
23        let mut children = arrayvec::ArrayVec::new_const();
24        children.push(&self.card_type as &dyn AbilityTreeNode);
25        children.push(&self.colors as &dyn AbilityTreeNode);
26        children.push(&self.abilities as &dyn AbilityTreeNode);
27        children
28    }
29
30    fn display(&self, out: &mut crate::utils::TreeFormatter<'_>) -> std::io::Result<()> {
31        use std::io::Write;
32        write!(out, "token:")?;
33        out.push_inter_branch()?;
34        write!(out, "types:")?;
35        out.push_final_branch()?;
36        self.card_type.display(out)?;
37        out.pop_branch();
38        out.next_inter_branch()?;
39        write!(out, "color:")?;
40        out.push_final_branch()?;
41        self.colors.display(out)?;
42        out.pop_branch();
43        out.next_final_branch()?;
44        write!(out, "abilities:")?;
45        out.push_final_branch()?;
46        self.abilities.display(out)?;
47        out.pop_branch();
48        out.pop_branch();
49        Ok(())
50    }
51
52    fn node_tag(&self) -> &'static str {
53        "token description"
54    }
55
56    #[cfg(feature = "spanned_tree")]
57    fn node_span(&self) -> crate::ability_tree::span::TreeSpan {
58        self.span
59    }
60}
61
62impl super::LayoutImpl for TokenLayout {
63    fn card_types(&self) -> arrayvec::ArrayVec<mtg_data::CardType, 4> {
64        self.card_type.card_types()
65    }
66
67    fn mana_value(&self) -> usize {
68        0
69    }
70
71    #[cfg(feature = "parser")]
72    fn from_raw_card(raw_card: &mtg_cardbase::Card) -> Result<Self, String> {
73        use crate::lexer::IntoToken;
74
75        let type_line_span = crate::lexer::Span {
76            start: 0,
77            length: raw_card.type_line.len(),
78            text: raw_card.type_line.as_str(),
79        };
80
81        Ok(TokenLayout {
82            name: raw_card.name.clone(),
83            card_type: crate::ability_tree::type_line::TypeLine::try_from_span(&type_line_span)
84                .ok_or_else(|| format!("Failed to parse card type: {}", raw_card.type_line))?,
85            colors: crate::ability_tree::colors::Colors::try_from(raw_card.color_identity.as_slice())?,
86            abilities: match raw_card.oracle_text.as_ref() {
87                Some(oracle_text) => crate::AbilityTree::from_oracle_text(oracle_text, &raw_card.name)
88                    .map_err(|e| format!("Failed to parse oracle text to ability tree: {e}"))?,
89                None => crate::AbilityTree::empty(),
90            },
91            #[cfg(feature = "spanned_tree")]
92            span: Default::default(),
93        })
94    }
95
96    fn layout_debug_display<W: std::io::Write>(&self, _output: &mut W) -> std::io::Result<()> {
97        unimplemented!()
98    }
99}
100
101#[cfg(feature = "parser")]
102impl crate::utils::DummyInit for TokenLayout {
103    fn dummy_init() -> Self {
104        Self {
105            name: String::with_capacity(0),
106            card_type: crate::utils::dummy(),
107            abilities: crate::utils::dummy(),
108            colors: crate::utils::dummy(),
109            #[cfg(feature = "spanned_tree")]
110            span: Default::default(),
111        }
112    }
113}