diff --git a/riven/src/consts/champion.rs b/riven/src/consts/champion.rs index 3d75f1f..2d072ff 100644 --- a/riven/src/consts/champion.rs +++ b/riven/src/consts/champion.rs @@ -860,182 +860,195 @@ impl Champion { } } +#[derive(Debug)] +pub struct ParseChampionError([char; 4]); +impl std::fmt::Display for ParseChampionError { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + let s: String = self.0.iter().copied().take_while(|&c| '\0' != c).collect(); + write!(f, "Failed to parse unknown champion prefix: {:?}", s) + } +} +impl std::error::Error for ParseChampionError {} + impl std::str::FromStr for Champion { - type Err = (); + type Err = ParseChampionError; fn from_str(s: &str) -> Result { - match s.chars() + let mut chars = ['\0'; 4]; + s.chars() .take(4) .filter(|c| c.is_ascii_alphanumeric()) - .fold(0_u32, |hash, next| hash * 256 + u32::from(next)) - { - 0x41415452 /* AATR */ => Ok(Champion::AATROX), - 0x41485249 /* AHRI */ => Ok(Champion::AHRI), - 0x414b414c /* AKAL */ => Ok(Champion::AKALI), - 0x414b5348 /* AKSH */ => Ok(Champion::AKSHAN), - 0x414c4953 /* ALIS */ => Ok(Champion::ALISTAR), - 0x414d554d /* AMUM */ => Ok(Champion::AMUMU), - 0x414e4956 /* ANIV */ => Ok(Champion::ANIVIA), - 0x414e4e49 /* ANNI */ => Ok(Champion::ANNIE), - 0x41504845 /* APHE */ => Ok(Champion::APHELIOS), - 0x41534845 /* ASHE */ => Ok(Champion::ASHE), - 0x41555245 /* AURE */ => Ok(Champion::AURELION_SOL), - 0x415a4952 /* AZIR */ => Ok(Champion::AZIR), - 0x42415244 /* BARD */ => Ok(Champion::BARD), - 0x424c4954 /* BLIT */ => Ok(Champion::BLITZCRANK), - 0x4252414e /* BRAN */ => Ok(Champion::BRAND), - 0x42524155 /* BRAU */ => Ok(Champion::BRAUM), - 0x43414954 /* CAIT */ => Ok(Champion::CAITLYN), - 0x43414d49 /* CAMI */ => Ok(Champion::CAMILLE), - 0x43415353 /* CASS */ => Ok(Champion::CASSIOPEIA), - 0x43484f47 /* CHOG */ => Ok(Champion::CHO_GATH), - 0x43484f /* CHO */ => Ok(Champion::CHO_GATH), - 0x434f524b /* CORK */ => Ok(Champion::CORKI), - 0x44415249 /* DARI */ => Ok(Champion::DARIUS), - 0x4449414e /* DIAN */ => Ok(Champion::DIANA), - 0x44524d55 /* DRMU */ => Ok(Champion::DR_MUNDO), - 0x4452 /* DR */ => Ok(Champion::DR_MUNDO), - 0x44524156 /* DRAV */ => Ok(Champion::DRAVEN), - 0x454b4b4f /* EKKO */ => Ok(Champion::EKKO), - 0x454c4953 /* ELIS */ => Ok(Champion::ELISE), - 0x4556454c /* EVEL */ => Ok(Champion::EVELYNN), - 0x455a5245 /* EZRE */ => Ok(Champion::EZREAL), - 0x46494444 /* FIDD */ => Ok(Champion::FIDDLESTICKS), - 0x46494f52 /* FIOR */ => Ok(Champion::FIORA), - 0x46495a5a /* FIZZ */ => Ok(Champion::FIZZ), - 0x47414c49 /* GALI */ => Ok(Champion::GALIO), - 0x47414e47 /* GANG */ => Ok(Champion::GANGPLANK), - 0x47415245 /* GARE */ => Ok(Champion::GAREN), - 0x474e4152 /* GNAR */ => Ok(Champion::GNAR), - 0x47524147 /* GRAG */ => Ok(Champion::GRAGAS), - 0x47524156 /* GRAV */ => Ok(Champion::GRAVES), - 0x4757454e /* GWEN */ => Ok(Champion::GWEN), - 0x48454341 /* HECA */ => Ok(Champion::HECARIM), - 0x4845494d /* HEIM */ => Ok(Champion::HEIMERDINGER), - 0x494c4c41 /* ILLA */ => Ok(Champion::ILLAOI), - 0x4952454c /* IREL */ => Ok(Champion::IRELIA), - 0x49564552 /* IVER */ => Ok(Champion::IVERN), - 0x4a414e4e /* JANN */ => Ok(Champion::JANNA), - 0x4a415256 /* JARV */ => Ok(Champion::JARVAN_IV), - 0x4a4158 /* JAX */ => Ok(Champion::JAX), - 0x4a415943 /* JAYC */ => Ok(Champion::JAYCE), - 0x4a48494e /* JHIN */ => Ok(Champion::JHIN), - 0x4a494e58 /* JINX */ => Ok(Champion::JINX), - 0x4b414953 /* KAIS */ => Ok(Champion::KAI_SA), - 0x4b4149 /* KAI */ => Ok(Champion::KAI_SA), - 0x4b414c49 /* KALI */ => Ok(Champion::KALISTA), - 0x4b41524d /* KARM */ => Ok(Champion::KARMA), - 0x4b415254 /* KART */ => Ok(Champion::KARTHUS), - 0x4b415353 /* KASS */ => Ok(Champion::KASSADIN), - 0x4b415441 /* KATA */ => Ok(Champion::KATARINA), - 0x4b41594c /* KAYL */ => Ok(Champion::KAYLE), - 0x4b41594e /* KAYN */ => Ok(Champion::KAYN), - 0x4b454e4e /* KENN */ => Ok(Champion::KENNEN), - 0x4b48415a /* KHAZ */ => Ok(Champion::KHA_ZIX), - 0x4b4841 /* KHA */ => Ok(Champion::KHA_ZIX), - 0x4b494e44 /* KIND */ => Ok(Champion::KINDRED), - 0x4b4c4544 /* KLED */ => Ok(Champion::KLED), - 0x4b4f474d /* KOGM */ => Ok(Champion::KOG_MAW), - 0x4b4f47 /* KOG */ => Ok(Champion::KOG_MAW), - 0x4c45424c /* LEBL */ => Ok(Champion::LE_BLANC), - 0x4c454553 /* LEES */ => Ok(Champion::LEE_SIN), - 0x4c4545 /* LEE */ => Ok(Champion::LEE_SIN), - 0x4c454f4e /* LEON */ => Ok(Champion::LEONA), - 0x4c494c4c /* LILL */ => Ok(Champion::LILLIA), - 0x4c495353 /* LISS */ => Ok(Champion::LISSANDRA), - 0x4c554349 /* LUCI */ => Ok(Champion::LUCIAN), - 0x4c554c55 /* LULU */ => Ok(Champion::LULU), - 0x4c5558 /* LUX */ => Ok(Champion::LUX), - 0x4d414c50 /* MALP */ => Ok(Champion::MALPHITE), - 0x4d414c5a /* MALZ */ => Ok(Champion::MALZAHAR), - 0x4d414f4b /* MAOK */ => Ok(Champion::MAOKAI), - 0x4d415354 /* MAST */ => Ok(Champion::MASTER_YI), - 0x4d495353 /* MISS */ => Ok(Champion::MISS_FORTUNE), - 0x4d4f5244 /* MORD */ => Ok(Champion::MORDEKAISER), - 0x4d4f5247 /* MORG */ => Ok(Champion::MORGANA), - 0x4e414d49 /* NAMI */ => Ok(Champion::NAMI), - 0x4e415355 /* NASU */ => Ok(Champion::NASUS), - 0x4e415554 /* NAUT */ => Ok(Champion::NAUTILUS), - 0x4e45454b /* NEEK */ => Ok(Champion::NEEKO), - 0x4e494441 /* NIDA */ => Ok(Champion::NIDALEE), - 0x4e4f4354 /* NOCT */ => Ok(Champion::NOCTURNE), - 0x4e554e55 /* NUNU */ => Ok(Champion::NUNU_WILLUMP), - 0x4f4c4146 /* OLAF */ => Ok(Champion::OLAF), - 0x4f524941 /* ORIA */ => Ok(Champion::ORIANNA), - 0x4f524e4e /* ORNN */ => Ok(Champion::ORNN), - 0x50414e54 /* PANT */ => Ok(Champion::PANTHEON), - 0x504f5050 /* POPP */ => Ok(Champion::POPPY), - 0x50594b45 /* PYKE */ => Ok(Champion::PYKE), - 0x51495941 /* QIYA */ => Ok(Champion::QIYANA), - 0x5155494e /* QUIN */ => Ok(Champion::QUINN), - 0x52414b41 /* RAKA */ => Ok(Champion::RAKAN), - 0x52414d4d /* RAMM */ => Ok(Champion::RAMMUS), - 0x52454b53 /* REKS */ => Ok(Champion::REK_SAI), - 0x52454b /* REK */ => Ok(Champion::REK_SAI), - 0x52454c4c /* RELL */ => Ok(Champion::RELL), - 0x52454e45 /* RENE */ => Ok(Champion::RENEKTON), - 0x52454e47 /* RENG */ => Ok(Champion::RENGAR), - 0x52495645 /* RIVE */ => Ok(Champion::RIVEN), - 0x52554d42 /* RUMB */ => Ok(Champion::RUMBLE), - 0x52595a45 /* RYZE */ => Ok(Champion::RYZE), - 0x53414d49 /* SAMI */ => Ok(Champion::SAMIRA), - 0x53454a55 /* SEJU */ => Ok(Champion::SEJUANI), - 0x53454e4e /* SENN */ => Ok(Champion::SENNA), - 0x53455241 /* SERA */ => Ok(Champion::SERAPHINE), - 0x53455454 /* SETT */ => Ok(Champion::SETT), - 0x53484143 /* SHAC */ => Ok(Champion::SHACO), - 0x5348454e /* SHEN */ => Ok(Champion::SHEN), - 0x53485956 /* SHYV */ => Ok(Champion::SHYVANA), - 0x53494e47 /* SING */ => Ok(Champion::SINGED), - 0x53494f4e /* SION */ => Ok(Champion::SION), - 0x53495649 /* SIVI */ => Ok(Champion::SIVIR), - 0x534b4152 /* SKAR */ => Ok(Champion::SKARNER), - 0x534f4e41 /* SONA */ => Ok(Champion::SONA), - 0x534f5241 /* SORA */ => Ok(Champion::SORAKA), - 0x53574149 /* SWAI */ => Ok(Champion::SWAIN), - 0x53594c41 /* SYLA */ => Ok(Champion::SYLAS), - 0x53594e44 /* SYND */ => Ok(Champion::SYNDRA), - 0x5441484d /* TAHM */ => Ok(Champion::TAHM_KENCH), - 0x54414c49 /* TALI */ => Ok(Champion::TALIYAH), - 0x54414c4f /* TALO */ => Ok(Champion::TALON), - 0x54415249 /* TARI */ => Ok(Champion::TARIC), - 0x5445454d /* TEEM */ => Ok(Champion::TEEMO), - 0x54485245 /* THRE */ => Ok(Champion::THRESH), - 0x54524953 /* TRIS */ => Ok(Champion::TRISTANA), - 0x5452554e /* TRUN */ => Ok(Champion::TRUNDLE), - 0x5452594e /* TRYN */ => Ok(Champion::TRYNDAMERE), - 0x54574953 /* TWIS */ => Ok(Champion::TWISTED_FATE), - 0x54574954 /* TWIT */ => Ok(Champion::TWITCH), - 0x55445952 /* UDYR */ => Ok(Champion::UDYR), - 0x5552474f /* URGO */ => Ok(Champion::URGOT), - 0x56415255 /* VARU */ => Ok(Champion::VARUS), - 0x5641594e /* VAYN */ => Ok(Champion::VAYNE), - 0x56454947 /* VEIG */ => Ok(Champion::VEIGAR), - 0x56454c4b /* VELK */ => Ok(Champion::VEL_KOZ), - 0x56454c /* VEL */ => Ok(Champion::VEL_KOZ), - 0x564558 /* VEX */ => Ok(Champion::VEX), - 0x5649 /* VI */ => Ok(Champion::VI), - 0x56494547 /* VIEG */ => Ok(Champion::VIEGO), - 0x56494b54 /* VIKT */ => Ok(Champion::VIKTOR), - 0x564c4144 /* VLAD */ => Ok(Champion::VLADIMIR), - 0x564f4c49 /* VOLI */ => Ok(Champion::VOLIBEAR), - 0x57415257 /* WARW */ => Ok(Champion::WARWICK), - 0x57554b4f /* WUKO */ => Ok(Champion::WUKONG), - 0x4d4f4e4b /* MONK */ => Ok(Champion::WUKONG), - 0x58415941 /* XAYA */ => Ok(Champion::XAYAH), - 0x58455241 /* XERA */ => Ok(Champion::XERATH), - 0x58494e5a /* XINZ */ => Ok(Champion::XIN_ZHAO), - 0x58494e /* XIN */ => Ok(Champion::XIN_ZHAO), - 0x59415355 /* YASU */ => Ok(Champion::YASUO), - 0x594f4e45 /* YONE */ => Ok(Champion::YONE), - 0x594f5249 /* YORI */ => Ok(Champion::YORICK), - 0x5955554d /* YUUM */ => Ok(Champion::YUUMI), - 0x5a4143 /* ZAC */ => Ok(Champion::ZAC), - 0x5a4544 /* ZED */ => Ok(Champion::ZED), - 0x5a494747 /* ZIGG */ => Ok(Champion::ZIGGS), - 0x5a494c45 /* ZILE */ => Ok(Champion::ZILEAN), - 0x5a4f45 /* ZOE */ => Ok(Champion::ZOE), - 0x5a595241 /* ZYRA */ => Ok(Champion::ZYRA), - _ => Err(()), + .map(|c| c.to_ascii_uppercase()) + .enumerate() + .for_each(|(i, c)| chars[i] = c); + match chars { + /* AATR */ [ 'A', 'A', 'T', 'R'] => Ok(Champion::AATROX), + /* AHRI */ [ 'A', 'H', 'R', 'I'] => Ok(Champion::AHRI), + /* AKAL */ [ 'A', 'K', 'A', 'L'] => Ok(Champion::AKALI), + /* AKSH */ [ 'A', 'K', 'S', 'H'] => Ok(Champion::AKSHAN), + /* ALIS */ [ 'A', 'L', 'I', 'S'] => Ok(Champion::ALISTAR), + /* AMUM */ [ 'A', 'M', 'U', 'M'] => Ok(Champion::AMUMU), + /* ANIV */ [ 'A', 'N', 'I', 'V'] => Ok(Champion::ANIVIA), + /* ANNI */ [ 'A', 'N', 'N', 'I'] => Ok(Champion::ANNIE), + /* APHE */ [ 'A', 'P', 'H', 'E'] => Ok(Champion::APHELIOS), + /* ASHE */ [ 'A', 'S', 'H', 'E'] => Ok(Champion::ASHE), + /* AURE */ [ 'A', 'U', 'R', 'E'] => Ok(Champion::AURELION_SOL), + /* AZIR */ [ 'A', 'Z', 'I', 'R'] => Ok(Champion::AZIR), + /* BARD */ [ 'B', 'A', 'R', 'D'] => Ok(Champion::BARD), + /* BLIT */ [ 'B', 'L', 'I', 'T'] => Ok(Champion::BLITZCRANK), + /* BRAN */ [ 'B', 'R', 'A', 'N'] => Ok(Champion::BRAND), + /* BRAU */ [ 'B', 'R', 'A', 'U'] => Ok(Champion::BRAUM), + /* CAIT */ [ 'C', 'A', 'I', 'T'] => Ok(Champion::CAITLYN), + /* CAMI */ [ 'C', 'A', 'M', 'I'] => Ok(Champion::CAMILLE), + /* CASS */ [ 'C', 'A', 'S', 'S'] => Ok(Champion::CASSIOPEIA), + /* CHOG */ [ 'C', 'H', 'O', 'G'] => Ok(Champion::CHO_GATH), + /* CHO */ [ 'C', 'H', 'O', '\0'] => Ok(Champion::CHO_GATH), + /* CORK */ [ 'C', 'O', 'R', 'K'] => Ok(Champion::CORKI), + /* DARI */ [ 'D', 'A', 'R', 'I'] => Ok(Champion::DARIUS), + /* DIAN */ [ 'D', 'I', 'A', 'N'] => Ok(Champion::DIANA), + /* DRMU */ [ 'D', 'R', 'M', 'U'] => Ok(Champion::DR_MUNDO), + /* DR */ [ 'D', 'R', '\0', '\0'] => Ok(Champion::DR_MUNDO), + /* DRAV */ [ 'D', 'R', 'A', 'V'] => Ok(Champion::DRAVEN), + /* EKKO */ [ 'E', 'K', 'K', 'O'] => Ok(Champion::EKKO), + /* ELIS */ [ 'E', 'L', 'I', 'S'] => Ok(Champion::ELISE), + /* EVEL */ [ 'E', 'V', 'E', 'L'] => Ok(Champion::EVELYNN), + /* EZRE */ [ 'E', 'Z', 'R', 'E'] => Ok(Champion::EZREAL), + /* FIDD */ [ 'F', 'I', 'D', 'D'] => Ok(Champion::FIDDLESTICKS), + /* FIOR */ [ 'F', 'I', 'O', 'R'] => Ok(Champion::FIORA), + /* FIZZ */ [ 'F', 'I', 'Z', 'Z'] => Ok(Champion::FIZZ), + /* GALI */ [ 'G', 'A', 'L', 'I'] => Ok(Champion::GALIO), + /* GANG */ [ 'G', 'A', 'N', 'G'] => Ok(Champion::GANGPLANK), + /* GARE */ [ 'G', 'A', 'R', 'E'] => Ok(Champion::GAREN), + /* GNAR */ [ 'G', 'N', 'A', 'R'] => Ok(Champion::GNAR), + /* GRAG */ [ 'G', 'R', 'A', 'G'] => Ok(Champion::GRAGAS), + /* GRAV */ [ 'G', 'R', 'A', 'V'] => Ok(Champion::GRAVES), + /* GWEN */ [ 'G', 'W', 'E', 'N'] => Ok(Champion::GWEN), + /* HECA */ [ 'H', 'E', 'C', 'A'] => Ok(Champion::HECARIM), + /* HEIM */ [ 'H', 'E', 'I', 'M'] => Ok(Champion::HEIMERDINGER), + /* ILLA */ [ 'I', 'L', 'L', 'A'] => Ok(Champion::ILLAOI), + /* IREL */ [ 'I', 'R', 'E', 'L'] => Ok(Champion::IRELIA), + /* IVER */ [ 'I', 'V', 'E', 'R'] => Ok(Champion::IVERN), + /* JANN */ [ 'J', 'A', 'N', 'N'] => Ok(Champion::JANNA), + /* JARV */ [ 'J', 'A', 'R', 'V'] => Ok(Champion::JARVAN_IV), + /* JAX */ [ 'J', 'A', 'X', '\0'] => Ok(Champion::JAX), + /* JAYC */ [ 'J', 'A', 'Y', 'C'] => Ok(Champion::JAYCE), + /* JHIN */ [ 'J', 'H', 'I', 'N'] => Ok(Champion::JHIN), + /* JINX */ [ 'J', 'I', 'N', 'X'] => Ok(Champion::JINX), + /* KAIS */ [ 'K', 'A', 'I', 'S'] => Ok(Champion::KAI_SA), + /* KAI */ [ 'K', 'A', 'I', '\0'] => Ok(Champion::KAI_SA), + /* KALI */ [ 'K', 'A', 'L', 'I'] => Ok(Champion::KALISTA), + /* KARM */ [ 'K', 'A', 'R', 'M'] => Ok(Champion::KARMA), + /* KART */ [ 'K', 'A', 'R', 'T'] => Ok(Champion::KARTHUS), + /* KASS */ [ 'K', 'A', 'S', 'S'] => Ok(Champion::KASSADIN), + /* KATA */ [ 'K', 'A', 'T', 'A'] => Ok(Champion::KATARINA), + /* KAYL */ [ 'K', 'A', 'Y', 'L'] => Ok(Champion::KAYLE), + /* KAYN */ [ 'K', 'A', 'Y', 'N'] => Ok(Champion::KAYN), + /* KENN */ [ 'K', 'E', 'N', 'N'] => Ok(Champion::KENNEN), + /* KHAZ */ [ 'K', 'H', 'A', 'Z'] => Ok(Champion::KHA_ZIX), + /* KHA */ [ 'K', 'H', 'A', '\0'] => Ok(Champion::KHA_ZIX), + /* KIND */ [ 'K', 'I', 'N', 'D'] => Ok(Champion::KINDRED), + /* KLED */ [ 'K', 'L', 'E', 'D'] => Ok(Champion::KLED), + /* KOGM */ [ 'K', 'O', 'G', 'M'] => Ok(Champion::KOG_MAW), + /* KOG */ [ 'K', 'O', 'G', '\0'] => Ok(Champion::KOG_MAW), + /* LEBL */ [ 'L', 'E', 'B', 'L'] => Ok(Champion::LE_BLANC), + /* LEES */ [ 'L', 'E', 'E', 'S'] => Ok(Champion::LEE_SIN), + /* LEE */ [ 'L', 'E', 'E', '\0'] => Ok(Champion::LEE_SIN), + /* LEON */ [ 'L', 'E', 'O', 'N'] => Ok(Champion::LEONA), + /* LILL */ [ 'L', 'I', 'L', 'L'] => Ok(Champion::LILLIA), + /* LISS */ [ 'L', 'I', 'S', 'S'] => Ok(Champion::LISSANDRA), + /* LUCI */ [ 'L', 'U', 'C', 'I'] => Ok(Champion::LUCIAN), + /* LULU */ [ 'L', 'U', 'L', 'U'] => Ok(Champion::LULU), + /* LUX */ [ 'L', 'U', 'X', '\0'] => Ok(Champion::LUX), + /* MALP */ [ 'M', 'A', 'L', 'P'] => Ok(Champion::MALPHITE), + /* MALZ */ [ 'M', 'A', 'L', 'Z'] => Ok(Champion::MALZAHAR), + /* MAOK */ [ 'M', 'A', 'O', 'K'] => Ok(Champion::MAOKAI), + /* MAST */ [ 'M', 'A', 'S', 'T'] => Ok(Champion::MASTER_YI), + /* MISS */ [ 'M', 'I', 'S', 'S'] => Ok(Champion::MISS_FORTUNE), + /* MORD */ [ 'M', 'O', 'R', 'D'] => Ok(Champion::MORDEKAISER), + /* MORG */ [ 'M', 'O', 'R', 'G'] => Ok(Champion::MORGANA), + /* NAMI */ [ 'N', 'A', 'M', 'I'] => Ok(Champion::NAMI), + /* NASU */ [ 'N', 'A', 'S', 'U'] => Ok(Champion::NASUS), + /* NAUT */ [ 'N', 'A', 'U', 'T'] => Ok(Champion::NAUTILUS), + /* NEEK */ [ 'N', 'E', 'E', 'K'] => Ok(Champion::NEEKO), + /* NIDA */ [ 'N', 'I', 'D', 'A'] => Ok(Champion::NIDALEE), + /* NOCT */ [ 'N', 'O', 'C', 'T'] => Ok(Champion::NOCTURNE), + /* NUNU */ [ 'N', 'U', 'N', 'U'] => Ok(Champion::NUNU_WILLUMP), + /* OLAF */ [ 'O', 'L', 'A', 'F'] => Ok(Champion::OLAF), + /* ORIA */ [ 'O', 'R', 'I', 'A'] => Ok(Champion::ORIANNA), + /* ORNN */ [ 'O', 'R', 'N', 'N'] => Ok(Champion::ORNN), + /* PANT */ [ 'P', 'A', 'N', 'T'] => Ok(Champion::PANTHEON), + /* POPP */ [ 'P', 'O', 'P', 'P'] => Ok(Champion::POPPY), + /* PYKE */ [ 'P', 'Y', 'K', 'E'] => Ok(Champion::PYKE), + /* QIYA */ [ 'Q', 'I', 'Y', 'A'] => Ok(Champion::QIYANA), + /* QUIN */ [ 'Q', 'U', 'I', 'N'] => Ok(Champion::QUINN), + /* RAKA */ [ 'R', 'A', 'K', 'A'] => Ok(Champion::RAKAN), + /* RAMM */ [ 'R', 'A', 'M', 'M'] => Ok(Champion::RAMMUS), + /* REKS */ [ 'R', 'E', 'K', 'S'] => Ok(Champion::REK_SAI), + /* REK */ [ 'R', 'E', 'K', '\0'] => Ok(Champion::REK_SAI), + /* RELL */ [ 'R', 'E', 'L', 'L'] => Ok(Champion::RELL), + /* RENE */ [ 'R', 'E', 'N', 'E'] => Ok(Champion::RENEKTON), + /* RENG */ [ 'R', 'E', 'N', 'G'] => Ok(Champion::RENGAR), + /* RIVE */ [ 'R', 'I', 'V', 'E'] => Ok(Champion::RIVEN), + /* RUMB */ [ 'R', 'U', 'M', 'B'] => Ok(Champion::RUMBLE), + /* RYZE */ [ 'R', 'Y', 'Z', 'E'] => Ok(Champion::RYZE), + /* SAMI */ [ 'S', 'A', 'M', 'I'] => Ok(Champion::SAMIRA), + /* SEJU */ [ 'S', 'E', 'J', 'U'] => Ok(Champion::SEJUANI), + /* SENN */ [ 'S', 'E', 'N', 'N'] => Ok(Champion::SENNA), + /* SERA */ [ 'S', 'E', 'R', 'A'] => Ok(Champion::SERAPHINE), + /* SETT */ [ 'S', 'E', 'T', 'T'] => Ok(Champion::SETT), + /* SHAC */ [ 'S', 'H', 'A', 'C'] => Ok(Champion::SHACO), + /* SHEN */ [ 'S', 'H', 'E', 'N'] => Ok(Champion::SHEN), + /* SHYV */ [ 'S', 'H', 'Y', 'V'] => Ok(Champion::SHYVANA), + /* SING */ [ 'S', 'I', 'N', 'G'] => Ok(Champion::SINGED), + /* SION */ [ 'S', 'I', 'O', 'N'] => Ok(Champion::SION), + /* SIVI */ [ 'S', 'I', 'V', 'I'] => Ok(Champion::SIVIR), + /* SKAR */ [ 'S', 'K', 'A', 'R'] => Ok(Champion::SKARNER), + /* SONA */ [ 'S', 'O', 'N', 'A'] => Ok(Champion::SONA), + /* SORA */ [ 'S', 'O', 'R', 'A'] => Ok(Champion::SORAKA), + /* SWAI */ [ 'S', 'W', 'A', 'I'] => Ok(Champion::SWAIN), + /* SYLA */ [ 'S', 'Y', 'L', 'A'] => Ok(Champion::SYLAS), + /* SYND */ [ 'S', 'Y', 'N', 'D'] => Ok(Champion::SYNDRA), + /* TAHM */ [ 'T', 'A', 'H', 'M'] => Ok(Champion::TAHM_KENCH), + /* TALI */ [ 'T', 'A', 'L', 'I'] => Ok(Champion::TALIYAH), + /* TALO */ [ 'T', 'A', 'L', 'O'] => Ok(Champion::TALON), + /* TARI */ [ 'T', 'A', 'R', 'I'] => Ok(Champion::TARIC), + /* TEEM */ [ 'T', 'E', 'E', 'M'] => Ok(Champion::TEEMO), + /* THRE */ [ 'T', 'H', 'R', 'E'] => Ok(Champion::THRESH), + /* TRIS */ [ 'T', 'R', 'I', 'S'] => Ok(Champion::TRISTANA), + /* TRUN */ [ 'T', 'R', 'U', 'N'] => Ok(Champion::TRUNDLE), + /* TRYN */ [ 'T', 'R', 'Y', 'N'] => Ok(Champion::TRYNDAMERE), + /* TWIS */ [ 'T', 'W', 'I', 'S'] => Ok(Champion::TWISTED_FATE), + /* TWIT */ [ 'T', 'W', 'I', 'T'] => Ok(Champion::TWITCH), + /* UDYR */ [ 'U', 'D', 'Y', 'R'] => Ok(Champion::UDYR), + /* URGO */ [ 'U', 'R', 'G', 'O'] => Ok(Champion::URGOT), + /* VARU */ [ 'V', 'A', 'R', 'U'] => Ok(Champion::VARUS), + /* VAYN */ [ 'V', 'A', 'Y', 'N'] => Ok(Champion::VAYNE), + /* VEIG */ [ 'V', 'E', 'I', 'G'] => Ok(Champion::VEIGAR), + /* VELK */ [ 'V', 'E', 'L', 'K'] => Ok(Champion::VEL_KOZ), + /* VEL */ [ 'V', 'E', 'L', '\0'] => Ok(Champion::VEL_KOZ), + /* VEX */ [ 'V', 'E', 'X', '\0'] => Ok(Champion::VEX), + /* VI */ [ 'V', 'I', '\0', '\0'] => Ok(Champion::VI), + /* VIEG */ [ 'V', 'I', 'E', 'G'] => Ok(Champion::VIEGO), + /* VIKT */ [ 'V', 'I', 'K', 'T'] => Ok(Champion::VIKTOR), + /* VLAD */ [ 'V', 'L', 'A', 'D'] => Ok(Champion::VLADIMIR), + /* VOLI */ [ 'V', 'O', 'L', 'I'] => Ok(Champion::VOLIBEAR), + /* WARW */ [ 'W', 'A', 'R', 'W'] => Ok(Champion::WARWICK), + /* WUKO */ [ 'W', 'U', 'K', 'O'] => Ok(Champion::WUKONG), + /* MONK */ [ 'M', 'O', 'N', 'K'] => Ok(Champion::WUKONG), + /* XAYA */ [ 'X', 'A', 'Y', 'A'] => Ok(Champion::XAYAH), + /* XERA */ [ 'X', 'E', 'R', 'A'] => Ok(Champion::XERATH), + /* XINZ */ [ 'X', 'I', 'N', 'Z'] => Ok(Champion::XIN_ZHAO), + /* XIN */ [ 'X', 'I', 'N', '\0'] => Ok(Champion::XIN_ZHAO), + /* YASU */ [ 'Y', 'A', 'S', 'U'] => Ok(Champion::YASUO), + /* YONE */ [ 'Y', 'O', 'N', 'E'] => Ok(Champion::YONE), + /* YORI */ [ 'Y', 'O', 'R', 'I'] => Ok(Champion::YORICK), + /* YUUM */ [ 'Y', 'U', 'U', 'M'] => Ok(Champion::YUUMI), + /* ZAC */ [ 'Z', 'A', 'C', '\0'] => Ok(Champion::ZAC), + /* ZED */ [ 'Z', 'E', 'D', '\0'] => Ok(Champion::ZED), + /* ZIGG */ [ 'Z', 'I', 'G', 'G'] => Ok(Champion::ZIGGS), + /* ZILE */ [ 'Z', 'I', 'L', 'E'] => Ok(Champion::ZILEAN), + /* ZOE */ [ 'Z', 'O', 'E', '\0'] => Ok(Champion::ZOE), + /* ZYRA */ [ 'Z', 'Y', 'R', 'A'] => Ok(Champion::ZYRA), + unknown => Err(ParseChampionError(unknown)), } } } diff --git a/riven/src/error.rs b/riven/src/error.rs index 8159ae3..76ba627 100644 --- a/riven/src/error.rs +++ b/riven/src/error.rs @@ -1,4 +1,3 @@ -use std::error::Error as StdError; use std::fmt; use reqwest::{ Error, Response, StatusCode }; @@ -58,8 +57,8 @@ impl fmt::Display for RiotApiError { write!(f, "{:#?}", self) } } -impl StdError for RiotApiError { - fn source(&self) -> Option<&(dyn StdError + 'static)> { +impl std::error::Error for RiotApiError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { Some(&self.reqwest_error) } } diff --git a/riven/srcgen/consts/champion.rs.dt b/riven/srcgen/consts/champion.rs.dt index a650a15..9ac48b4 100644 --- a/riven/srcgen/consts/champion.rs.dt +++ b/riven/srcgen/consts/champion.rs.dt @@ -6,14 +6,6 @@ const constName = name => dotUtils.changeCase.constantCase(name).replace(/[^_A-Z0-9]+/g, ''); const constNamePad = 12; - - const hashFactor = 256; - const strHash = (str) => { - let h = 0; - for (const c of str) - h = hashFactor * h + c.charCodeAt(0); - return h; - }; }}{{= dotUtils.preamble() }} newtype_enum! { @@ -115,14 +107,27 @@ impl Champion { } } +#[derive(Debug)] +pub struct ParseChampionError([char; 4]); +impl std::fmt::Display for ParseChampionError { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + let s: String = self.0.iter().copied().take_while(|&c| '\0' != c).collect(); + write!(f, "Failed to parse unknown champion prefix: {:?}", s) + } +} +impl std::error::Error for ParseChampionError {} + impl std::str::FromStr for Champion { - type Err = (); + type Err = ParseChampionError; fn from_str(s: &str) -> Result { - match s.chars() + let mut chars = ['\0'; 4]; + s.chars() .take(4) .filter(|c| c.is_ascii_alphanumeric()) - .fold(0_u32, |hash, next| hash * {{= hashFactor }} + u32::from(next)) - { + .map(|c| c.to_ascii_uppercase()) + .enumerate() + .for_each(|(i, c)| chars[i] = c); + match chars { {{ const keyStrings = (name, alias) => new Set([].concat(...[ name, alias ].map(s => s.toUpperCase()) .map(s => [ @@ -132,13 +137,16 @@ impl std::str::FromStr for Champion { ]))); for (const { id, alias, name } of champions) { for (const prefix of keyStrings(name, alias)) { + const chars = Object.assign(Array(4).fill('\\0'), Array.from(prefix)) + .map(c => `'${c}'`) + .map(c => c.padStart(4)); }} - 0x{{= strHash(prefix).toString(16).padEnd(8) }} /* {{= prefix.padEnd(4) }} */ => Ok(Champion::{{= constName(name) }}), + /* {{= prefix.padEnd(4) }} */ [{{= chars.join(', ') }}] => Ok(Champion::{{= constName(name) }}), {{ } } }} - _ => Err(()), + unknown => Err(ParseChampionError(unknown)), } } } diff --git a/riven/tests/testutils.rs b/riven/tests/testutils.rs index 0112164..c748619 100644 --- a/riven/tests/testutils.rs +++ b/riven/tests/testutils.rs @@ -40,6 +40,12 @@ pub async fn match_v5_get(route: RegionalRoute, matches: &[&'static str]) -> Res if m.metadata.participants.is_empty() { return Err("Match should have participants.".to_owned()); } + if m.metadata.participants.len() != m.info.participants.len() { + return Err("Match participants do not line up with participant UUIDs.".to_owned()); + } + for participant in &m.info.participants { + participant.champion().map_err(|e| format!("Failed to determine champion: {}", e))?; + } if m.info.teams.is_empty() { return Err("Match should have teams.".to_owned()); }