boseiju/ability_tree/object/
object_kind.rs

1mod artifact_subtype;
2mod battle_subtype;
3mod card;
4mod card_type;
5mod creature_subtype;
6mod enchantment_subtype;
7mod instant_sorcery_subtype;
8mod land_subtype;
9mod permanent;
10mod planeswalker_subtype;
11mod spell;
12mod supertype;
13
14pub use artifact_subtype::ArtifactSubtype;
15pub use battle_subtype::BattleSubtype;
16pub use card::CardObjectKind;
17pub use card_type::CardType;
18pub use creature_subtype::CreatureSubtype;
19pub use enchantment_subtype::EnchantmentSubtype;
20pub use instant_sorcery_subtype::SpellSubtype;
21pub use land_subtype::LandSubtype;
22pub use permanent::PermanentObjectKind;
23pub use planeswalker_subtype::PlaneswalkerSubtype;
24pub use spell::SpellObjectKind;
25pub use supertype::Supertype;
26
27use crate::ability_tree::AbilityTreeNode;
28use crate::ability_tree::MAX_CHILDREN_PER_NODE;
29
30/// An object kind wraps up most of the supertypes, types and subtypes,
31/// as well as some grouping types, such as spell, card and permanent.
32///
33/// It is mostly made to be an object specifier (e.g. "destroy target creature /
34/// enchantment / permanent").
35#[derive(idris_derive::Idris)]
36#[derive(serde::Serialize, serde::Deserialize)]
37#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
38pub enum ObjectKind {
39    ArtifactSubtype(ArtifactSubtype),
40    BattleSubtype(BattleSubtype),
41    Card(CardObjectKind),
42    CardType(CardType),
43    CreatureSubtype(CreatureSubtype),
44    EnchantmentSubtype(EnchantmentSubtype),
45    InstantSorcerySubtype(SpellSubtype),
46    LandSubtype(LandSubtype),
47    Permanent(PermanentObjectKind),
48    PlaneswalkerSubtype(PlaneswalkerSubtype),
49    Spell(SpellObjectKind),
50    Supertype(Supertype),
51}
52
53impl ObjectKind {
54    pub fn all() -> impl Iterator<Item = Self> {
55        std::iter::empty()
56            .chain(ArtifactSubtype::all().map(Self::ArtifactSubtype))
57            .chain(BattleSubtype::all().map(Self::BattleSubtype))
58            .chain(CardObjectKind::all().map(Self::Card))
59            .chain(CardType::all().map(Self::CardType))
60            .chain(CreatureSubtype::all().map(Self::CreatureSubtype))
61            .chain(EnchantmentSubtype::all().map(Self::EnchantmentSubtype))
62            .chain(SpellSubtype::all().map(Self::InstantSorcerySubtype))
63            .chain(LandSubtype::all().map(Self::LandSubtype))
64            .chain(PermanentObjectKind::all().map(Self::Permanent))
65            .chain(PlaneswalkerSubtype::all().map(Self::PlaneswalkerSubtype))
66            .chain(SpellObjectKind::all().map(Self::Spell))
67            .chain(Supertype::all().map(Self::Supertype))
68    }
69}
70
71impl AbilityTreeNode for ObjectKind {
72    fn node_id(&self) -> usize {
73        use crate::ability_tree::tree_node::MtgDataNodeKind;
74        use idris::Idris;
75
76        crate::ability_tree::NodeKind::MtgData(MtgDataNodeKind::ObjectKindIdMarker).id()
77    }
78
79    fn children(&self) -> arrayvec::ArrayVec<&dyn AbilityTreeNode, MAX_CHILDREN_PER_NODE> {
80        let mut children = arrayvec::ArrayVec::new_const();
81        match self {
82            Self::ArtifactSubtype(child) => children.push(child as &dyn AbilityTreeNode),
83            Self::BattleSubtype(child) => children.push(child as &dyn AbilityTreeNode),
84            Self::Card(child) => children.push(child as &dyn AbilityTreeNode),
85            Self::CardType(child) => children.push(child as &dyn AbilityTreeNode),
86            Self::CreatureSubtype(child) => children.push(child as &dyn AbilityTreeNode),
87            Self::EnchantmentSubtype(child) => children.push(child as &dyn AbilityTreeNode),
88            Self::InstantSorcerySubtype(child) => children.push(child as &dyn AbilityTreeNode),
89            Self::LandSubtype(child) => children.push(child as &dyn AbilityTreeNode),
90            Self::Permanent(child) => children.push(child as &dyn AbilityTreeNode),
91            Self::PlaneswalkerSubtype(child) => children.push(child as &dyn AbilityTreeNode),
92            Self::Spell(child) => children.push(child as &dyn AbilityTreeNode),
93            Self::Supertype(child) => children.push(child as &dyn AbilityTreeNode),
94        }
95        children
96    }
97
98    fn display(&self, out: &mut crate::utils::TreeFormatter<'_>) -> std::io::Result<()> {
99        use std::io::Write;
100        write!(out, "object kind")?;
101        out.push_final_branch()?;
102        match self {
103            Self::ArtifactSubtype(child) => child.display(out)?,
104            Self::BattleSubtype(child) => child.display(out)?,
105            Self::Card(child) => child.display(out)?,
106            Self::CardType(child) => child.display(out)?,
107            Self::CreatureSubtype(child) => child.display(out)?,
108            Self::EnchantmentSubtype(child) => child.display(out)?,
109            Self::InstantSorcerySubtype(child) => child.display(out)?,
110            Self::LandSubtype(child) => child.display(out)?,
111            Self::Permanent(child) => child.display(out)?,
112            Self::PlaneswalkerSubtype(child) => child.display(out)?,
113            Self::Spell(child) => child.display(out)?,
114            Self::Supertype(child) => child.display(out)?,
115        }
116        out.pop_branch();
117        Ok(())
118    }
119
120    fn node_tag(&self) -> &'static str {
121        "object kind"
122    }
123
124    #[cfg(feature = "spanned_tree")]
125    fn node_span(&self) -> crate::ability_tree::span::TreeSpan {
126        match self {
127            Self::ArtifactSubtype(child) => child.node_span(),
128            Self::BattleSubtype(child) => child.node_span(),
129            Self::Card(child) => child.node_span(),
130            Self::CardType(child) => child.node_span(),
131            Self::CreatureSubtype(child) => child.node_span(),
132            Self::EnchantmentSubtype(child) => child.node_span(),
133            Self::InstantSorcerySubtype(child) => child.node_span(),
134            Self::LandSubtype(child) => child.node_span(),
135            Self::Permanent(child) => child.node_span(),
136            Self::PlaneswalkerSubtype(child) => child.node_span(),
137            Self::Spell(child) => child.node_span(),
138            Self::Supertype(child) => child.node_span(),
139        }
140    }
141}
142
143#[cfg(feature = "lexer")]
144impl crate::lexer::IntoToken for ObjectKind {
145    fn try_from_span(span: &crate::lexer::Span) -> Option<Self> {
146        if let Some(result) = ArtifactSubtype::try_from_span(span) {
147            Some(Self::ArtifactSubtype(result))
148        } else if let Some(result) = BattleSubtype::try_from_span(span) {
149            Some(Self::BattleSubtype(result))
150        } else if let Some(result) = CardObjectKind::try_from_span(span) {
151            Some(Self::Card(result))
152        } else if let Some(result) = CardType::try_from_span(span) {
153            Some(Self::CardType(result))
154        } else if let Some(result) = CreatureSubtype::try_from_span(span) {
155            Some(Self::CreatureSubtype(result))
156        } else if let Some(result) = EnchantmentSubtype::try_from_span(span) {
157            Some(Self::EnchantmentSubtype(result))
158        } else if let Some(result) = SpellSubtype::try_from_span(span) {
159            Some(Self::InstantSorcerySubtype(result))
160        } else if let Some(result) = LandSubtype::try_from_span(span) {
161            Some(Self::LandSubtype(result))
162        } else if let Some(result) = PermanentObjectKind::try_from_span(span) {
163            Some(Self::Permanent(result))
164        } else if let Some(result) = PlaneswalkerSubtype::try_from_span(span) {
165            Some(Self::PlaneswalkerSubtype(result))
166        } else if let Some(result) = SpellObjectKind::try_from_span(span) {
167            Some(Self::Spell(result))
168        } else if let Some(result) = Supertype::try_from_span(span) {
169            Some(Self::Supertype(result))
170        } else {
171            None
172        }
173    }
174}
175
176#[cfg(feature = "parser")]
177impl crate::utils::DummyInit for ObjectKind {
178    fn dummy_init() -> Self {
179        Self::Card(crate::utils::dummy())
180    }
181}