Skip to main content

infinite_fusion/
types.rs

1use crate::as_transparent;
2use indexmap::IndexMap;
3use reikland::Ignored;
4use serde::{Deserialize, Deserializer, Serialize};
5
6#[derive(Debug, Clone, Deserialize, Serialize)]
7#[cfg_attr(test, serde(deny_unknown_fields))]
8pub struct Type {
9    #[serde(rename = "@id", deserialize_with = "as_transparent")]
10    pub id: String,
11    #[serde(rename = "@id_number")]
12    pub id_number: u8, // max as of writing is 27
13    #[serde(rename = "@real_name", deserialize_with = "as_transparent")]
14    pub real_name: String,
15    #[serde(rename = "@pseudo_type")]
16    pub pseudo_type: bool,
17    #[serde(rename = "@special_type")]
18    pub special_type: bool,
19    #[serde(rename = "@weaknesses")]
20    pub weaknesses: Vec<String>,
21    #[serde(rename = "@resistances")]
22    pub resistances: Vec<String>,
23    #[serde(rename = "@immunities")]
24    pub immunities: Vec<String>,
25}
26
27/// [`Deserialize`] implementation for `types.dat`
28#[derive(Debug, Clone, Serialize)]
29pub struct TypeDex(pub Vec<Type>);
30
31impl<'de> serde::Deserialize<'de> for TypeDex {
32    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
33    where
34        D: Deserializer<'de>,
35    {
36        reikland::DualKeyVec::<(Type, Ignored)>::deserialize(deserializer)
37            .map(|reikland::DualKeyVec(mut d)| {
38                d.sort_by_key(|(t, _)| t.id_number);
39                d.into_iter().map(|(t, _)| t).collect()
40            })
41            .map(TypeDex)
42    }
43}
44
45/// [`Deserialize`] implementation for `types.dat`, indexable by key or value
46#[derive(Debug, Clone, Serialize)]
47pub struct TypeMap(pub IndexMap<String, Type>);
48
49impl<'de> serde::Deserialize<'de> for TypeMap {
50    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
51    where
52        D: Deserializer<'de>,
53    {
54        TypeDex::deserialize(deserializer)
55            .map(|TypeDex(v)| TypeMap(v.into_iter().map(|t| (t.id.clone(), t)).collect()))
56    }
57}
58
59pub(crate) fn fuse_types<'a>(
60    head_1: &'a String,
61    head_2: Option<&'a String>,
62    body_1: &'a String,
63    body_2: Option<&'a String>,
64) -> (&'a String, Option<&'a String>) {
65    let type_1 = if let Some(secondary) = head_2
66        && is_normal_flying(head_1, head_2)
67    {
68        secondary
69    } else {
70        head_1
71    };
72
73    let type_2 = match body_2 {
74        None if body_1 == type_1 => None,
75        None => Some(body_1),
76        Some(secondary) if secondary == type_1 => Some(body_1),
77        Some(secondary) => Some(secondary),
78    };
79    (type_1, type_2)
80}
81
82fn is_normal_flying(head_1: &String, head_2: Option<&String>) -> bool {
83    if head_1 == "NORMAL" {
84        head_2.is_some_and(|v| v == "FLYING")
85    } else {
86        false
87    }
88}
89
90#[cfg(test)]
91mod tests {
92    use crate::test::PathTracked;
93
94    use super::*;
95
96    const TYPES_DAT: &[u8] = include_bytes!("../InfiniteFusion/Data/types.dat");
97
98    #[test]
99    fn deserialize_types_dat_vec() {
100        let PathTracked(dex) = reikland::from_bytes::<PathTracked<TypeDex>>(TYPES_DAT)
101            .unwrap_or_else(|e| panic!("types.dat failed to deserialize: {e}"));
102
103        assert!(!dex.0.is_empty());
104        assert_normal(dex.0.first().unwrap());
105    }
106
107    #[test]
108    fn deserialize_types_dat_map() {
109        let PathTracked(dex) = reikland::from_bytes::<PathTracked<TypeMap>>(TYPES_DAT)
110            .unwrap_or_else(|e| panic!("types.dat failed to deserialize: {e}"));
111
112        assert!(!dex.0.is_empty());
113        assert_normal(dex.0.first().unwrap().1);
114    }
115
116    fn assert_normal(t: &Type) {
117        assert_eq!(t.id, "NORMAL");
118        assert_eq!(t.id_number, 0);
119        assert_eq!(t.real_name, "Normal");
120        assert!(!t.pseudo_type);
121        assert!(!t.special_type);
122        assert_eq!(t.weaknesses, vec!["FIGHTING"]);
123        assert!(t.resistances.is_empty());
124        assert_eq!(t.immunities, vec!["GHOST"]);
125    }
126}