Skip to main content

rosu_mods/
serde.rs

1#![cfg(feature = "serde")]
2
3use std::{
4    collections::{BTreeMap, HashMap},
5    error::Error as StdError,
6    fmt::{Debug, Display, Formatter, Result as FmtResult},
7    marker::PhantomData,
8    slice,
9    str::FromStr,
10};
11
12use serde::de::{
13    value::BorrowedStrDeserializer, Deserialize, DeserializeSeed, Deserializer, Error as DeError,
14    IgnoredAny, MapAccess, SeqAccess, Unexpected, Visitor,
15};
16
17use crate::{
18    generated_mods::{GameMod, UnknownMod},
19    order::GameModOrder,
20    simple::SettingSimple,
21    Acronym, GameModIntermode, GameMode, GameMods, GameModsIntermode,
22};
23
24pub(crate) const BITFLAGS_U32: &str = "bitflags must be a u32";
25const EXPECTED_ACRONYM_FIRST: &str = "expected `acronym` as first field";
26
27const MODES: [GameMode; 4] = [
28    GameMode::Osu,
29    GameMode::Taiko,
30    GameMode::Catch,
31    GameMode::Mania,
32];
33
34pub(crate) struct GameModVisitor<M>(PhantomData<M>);
35
36impl<M> GameModVisitor<M> {
37    pub(crate) const fn new() -> Self {
38        Self(PhantomData)
39    }
40}
41
42pub(crate) struct DeserializedGameMod<'a, M> {
43    pub(crate) gamemod: M,
44    pub(crate) unknown_key: Option<UnknownKey<'a>>,
45}
46
47impl<'a, M> DeserializedGameMod<'a, M> {
48    pub(crate) fn new(
49        gamemod: M,
50        unknown_key: Option<MaybeOwnedStr<'a>>,
51        expected: &'static [&'static str],
52    ) -> Self {
53        Self {
54            gamemod,
55            unknown_key: UnknownKey::new(unknown_key, expected),
56        }
57    }
58}
59
60impl<'de, M> DeserializedGameMod<'de, M> {
61    pub(crate) fn try_deserialize_mod<D>(d: D, deny_unknown_fields: bool) -> Result<M, D::Error>
62    where
63        GameModVisitor<M>: Visitor<'de, Value = Self>,
64        D: Deserializer<'de>,
65    {
66        match d.deserialize_map(GameModVisitor::<M>::new()) {
67            Ok(Self { gamemod, .. }) if !deny_unknown_fields => Ok(gamemod),
68            Ok(Self {
69                gamemod,
70                unknown_key: None,
71            }) => Ok(gamemod),
72            Ok(Self {
73                unknown_key: Some(key),
74                ..
75            }) => Err(Self::unknown_field(&key)),
76            Err(err) => Err(err),
77        }
78    }
79
80    fn unknown_field<E: DeError>(unknown_key: &UnknownKey<'_>) -> E {
81        DeError::unknown_field(unknown_key.name.as_str(), unknown_key.expected)
82    }
83}
84
85pub(crate) struct UnknownKey<'a> {
86    pub(crate) name: MaybeOwnedStr<'a>,
87    pub(crate) expected: &'static [&'static str],
88}
89
90impl<'a> UnknownKey<'a> {
91    fn new(
92        unknown_key: Option<MaybeOwnedStr<'a>>,
93        expected: &'static [&'static str],
94    ) -> Option<Self> {
95        unknown_key.map(|name| Self { name, expected })
96    }
97}
98
99pub(crate) struct GameModSettingsSeed<'a> {
100    pub(crate) acronym: &'a str,
101    pub(crate) mode: GameMode,
102    pub(crate) deny_unknown_fields: bool,
103}
104
105impl<'de> DeserializeSeed<'de> for GameModSettingsSeed<'_> {
106    type Value = <Self as Visitor<'de>>::Value;
107
108    fn deserialize<D: Deserializer<'de>>(self, d: D) -> Result<Self::Value, D::Error> {
109        d.deserialize_map(self)
110    }
111}
112
113/// Struct to pass parameters into a [`GameMod`] deserialization.
114///
115/// This deserializes an integer as bitflags, a string as an acronym, or a map
116/// as a [`GameMod`] struct.
117///
118/// # Examples
119///
120/// If the [`GameMode`] is available, we can use the `Mode` variant.
121///
122/// ```
123/// use rosu_mods::{GameMod, GameMode, serde::GameModSeed, generated_mods::DifficultyAdjustMania};
124/// use serde::de;
125///
126/// // Note that `GameMod` does not implement `Deserialize` so we must
127/// // implement it manually.
128/// #[derive(serde::Deserialize)]
129/// struct MyStruct(
130///     #[serde(deserialize_with = "custom_deser")]
131///     GameMod
132/// );
133///
134/// // If this is our JSON...
135/// const JSON: &str = r#"{
136///     "mode": 3,
137///     "mod": {
138///         "acronym": "DA",
139///         "settings": {
140///             "drain_rate": 0.73
141///         }
142///     }
143/// }"#;
144///
145/// // ... our deserialization could look like this
146/// fn custom_deser<'de, D: de::Deserializer<'de>>(d: D) -> Result<GameMod, D::Error> {
147///     struct MyVisitor;
148///
149///     impl<'de> de::Visitor<'de> for MyVisitor {
150///         type Value = GameMod;
151///
152///         fn expecting(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
153///             f.write_str("MyStruct")
154///         }
155///
156///         fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
157///         where
158///             A: de::MapAccess<'de>
159///         {
160///             let Some("mode") = map.next_key()? else {
161///                 return Err(de::Error::custom("expected `mode` as first field"));
162///             };
163///             let mode: GameMode = map.next_value()?;
164///             let Some("mod") = map.next_key()? else {
165///                 return Err(de::Error::custom("expected `mod` as second field"));
166///             };
167///
168///             let seed = GameModSeed::Mode { mode, deny_unknown_fields: true }; // <-
169///
170///             map.next_value_seed(seed)
171///         }
172///     }
173///
174///     d.deserialize_map(MyVisitor)
175/// }
176///
177/// let MyStruct(gamemod) = serde_json::from_str(JSON).unwrap();
178///
179/// assert_eq!(
180///     gamemod,
181///     GameMod::DifficultyAdjustMania(DifficultyAdjustMania {
182///         drain_rate: Some(0.73),
183///         ..Default::default()
184///     })
185/// );
186/// ```
187///
188/// If the mode is not available, we can use the `GuessMode` variant.
189///
190/// ```
191/// use rosu_mods::{GameMod, serde::GameModSeed, generated_mods::DifficultyAdjustTaiko};
192/// use serde::de;
193///
194/// #[derive(serde::Deserialize)]
195/// struct MyStruct(
196///     #[serde(deserialize_with = "custom_deser")]
197///     GameMod,
198/// );
199///
200/// // No mode in here so we can only guess
201/// const JSON: &str = r#"{
202///     "acronym": "DA",
203///     "settings": {
204///         "scroll_speed": 0.95
205///     }
206/// }"#;
207///
208/// // For the above JSON, the deserialization will try to use each mode's
209/// // `GameMod` variant for the `DA` acronym.
210/// // First it tries `DifficultyAdjustOsu` but sees that it has no
211/// // `scroll_speed` field so it continues on and succeeds for the taiko
212/// // variant. Note that if `deny_unknown_fields` was set to `false`, the
213/// // unknown `scroll_speed` field would not have caused an error when
214/// // deserializing the `DifficultyAdjustOsu`.
215///
216/// fn custom_deser<'de, D: de::Deserializer<'de>>(d: D) -> Result<GameMod, D::Error> {
217///     d.deserialize_map(GameModSeed::GuessMode { deny_unknown_fields: true })
218/// }
219///
220/// let MyStruct(gamemod) = serde_json::from_str(JSON).unwrap();
221///
222/// assert_eq!(
223///     gamemod,
224///     GameMod::DifficultyAdjustTaiko(DifficultyAdjustTaiko {
225///         scroll_speed: Some(0.95),
226///         ..Default::default()
227///     })
228/// );
229/// ```
230#[derive(Copy, Clone)]
231pub enum GameModSeed {
232    /// Use a specified [`GameMode`] for deserialization.
233    Mode {
234        mode: GameMode,
235        deny_unknown_fields: bool,
236    },
237    /// Try to deserialize for each [`GameMode`] and pick the first one that
238    /// doesn't fail.
239    GuessMode { deny_unknown_fields: bool },
240}
241
242impl GameModSeed {
243    fn convert_acronym(self, acronym: &str) -> GameMod {
244        match self {
245            Self::Mode { mode, .. } => GameMod::new(acronym, mode),
246            Self::GuessMode { .. } => {
247                // False positive from clippy
248                #[allow(clippy::needless_match)]
249                let unknown = match GameMod::new(acronym, GameMode::Osu) {
250                    gamemod @ GameMod::UnknownOsu(_) => gamemod,
251                    gamemod => return gamemod,
252                };
253
254                match GameMod::new(acronym, GameMode::Taiko) {
255                    GameMod::UnknownTaiko(_) => {}
256                    gamemod => return gamemod,
257                }
258
259                match GameMod::new(acronym, GameMode::Catch) {
260                    GameMod::UnknownCatch(_) => {}
261                    gamemod => return gamemod,
262                }
263
264                match GameMod::new(acronym, GameMode::Mania) {
265                    GameMod::UnknownMania(_) => {}
266                    gamemod => return gamemod,
267                }
268
269                unknown
270            }
271        }
272    }
273}
274
275impl<'de> DeserializeSeed<'de> for GameModSeed {
276    type Value = GameMod;
277
278    fn deserialize<D: Deserializer<'de>>(self, d: D) -> Result<Self::Value, D::Error> {
279        d.deserialize_any(self)
280    }
281}
282
283impl<'de> Visitor<'de> for GameModSeed {
284    type Value = GameMod;
285
286    fn expecting(&self, f: &mut Formatter<'_>) -> FmtResult {
287        f.write_str("GameMod")
288    }
289
290    fn visit_str<E: DeError>(self, v: &str) -> Result<Self::Value, E> {
291        Ok(self.convert_acronym(v))
292    }
293
294    fn visit_string<E: DeError>(self, v: String) -> Result<Self::Value, E> {
295        self.visit_str(&v)
296    }
297
298    fn visit_i64<E: DeError>(self, v: i64) -> Result<Self::Value, E> {
299        let Ok(bits) = u32::try_from(v) else {
300            return Err(DeError::custom(BITFLAGS_U32));
301        };
302
303        self.visit_u32(bits)
304    }
305
306    fn visit_u32<E: DeError>(self, v: u32) -> Result<Self::Value, E> {
307        let acronym = GameModIntermode::try_from_bits(v)
308            .ok_or_else(|| DeError::custom(format!("invalid bits value `{v}`")))?
309            .acronym();
310
311        Ok(self.convert_acronym(acronym.as_str()))
312    }
313
314    fn visit_u64<E: DeError>(self, v: u64) -> Result<Self::Value, E> {
315        let Ok(bits) = u32::try_from(v) else {
316            return Err(DeError::custom(BITFLAGS_U32));
317        };
318
319        self.visit_u32(bits)
320    }
321
322    fn visit_map<A: MapAccess<'de>>(self, mut map: A) -> Result<Self::Value, A::Error> {
323        let Some(GameModField::Acronym) = map.next_key()? else {
324            return Err(DeError::custom(EXPECTED_ACRONYM_FIRST));
325        };
326
327        let acronym_raw: MaybeOwnedStr<'de> = map.next_value()?;
328        let acronym = acronym_raw.as_str();
329        let mut gamemod = None;
330
331        while let Some(field) = map.next_key::<GameModField>()? {
332            if field == GameModField::Settings {
333                match self {
334                    Self::Mode {
335                        mode,
336                        deny_unknown_fields,
337                    } => {
338                        let seed = GameModSettingsSeed {
339                            acronym,
340                            mode,
341                            deny_unknown_fields,
342                        };
343                        gamemod = Some(map.next_value_seed(seed)?);
344                    }
345                    Self::GuessMode {
346                        deny_unknown_fields,
347                    } => {
348                        let settings: GameModSettings<'de> = map.next_value()?;
349
350                        gamemod = match settings.try_deserialize(acronym, deny_unknown_fields) {
351                            gamemod @ Some(_) => gamemod,
352                            None => Some(GameMod::UnknownOsu(UnknownMod {
353                                acronym: <Acronym as FromStr>::from_str(acronym)
354                                    .unwrap_or(UnknownMod::UNKNOWN_ACRONYM),
355                            })),
356                        };
357                    }
358                }
359            } else {
360                let _: IgnoredAny = map.next_value()?;
361            }
362        }
363
364        Ok(gamemod.unwrap_or_else(|| self.convert_acronym(acronym)))
365    }
366}
367
368pub(crate) struct GameModSettings<'a> {
369    fields: Vec<GameModSettingField<'a>>,
370}
371
372impl<'a> GameModSettings<'a> {
373    /// Build a [`GameModSettings`] from the owned map stored in a
374    /// [`GameModSimple`].
375    ///
376    /// [`GameModSimple`]: crate::GameModSimple
377    pub(crate) fn from_simple_settings(map: &'a HashMap<Box<str>, SettingSimple>) -> Self {
378        let fields = map
379            .iter()
380            .map(|(key, setting)| {
381                let value = match setting {
382                    SettingSimple::Bool(b) => Value::Bool(*b),
383                    SettingSimple::Number(n) => Value::Number(*n),
384                    SettingSimple::String(s) => Value::Str(MaybeOwnedStr::Borrowed(s)),
385                };
386
387                GameModSettingField {
388                    name: MaybeOwnedStr::Borrowed(key),
389                    value,
390                }
391            })
392            .collect();
393
394        Self { fields }
395    }
396}
397
398impl Debug for GameModSettings<'_> {
399    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
400        Debug::fmt(&self.fields, f)
401    }
402}
403
404impl<'de> Deserialize<'de> for GameModSettings<'de> {
405    fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
406        struct FieldsVisitor;
407
408        impl<'de> Visitor<'de> for FieldsVisitor {
409            type Value = Vec<GameModSettingField<'de>>;
410
411            fn expecting(&self, f: &mut Formatter<'_>) -> FmtResult {
412                f.write_str("GameModSettings")
413            }
414
415            fn visit_map<A: MapAccess<'de>>(self, mut map: A) -> Result<Self::Value, A::Error> {
416                let mut fields = Vec::with_capacity(map.size_hint().unwrap_or(0));
417
418                while let Some((name, value)) = map.next_entry()? {
419                    fields.push(GameModSettingField { name, value });
420                }
421
422                Ok(fields)
423            }
424        }
425
426        Ok(Self {
427            fields: d.deserialize_map(FieldsVisitor)?,
428        })
429    }
430}
431
432#[derive(Debug)]
433pub(crate) struct GameModDeserializeError {
434    msg: Box<str>,
435}
436
437impl Display for GameModDeserializeError {
438    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
439        f.write_str(&self.msg)
440    }
441}
442
443impl StdError for GameModDeserializeError {}
444
445impl DeError for GameModDeserializeError {
446    fn custom<T: Display>(msg: T) -> Self {
447        Self {
448            msg: msg.to_string().into_boxed_str(),
449        }
450    }
451}
452
453impl<'de> Deserializer<'de> for &'de GameModSettings<'_> {
454    type Error = GameModDeserializeError;
455
456    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
457    where
458        V: Visitor<'de>,
459    {
460        self.deserialize_map(visitor)
461    }
462
463    fn deserialize_bool<V>(self, _: V) -> Result<V::Value, Self::Error>
464    where
465        V: Visitor<'de>,
466    {
467        unimplemented!()
468    }
469
470    fn deserialize_i8<V>(self, _: V) -> Result<V::Value, Self::Error>
471    where
472        V: Visitor<'de>,
473    {
474        unimplemented!()
475    }
476
477    fn deserialize_i16<V>(self, _: V) -> Result<V::Value, Self::Error>
478    where
479        V: Visitor<'de>,
480    {
481        unimplemented!()
482    }
483
484    fn deserialize_i32<V>(self, _: V) -> Result<V::Value, Self::Error>
485    where
486        V: Visitor<'de>,
487    {
488        unimplemented!()
489    }
490
491    fn deserialize_i64<V>(self, _: V) -> Result<V::Value, Self::Error>
492    where
493        V: Visitor<'de>,
494    {
495        unimplemented!()
496    }
497
498    fn deserialize_u8<V>(self, _: V) -> Result<V::Value, Self::Error>
499    where
500        V: Visitor<'de>,
501    {
502        unimplemented!()
503    }
504
505    fn deserialize_u16<V>(self, _: V) -> Result<V::Value, Self::Error>
506    where
507        V: Visitor<'de>,
508    {
509        unimplemented!()
510    }
511
512    fn deserialize_u32<V>(self, _: V) -> Result<V::Value, Self::Error>
513    where
514        V: Visitor<'de>,
515    {
516        unimplemented!()
517    }
518
519    fn deserialize_u64<V>(self, _: V) -> Result<V::Value, Self::Error>
520    where
521        V: Visitor<'de>,
522    {
523        unimplemented!()
524    }
525
526    fn deserialize_f32<V>(self, _: V) -> Result<V::Value, Self::Error>
527    where
528        V: Visitor<'de>,
529    {
530        unimplemented!()
531    }
532
533    fn deserialize_f64<V>(self, _: V) -> Result<V::Value, Self::Error>
534    where
535        V: Visitor<'de>,
536    {
537        unimplemented!()
538    }
539
540    fn deserialize_char<V>(self, _: V) -> Result<V::Value, Self::Error>
541    where
542        V: Visitor<'de>,
543    {
544        unimplemented!()
545    }
546
547    fn deserialize_str<V>(self, _: V) -> Result<V::Value, Self::Error>
548    where
549        V: Visitor<'de>,
550    {
551        unimplemented!()
552    }
553
554    fn deserialize_string<V>(self, _: V) -> Result<V::Value, Self::Error>
555    where
556        V: Visitor<'de>,
557    {
558        unimplemented!()
559    }
560
561    fn deserialize_bytes<V>(self, _: V) -> Result<V::Value, Self::Error>
562    where
563        V: Visitor<'de>,
564    {
565        unimplemented!()
566    }
567
568    fn deserialize_byte_buf<V>(self, _: V) -> Result<V::Value, Self::Error>
569    where
570        V: Visitor<'de>,
571    {
572        unimplemented!()
573    }
574
575    fn deserialize_option<V>(self, _: V) -> Result<V::Value, Self::Error>
576    where
577        V: Visitor<'de>,
578    {
579        unimplemented!()
580    }
581
582    fn deserialize_unit<V>(self, _: V) -> Result<V::Value, Self::Error>
583    where
584        V: Visitor<'de>,
585    {
586        unimplemented!()
587    }
588
589    fn deserialize_unit_struct<V>(self, _: &'static str, _: V) -> Result<V::Value, Self::Error>
590    where
591        V: Visitor<'de>,
592    {
593        unimplemented!()
594    }
595
596    fn deserialize_newtype_struct<V>(self, _: &'static str, _: V) -> Result<V::Value, Self::Error>
597    where
598        V: Visitor<'de>,
599    {
600        unimplemented!()
601    }
602
603    fn deserialize_seq<V>(self, _: V) -> Result<V::Value, Self::Error>
604    where
605        V: Visitor<'de>,
606    {
607        unimplemented!()
608    }
609
610    fn deserialize_tuple<V>(self, _: usize, _: V) -> Result<V::Value, Self::Error>
611    where
612        V: Visitor<'de>,
613    {
614        unimplemented!()
615    }
616
617    fn deserialize_tuple_struct<V>(
618        self,
619        _: &'static str,
620        _: usize,
621        _: V,
622    ) -> Result<V::Value, Self::Error>
623    where
624        V: Visitor<'de>,
625    {
626        unimplemented!()
627    }
628
629    fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, Self::Error>
630    where
631        V: Visitor<'de>,
632    {
633        let mut d = GameModSettingsMap {
634            fields: self.fields.iter(),
635            value: None,
636        };
637
638        visitor.visit_map(&mut d)
639    }
640
641    fn deserialize_struct<V>(
642        self,
643        _: &'static str,
644        _: &'static [&'static str],
645        visitor: V,
646    ) -> Result<V::Value, Self::Error>
647    where
648        V: Visitor<'de>,
649    {
650        self.deserialize_map(visitor)
651    }
652
653    fn deserialize_enum<V>(
654        self,
655        _: &'static str,
656        _: &'static [&'static str],
657        _: V,
658    ) -> Result<V::Value, Self::Error>
659    where
660        V: Visitor<'de>,
661    {
662        unimplemented!()
663    }
664
665    fn deserialize_identifier<V>(self, _: V) -> Result<V::Value, Self::Error>
666    where
667        V: Visitor<'de>,
668    {
669        unimplemented!()
670    }
671
672    fn deserialize_ignored_any<V>(self, _: V) -> Result<V::Value, Self::Error>
673    where
674        V: Visitor<'de>,
675    {
676        unimplemented!()
677    }
678}
679
680struct GameModSettingsMap<'de> {
681    fields: slice::Iter<'de, GameModSettingField<'de>>,
682    value: Option<&'de Value<'de>>,
683}
684
685impl<'de> MapAccess<'de> for GameModSettingsMap<'de> {
686    type Error = GameModDeserializeError;
687
688    fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error>
689    where
690        K: DeserializeSeed<'de>,
691    {
692        match self.fields.next() {
693            Some(field) => {
694                self.value = Some(&field.value);
695                let key_de = BorrowedStrDeserializer::new(field.name.as_str());
696
697                seed.deserialize(key_de).map(Some)
698            }
699            None => Ok(None),
700        }
701    }
702
703    fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Self::Error>
704    where
705        V: DeserializeSeed<'de>,
706    {
707        seed.deserialize(self.value.take().unwrap())
708    }
709
710    fn next_entry_seed<K, V>(
711        &mut self,
712        kseed: K,
713        vseed: V,
714    ) -> Result<Option<(K::Value, V::Value)>, Self::Error>
715    where
716        K: DeserializeSeed<'de>,
717        V: DeserializeSeed<'de>,
718    {
719        match self.fields.next() {
720            Some(field) => {
721                self.value.take();
722
723                let key_de = BorrowedStrDeserializer::new(field.name.as_str());
724                let key = kseed.deserialize(key_de)?;
725                let value = vseed.deserialize(&field.value)?;
726
727                Ok(Some((key, value)))
728            }
729            None => Ok(None),
730        }
731    }
732
733    fn size_hint(&self) -> Option<usize> {
734        let (lower, _) = self.fields.size_hint();
735
736        Some(lower)
737    }
738}
739
740struct GameModSettingField<'a> {
741    name: MaybeOwnedStr<'a>,
742    value: Value<'a>,
743}
744
745impl Debug for GameModSettingField<'_> {
746    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
747        f.debug_struct("GameModSettingField")
748            .field("name", &self.name.as_str())
749            .field("value", &self.value)
750            .finish()
751    }
752}
753
754pub(crate) enum Value<'de> {
755    Bool(bool),
756    Str(MaybeOwnedStr<'de>),
757    Number(f64),
758}
759
760impl Debug for Value<'_> {
761    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
762        match self {
763            Value::Bool(b) => Debug::fmt(b, f),
764            Value::Str(s) => Debug::fmt(s, f),
765            Value::Number(n) => Debug::fmt(n, f),
766        }
767    }
768}
769
770impl<'de> Deserialize<'de> for Value<'de> {
771    fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
772        struct ValueVisitor;
773
774        impl<'de> Visitor<'de> for ValueVisitor {
775            type Value = Value<'de>;
776
777            fn expecting(&self, f: &mut Formatter<'_>) -> FmtResult {
778                f.write_str("a bool, string, or number")
779            }
780
781            fn visit_bool<E: DeError>(self, v: bool) -> Result<Self::Value, E> {
782                Ok(Value::Bool(v))
783            }
784
785            fn visit_f32<E: DeError>(self, v: f32) -> Result<Self::Value, E> {
786                self.visit_f64(f64::from(v))
787            }
788
789            fn visit_f64<E: DeError>(self, v: f64) -> Result<Self::Value, E> {
790                Ok(Value::Number(v))
791            }
792
793            fn visit_u64<E: DeError>(self, v: u64) -> Result<Self::Value, E> {
794                self.visit_f64(v as f64)
795            }
796
797            fn visit_i64<E: DeError>(self, v: i64) -> Result<Self::Value, E> {
798                self.visit_f64(v as f64)
799            }
800
801            fn visit_borrowed_str<E: DeError>(self, v: &'de str) -> Result<Self::Value, E> {
802                Ok(Value::Str(MaybeOwnedStr::Borrowed(v)))
803            }
804
805            fn visit_str<E: DeError>(self, v: &str) -> Result<Self::Value, E> {
806                self.visit_string(v.to_owned())
807            }
808
809            fn visit_string<E: DeError>(self, v: String) -> Result<Self::Value, E> {
810                Ok(Value::Str(MaybeOwnedStr::Owned(v)))
811            }
812        }
813
814        d.deserialize_any(ValueVisitor)
815    }
816}
817
818impl<'de> Deserializer<'de> for &'de Value<'_> {
819    type Error = GameModDeserializeError;
820
821    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
822    where
823        V: Visitor<'de>,
824    {
825        match self {
826            Value::Bool(v) => visitor.visit_bool(*v),
827            Value::Number(v) => visitor.visit_f64(*v),
828            Value::Str(v) => visitor.visit_borrowed_str(v.as_str()),
829        }
830    }
831
832    fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Self::Error>
833    where
834        V: Visitor<'de>,
835    {
836        match self {
837            Value::Bool(v) => visitor.visit_bool(*v),
838            Value::Number(v) => Err(DeError::invalid_type(Unexpected::Float(*v), &visitor)),
839            Value::Str(v) => Err(DeError::invalid_type(Unexpected::Str(v.as_str()), &visitor)),
840        }
841    }
842
843    fn deserialize_i8<V>(self, _: V) -> Result<V::Value, Self::Error>
844    where
845        V: Visitor<'de>,
846    {
847        unimplemented!()
848    }
849
850    fn deserialize_i16<V>(self, _: V) -> Result<V::Value, Self::Error>
851    where
852        V: Visitor<'de>,
853    {
854        unimplemented!()
855    }
856
857    fn deserialize_i32<V>(self, _: V) -> Result<V::Value, Self::Error>
858    where
859        V: Visitor<'de>,
860    {
861        unimplemented!()
862    }
863
864    fn deserialize_i64<V>(self, _: V) -> Result<V::Value, Self::Error>
865    where
866        V: Visitor<'de>,
867    {
868        unimplemented!()
869    }
870
871    fn deserialize_u8<V>(self, _: V) -> Result<V::Value, Self::Error>
872    where
873        V: Visitor<'de>,
874    {
875        unimplemented!()
876    }
877
878    fn deserialize_u16<V>(self, _: V) -> Result<V::Value, Self::Error>
879    where
880        V: Visitor<'de>,
881    {
882        unimplemented!()
883    }
884
885    fn deserialize_u32<V>(self, _: V) -> Result<V::Value, Self::Error>
886    where
887        V: Visitor<'de>,
888    {
889        unimplemented!()
890    }
891
892    fn deserialize_u64<V>(self, _: V) -> Result<V::Value, Self::Error>
893    where
894        V: Visitor<'de>,
895    {
896        unimplemented!()
897    }
898
899    fn deserialize_f32<V>(self, _: V) -> Result<V::Value, Self::Error>
900    where
901        V: Visitor<'de>,
902    {
903        unimplemented!()
904    }
905
906    fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
907    where
908        V: Visitor<'de>,
909    {
910        match self {
911            Value::Bool(v) => Err(DeError::invalid_type(Unexpected::Bool(*v), &visitor)),
912            Value::Number(v) => visitor.visit_f64(*v),
913            Value::Str(v) => Err(DeError::invalid_type(Unexpected::Str(v.as_str()), &visitor)),
914        }
915    }
916
917    fn deserialize_char<V>(self, _: V) -> Result<V::Value, Self::Error>
918    where
919        V: Visitor<'de>,
920    {
921        unimplemented!()
922    }
923
924    fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Self::Error>
925    where
926        V: Visitor<'de>,
927    {
928        match self {
929            Value::Bool(v) => Err(DeError::invalid_type(Unexpected::Bool(*v), &visitor)),
930            Value::Number(v) => Err(DeError::invalid_type(Unexpected::Float(*v), &visitor)),
931            Value::Str(v) => visitor.visit_borrowed_str(v.as_str()),
932        }
933    }
934
935    fn deserialize_string<V>(self, visitor: V) -> Result<V::Value, Self::Error>
936    where
937        V: Visitor<'de>,
938    {
939        self.deserialize_str(visitor)
940    }
941
942    fn deserialize_bytes<V>(self, _: V) -> Result<V::Value, Self::Error>
943    where
944        V: Visitor<'de>,
945    {
946        unimplemented!()
947    }
948
949    fn deserialize_byte_buf<V>(self, _: V) -> Result<V::Value, Self::Error>
950    where
951        V: Visitor<'de>,
952    {
953        unimplemented!()
954    }
955
956    fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error>
957    where
958        V: Visitor<'de>,
959    {
960        visitor.visit_some(self)
961    }
962
963    fn deserialize_unit<V>(self, _: V) -> Result<V::Value, Self::Error>
964    where
965        V: Visitor<'de>,
966    {
967        unimplemented!()
968    }
969
970    fn deserialize_unit_struct<V>(self, _: &'static str, _: V) -> Result<V::Value, Self::Error>
971    where
972        V: Visitor<'de>,
973    {
974        unimplemented!()
975    }
976
977    fn deserialize_newtype_struct<V>(self, _: &'static str, _: V) -> Result<V::Value, Self::Error>
978    where
979        V: Visitor<'de>,
980    {
981        unimplemented!()
982    }
983
984    fn deserialize_seq<V>(self, _: V) -> Result<V::Value, Self::Error>
985    where
986        V: Visitor<'de>,
987    {
988        unimplemented!()
989    }
990
991    fn deserialize_tuple<V>(self, _: usize, _: V) -> Result<V::Value, Self::Error>
992    where
993        V: Visitor<'de>,
994    {
995        unimplemented!()
996    }
997
998    fn deserialize_tuple_struct<V>(
999        self,
1000        _: &'static str,
1001        _: usize,
1002        _: V,
1003    ) -> Result<V::Value, Self::Error>
1004    where
1005        V: Visitor<'de>,
1006    {
1007        unimplemented!()
1008    }
1009
1010    fn deserialize_map<V>(self, _: V) -> Result<V::Value, Self::Error>
1011    where
1012        V: Visitor<'de>,
1013    {
1014        unimplemented!()
1015    }
1016
1017    fn deserialize_struct<V>(
1018        self,
1019        _: &'static str,
1020        _: &'static [&'static str],
1021        _: V,
1022    ) -> Result<V::Value, Self::Error>
1023    where
1024        V: Visitor<'de>,
1025    {
1026        unimplemented!()
1027    }
1028
1029    fn deserialize_enum<V>(
1030        self,
1031        _: &'static str,
1032        _: &'static [&'static str],
1033        _: V,
1034    ) -> Result<V::Value, Self::Error>
1035    where
1036        V: Visitor<'de>,
1037    {
1038        unimplemented!()
1039    }
1040
1041    fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value, Self::Error>
1042    where
1043        V: Visitor<'de>,
1044    {
1045        self.deserialize_str(visitor)
1046    }
1047
1048    fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
1049    where
1050        V: Visitor<'de>,
1051    {
1052        visitor.visit_unit()
1053    }
1054}
1055
1056/// Struct to pass parameters into a [`GameMods`] deserialization.
1057///
1058/// This deserializes an integer as bitflags, a string as acronyms, or a
1059/// sequence of [`GameMod`] data.
1060///
1061/// # Example
1062///
1063/// Let's define deserialization so that each contained [`GameMod`] should
1064/// belong to the same (guessed) [`GameMode`].
1065///
1066/// ```
1067/// use rosu_mods::{
1068///     generated_mods::{NoScopeCatch, UnknownMod},
1069///     serde::GameModsSeed,
1070///     Acronym, GameMod, GameMods,
1071/// };
1072/// use serde::de;
1073/// # use std::str::FromStr;
1074///
1075/// #[derive(serde::Deserialize)]
1076/// struct MyStruct(#[serde(deserialize_with = "custom_deser")] GameMods);
1077///
1078/// // A JSON sequence containing bitflags of mania's `FadeIn` mod, the
1079/// // `FloatingFruits` acronym, and `NoScope` data.
1080/// const JSON: &str = r#"[
1081///     1048576,
1082///     "FF",
1083///     {
1084///         "acronym": "NS",
1085///         "settings": {
1086///             "hidden_combo_count": 5
1087///         }
1088///     }
1089/// ]"#;
1090///
1091/// fn custom_deser<'de, D: de::Deserializer<'de>>(d: D) -> Result<GameMods, D::Error> {
1092///     // Here, we're defining that all deserialized mods should belong to the
1093///     // same mode.
1094///     d.deserialize_any(GameModsSeed::SameModeForEachMod { deny_unknown_fields: true })
1095/// }
1096///
1097/// // Although `FI` is not a `Catch` mod, the mode still has the most
1098/// // successfully deserialized mods (2) so that's the one that will be
1099/// // chosen.
1100///
1101/// let MyStruct(mods) = serde_json::from_str(JSON).unwrap();
1102/// let mut iter = mods.into_iter();
1103///
1104/// // The following order of mods is irrelevant here. The iterator just shows
1105/// // which mods are contained.
1106///
1107/// // `FF` was only specified as acronym so it only contains default values.
1108/// assert_eq!(
1109///     iter.next(),
1110///     Some(GameMod::FloatingFruitsCatch(Default::default()))
1111/// );
1112///
1113/// // For `NS` we did deserialize a field
1114/// assert_eq!(
1115///     iter.next(),
1116///     Some(GameMod::NoScopeCatch(NoScopeCatch {
1117///         hidden_combo_count: Some(5.0)
1118///     }))
1119/// );
1120///
1121/// // `FI` is not a `Catch` mod so it's deserialized as `UnknownCatch`
1122/// assert_eq!(
1123///     iter.next(),
1124///     Some(GameMod::UnknownCatch(UnknownMod {
1125///         acronym: Acronym::from_str("FI").unwrap()
1126///     }))
1127/// );
1128///
1129/// assert_eq!(iter.next(), None);
1130/// ```
1131///
1132/// Next, let's define deserialization so that each contained [`GameMod`]
1133/// picks the first [`GameMode`] that deserializes successfully.
1134///
1135/// ```
1136/// use rosu_mods::{serde::GameModsSeed, GameMod, GameMods};
1137/// use serde::de;
1138///
1139/// #[derive(serde::Deserialize)]
1140/// struct MyStruct(#[serde(deserialize_with = "custom_deser")] GameMods);
1141///
1142/// // The bitflags for `DT` and `FI`
1143/// const JSON: &str = "1048640";
1144///
1145/// fn custom_deser<'de, D: de::Deserializer<'de>>(d: D) -> Result<GameMods, D::Error> {
1146///     d.deserialize_any(GameModsSeed::AllowMultipleModes { deny_unknown_fields: true })
1147/// }
1148///
1149/// let MyStruct(mods) = serde_json::from_str(JSON).unwrap();
1150/// let mut iter = mods.into_iter();
1151///
1152/// // `Osu` is the first mode that successfully deserializes `DT`.
1153/// assert_eq!(
1154///     iter.next(),
1155///     Some(GameMod::DoubleTimeOsu(Default::default()))
1156/// );
1157///
1158/// // `FI` is only deserialized properly for `Mania`
1159/// assert_eq!(
1160///     iter.next(),
1161///     Some(GameMod::FadeInMania(Default::default()))
1162/// );
1163///
1164/// assert_eq!(iter.next(), None);
1165/// ```
1166#[derive(Copy, Clone)]
1167pub enum GameModsSeed {
1168    /// Use a specified [`GameMode`] for deserialization.
1169    Mode {
1170        mode: GameMode,
1171        deny_unknown_fields: bool,
1172    },
1173    /// For each contained [`GameMod`], try to deserialize it for each
1174    /// [`GameMode`] and pick the first one that doesn't fail.
1175    AllowMultipleModes { deny_unknown_fields: bool },
1176    /// For each [`GameMode`], deserialize each [`GameMod`] for that mode and
1177    /// pick the first one for which each [`GameMod`] succeeds deserialization
1178    /// or alternatively the mode with the least amount of unknown mods.
1179    SameModeForEachMod { deny_unknown_fields: bool },
1180}
1181
1182impl GameModsSeed {
1183    fn convert_intermode(self, intermode: &GameModsIntermode) -> GameMods {
1184        match self {
1185            Self::Mode { mode, .. } => intermode.with_mode(mode),
1186            Self::SameModeForEachMod { .. } => {
1187                for mode in MODES {
1188                    if let Some(mods) = intermode.try_with_mode(mode) {
1189                        return mods;
1190                    }
1191                }
1192
1193                intermode.with_mode(GameMode::Osu)
1194            }
1195            Self::AllowMultipleModes { .. } => intermode
1196                .iter()
1197                .map(|gamemod| {
1198                    let [osu, modes @ ..] = MODES;
1199                    let osu = GameMod::new(gamemod.acronym().as_str(), osu);
1200
1201                    if !matches!(osu, GameMod::UnknownOsu(_)) {
1202                        return osu;
1203                    }
1204
1205                    for mode in modes {
1206                        match GameMod::new(gamemod.acronym().as_str(), mode) {
1207                            GameMod::UnknownTaiko(_)
1208                            | GameMod::UnknownCatch(_)
1209                            | GameMod::UnknownMania(_) => {}
1210                            gamemod => return gamemod,
1211                        }
1212                    }
1213
1214                    osu
1215                })
1216                .collect(),
1217        }
1218    }
1219}
1220
1221impl<'de> DeserializeSeed<'de> for GameModsSeed {
1222    type Value = GameMods;
1223
1224    fn deserialize<D: Deserializer<'de>>(self, d: D) -> Result<Self::Value, D::Error> {
1225        d.deserialize_any(self)
1226    }
1227}
1228
1229impl<'de> Visitor<'de> for GameModsSeed {
1230    type Value = GameMods;
1231
1232    fn expecting(&self, f: &mut Formatter<'_>) -> FmtResult {
1233        f.write_str("GameMods")
1234    }
1235
1236    fn visit_str<E: DeError>(self, v: &str) -> Result<Self::Value, E> {
1237        let intermode = v.parse::<GameModsIntermode>().map_err(DeError::custom)?;
1238
1239        Ok(self.convert_intermode(&intermode))
1240    }
1241
1242    fn visit_string<E: DeError>(self, v: String) -> Result<Self::Value, E> {
1243        self.visit_str(&v)
1244    }
1245
1246    fn visit_i64<E: DeError>(self, v: i64) -> Result<Self::Value, E> {
1247        let Ok(bits) = u32::try_from(v) else {
1248            return Err(DeError::custom(BITFLAGS_U32));
1249        };
1250
1251        self.visit_u32(bits)
1252    }
1253
1254    fn visit_u32<E: DeError>(self, v: u32) -> Result<Self::Value, E> {
1255        let intermode = GameModsIntermode::from_bits(v);
1256
1257        Ok(self.convert_intermode(&intermode))
1258    }
1259
1260    fn visit_u64<E: DeError>(self, v: u64) -> Result<Self::Value, E> {
1261        let Ok(bits) = u32::try_from(v) else {
1262            return Err(DeError::custom(BITFLAGS_U32));
1263        };
1264
1265        self.visit_u32(bits)
1266    }
1267
1268    fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
1269        let mut inner = BTreeMap::new();
1270
1271        let seed = match self {
1272            Self::Mode {
1273                mode,
1274                deny_unknown_fields,
1275            } => GameModSeed::Mode {
1276                mode,
1277                deny_unknown_fields,
1278            },
1279            Self::AllowMultipleModes {
1280                deny_unknown_fields,
1281            } => GameModSeed::GuessMode {
1282                deny_unknown_fields,
1283            },
1284            Self::SameModeForEachMod {
1285                deny_unknown_fields,
1286            } => {
1287                let mut mods_raw = Vec::new();
1288
1289                let seed = GameModRawSeed {
1290                    deny_unknown_fields,
1291                };
1292
1293                while let Some(gamemod) = seq.next_element_seed(seed)? {
1294                    mods_raw.push(gamemod);
1295                }
1296
1297                return GameModRaw::convert_slice::<A::Error>(&mods_raw);
1298            }
1299        };
1300
1301        while let Some(gamemod) = seq.next_element_seed(seed)? {
1302            inner.insert(GameModOrder::from(&gamemod), gamemod);
1303        }
1304
1305        Ok(GameMods { inner })
1306    }
1307
1308    fn visit_map<A: MapAccess<'de>>(self, map: A) -> Result<Self::Value, A::Error> {
1309        let seed = match self {
1310            Self::Mode {
1311                mode,
1312                deny_unknown_fields,
1313            } => GameModSeed::Mode {
1314                mode,
1315                deny_unknown_fields,
1316            },
1317            Self::AllowMultipleModes {
1318                deny_unknown_fields,
1319            }
1320            | Self::SameModeForEachMod {
1321                deny_unknown_fields,
1322            } => GameModSeed::GuessMode {
1323                deny_unknown_fields,
1324            },
1325        };
1326
1327        let gamemod = seed.visit_map(map)?;
1328
1329        let mut mods = GameMods::new();
1330        mods.insert(gamemod);
1331
1332        Ok(mods)
1333    }
1334}
1335
1336pub(crate) enum GameModRaw<'a> {
1337    Bits(u32),
1338    Acronym(MaybeOwnedStr<'a>),
1339    Full {
1340        acronym: MaybeOwnedStr<'a>,
1341        settings: GameModSettings<'a>,
1342        deny_unknown_fields: bool,
1343    },
1344}
1345
1346impl Debug for GameModRaw<'_> {
1347    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
1348        match self {
1349            Self::Bits(bits) => write!(f, "{bits}"),
1350            Self::Acronym(acronym) => Debug::fmt(acronym, f),
1351            Self::Full {
1352                acronym, settings, ..
1353            } => f
1354                .debug_struct("GameMod")
1355                .field("acronym", &acronym.as_str())
1356                .field("settings", settings)
1357                .finish(),
1358        }
1359    }
1360}
1361
1362impl GameModRaw<'_> {
1363    fn convert_slice<E: DeError>(mods_raw: &[Self]) -> Result<GameMods, E> {
1364        // Collect raw mods for each mode and see which one has the most known
1365        // mods.
1366        let mut inner = BTreeMap::new();
1367        let mut best_known_count = 0;
1368
1369        'modes: for mode in MODES {
1370            let mut mods = BTreeMap::new();
1371
1372            for mod_raw in mods_raw.iter() {
1373                let Ok(gamemod) = mod_raw.try_convert::<E>(mode) else {
1374                    continue 'modes;
1375                };
1376
1377                mods.insert(GameModOrder::from(&gamemod), gamemod);
1378            }
1379
1380            let known_count = mods
1381                .values()
1382                .filter(|gamemod| {
1383                    !matches!(
1384                        gamemod,
1385                        GameMod::UnknownOsu(_)
1386                            | GameMod::UnknownTaiko(_)
1387                            | GameMod::UnknownCatch(_)
1388                            | GameMod::UnknownMania(_)
1389                    )
1390                })
1391                .count();
1392
1393            if known_count == mods_raw.len() {
1394                return Ok(GameMods { inner: mods });
1395            } else if known_count > best_known_count {
1396                best_known_count = known_count;
1397                inner = mods;
1398            }
1399        }
1400
1401        if best_known_count > 0 || mods_raw.is_empty() {
1402            Ok(GameMods { inner })
1403        } else {
1404            Err(E::custom(format!(
1405                "all modes failed to deserialize mods {mods_raw:?}"
1406            )))
1407        }
1408    }
1409
1410    fn try_convert<E: DeError>(&self, mode: GameMode) -> Result<GameMod, E> {
1411        match self {
1412            GameModRaw::Bits(bits) => GameModIntermode::try_from_bits(*bits)
1413                .ok_or_else(|| DeError::custom(format!("invalid bits value `{bits}`")))
1414                .map(|intermode| GameMod::new(intermode.acronym().as_str(), mode)),
1415            GameModRaw::Acronym(acronym) => Ok(GameMod::new(acronym.as_str(), mode)),
1416            GameModRaw::Full {
1417                acronym,
1418                settings,
1419                deny_unknown_fields,
1420            } => GameModSettingsSeed {
1421                acronym: acronym.as_str(),
1422                mode,
1423                deny_unknown_fields: *deny_unknown_fields,
1424            }
1425            .deserialize(settings)
1426            .map_err(DeError::custom),
1427        }
1428    }
1429}
1430
1431#[derive(Copy, Clone)]
1432pub(crate) struct GameModRawSeed {
1433    pub(crate) deny_unknown_fields: bool,
1434}
1435
1436impl<'de> DeserializeSeed<'de> for GameModRawSeed {
1437    type Value = GameModRaw<'de>;
1438
1439    fn deserialize<D: Deserializer<'de>>(self, d: D) -> Result<Self::Value, D::Error> {
1440        d.deserialize_any(self)
1441    }
1442}
1443
1444impl<'de> Visitor<'de> for GameModRawSeed {
1445    type Value = GameModRaw<'de>;
1446
1447    fn expecting(&self, f: &mut Formatter<'_>) -> FmtResult {
1448        f.write_str("GameMod")
1449    }
1450
1451    fn visit_i64<E: DeError>(self, v: i64) -> Result<Self::Value, E> {
1452        let bits = u32::try_from(v).map_err(|_| DeError::custom(BITFLAGS_U32))?;
1453
1454        self.visit_u32(bits)
1455    }
1456
1457    fn visit_u32<E: DeError>(self, v: u32) -> Result<Self::Value, E> {
1458        Ok(GameModRaw::Bits(v))
1459    }
1460
1461    fn visit_u64<E: DeError>(self, v: u64) -> Result<Self::Value, E> {
1462        let bits = u32::try_from(v).map_err(|_| DeError::custom(BITFLAGS_U32))?;
1463
1464        self.visit_u32(bits)
1465    }
1466
1467    fn visit_borrowed_str<E: DeError>(self, v: &'de str) -> Result<Self::Value, E> {
1468        Ok(GameModRaw::Acronym(MaybeOwnedStr::Borrowed(v)))
1469    }
1470
1471    fn visit_str<E: DeError>(self, v: &str) -> Result<Self::Value, E> {
1472        self.visit_string(v.to_owned())
1473    }
1474
1475    fn visit_string<E: DeError>(self, v: String) -> Result<Self::Value, E> {
1476        Ok(GameModRaw::Acronym(MaybeOwnedStr::Owned(v)))
1477    }
1478
1479    fn visit_map<A: MapAccess<'de>>(self, mut map: A) -> Result<Self::Value, A::Error> {
1480        let Some(GameModField::Acronym) = map.next_key()? else {
1481            return Err(DeError::custom(EXPECTED_ACRONYM_FIRST));
1482        };
1483
1484        let acronym: MaybeOwnedStr<'de> = map.next_value()?;
1485
1486        loop {
1487            match map.next_key::<GameModField>()? {
1488                Some(GameModField::Settings) => {
1489                    let settings: GameModSettings<'de> = map.next_value()?;
1490
1491                    while map.next_entry::<GameModField, IgnoredAny>()?.is_some() {}
1492
1493                    return Ok(GameModRaw::Full {
1494                        acronym,
1495                        settings,
1496                        deny_unknown_fields: self.deny_unknown_fields,
1497                    });
1498                }
1499                Some(_) => {
1500                    let _: IgnoredAny = map.next_value()?;
1501                }
1502                None => return Ok(GameModRaw::Acronym(acronym)),
1503            }
1504        }
1505    }
1506}
1507
1508#[derive(Copy, Clone, PartialEq, Eq)]
1509enum GameModField {
1510    Acronym,
1511    Settings,
1512    Other,
1513}
1514
1515impl<'de> Deserialize<'de> for GameModField {
1516    fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
1517        struct GameModFieldVisitor;
1518
1519        impl Visitor<'_> for GameModFieldVisitor {
1520            type Value = GameModField;
1521
1522            fn expecting(&self, f: &mut Formatter<'_>) -> FmtResult {
1523                f.write_str("identifier")
1524            }
1525
1526            fn visit_str<E: DeError>(self, v: &str) -> Result<Self::Value, E> {
1527                let field = match v {
1528                    "acronym" => GameModField::Acronym,
1529                    "settings" => GameModField::Settings,
1530                    _ => GameModField::Other,
1531                };
1532
1533                Ok(field)
1534            }
1535
1536            fn visit_string<E: DeError>(self, v: String) -> Result<Self::Value, E> {
1537                self.visit_str(&v)
1538            }
1539        }
1540
1541        d.deserialize_identifier(GameModFieldVisitor)
1542    }
1543}
1544
1545pub(crate) enum MaybeOwnedStr<'a> {
1546    Borrowed(&'a str),
1547    Owned(String),
1548}
1549
1550impl Debug for MaybeOwnedStr<'_> {
1551    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
1552        match self {
1553            Self::Borrowed(s) => Debug::fmt(s, f),
1554            Self::Owned(s) => Debug::fmt(s, f),
1555        }
1556    }
1557}
1558
1559impl MaybeOwnedStr<'_> {
1560    pub(crate) const fn as_str(&self) -> &str {
1561        match self {
1562            MaybeOwnedStr::Borrowed(a) => a,
1563            MaybeOwnedStr::Owned(a) => a.as_str(),
1564        }
1565    }
1566
1567    pub(crate) fn into_owned(self) -> String {
1568        match self {
1569            MaybeOwnedStr::Borrowed(s) => s.to_owned(),
1570            MaybeOwnedStr::Owned(s) => s,
1571        }
1572    }
1573}
1574
1575impl<'de> Deserialize<'de> for MaybeOwnedStr<'de> {
1576    fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
1577        struct AcronymRawVisitor;
1578
1579        impl<'de> Visitor<'de> for AcronymRawVisitor {
1580            type Value = MaybeOwnedStr<'de>;
1581
1582            fn expecting(&self, f: &mut Formatter<'_>) -> FmtResult {
1583                f.write_str("string")
1584            }
1585
1586            fn visit_borrowed_str<E: DeError>(self, v: &'de str) -> Result<Self::Value, E> {
1587                Ok(MaybeOwnedStr::Borrowed(v))
1588            }
1589
1590            fn visit_str<E: DeError>(self, v: &str) -> Result<Self::Value, E> {
1591                self.visit_string(v.to_owned())
1592            }
1593
1594            fn visit_string<E: DeError>(self, v: String) -> Result<Self::Value, E> {
1595                Ok(MaybeOwnedStr::Owned(v))
1596            }
1597        }
1598
1599        d.deserialize_str(AcronymRawVisitor)
1600    }
1601}
1602
1603#[cfg(test)]
1604mod tests {
1605    use serde_json::Deserializer;
1606
1607    use crate::generated_mods::{
1608        AccuracyChallengeOsu, AccuracyChallengeTaiko, DifficultyAdjustTaiko,
1609    };
1610
1611    use super::*;
1612
1613    #[test]
1614    fn deser_mod_bits() {
1615        let json = "64";
1616
1617        let mut d = Deserializer::from_str(json);
1618        let osu_dt = GameModSeed::GuessMode {
1619            deny_unknown_fields: true,
1620        }
1621        .deserialize(&mut d)
1622        .unwrap();
1623        assert_eq!(osu_dt, GameMod::DoubleTimeOsu(Default::default()));
1624
1625        let mut d = Deserializer::from_str(json);
1626        let taiko_dt = GameModSeed::Mode {
1627            mode: GameMode::Taiko,
1628            deny_unknown_fields: true,
1629        }
1630        .deserialize(&mut d)
1631        .unwrap();
1632        assert_eq!(taiko_dt, GameMod::DoubleTimeTaiko(Default::default()));
1633    }
1634
1635    #[test]
1636    fn deser_mod_bits_fail() {
1637        let json = "2147483648";
1638
1639        let mut d = Deserializer::from_str(json);
1640        let err = GameModSeed::GuessMode {
1641            deny_unknown_fields: true,
1642        }
1643        .deserialize(&mut d);
1644        assert!(err.is_err());
1645
1646        let mut d = Deserializer::from_str(json);
1647        let err = GameModSeed::Mode {
1648            mode: GameMode::Mania,
1649            deny_unknown_fields: true,
1650        }
1651        .deserialize(&mut d);
1652        assert!(err.is_err());
1653    }
1654
1655    #[test]
1656    fn deser_mod_acronym() {
1657        let json = r#""AS""#;
1658
1659        let mut d = Deserializer::from_str(json);
1660        let osu_as = GameModSeed::GuessMode {
1661            deny_unknown_fields: true,
1662        }
1663        .deserialize(&mut d)
1664        .unwrap();
1665        assert_eq!(osu_as, GameMod::AdaptiveSpeedOsu(Default::default()));
1666
1667        let mut d = Deserializer::from_str(json);
1668        let taiko_as = GameModSeed::Mode {
1669            mode: GameMode::Taiko,
1670            deny_unknown_fields: true,
1671        }
1672        .deserialize(&mut d)
1673        .unwrap();
1674        assert_eq!(taiko_as, GameMod::AdaptiveSpeedTaiko(Default::default()));
1675
1676        let mut d = Deserializer::from_str(json);
1677        let catch_unknown = GameModSeed::Mode {
1678            mode: GameMode::Catch,
1679            deny_unknown_fields: true,
1680        }
1681        .deserialize(&mut d)
1682        .unwrap();
1683        assert_eq!(
1684            catch_unknown,
1685            GameMod::UnknownCatch(UnknownMod {
1686                acronym: "AS".parse().unwrap()
1687            })
1688        );
1689    }
1690
1691    #[test]
1692    fn deser_mod_data() {
1693        let json = r#"{
1694            "acronym": "AC",
1695            "settings": {
1696                "minimum_accuracy": 12.34,
1697                "accuracy_judge_mode": "my string",
1698                "restart": false
1699            }
1700        }"#;
1701
1702        let mut d = Deserializer::from_str(json);
1703        let osu_ac = GameModSeed::GuessMode {
1704            deny_unknown_fields: true,
1705        }
1706        .deserialize(&mut d)
1707        .unwrap();
1708        assert_eq!(
1709            osu_ac,
1710            GameMod::AccuracyChallengeOsu(AccuracyChallengeOsu {
1711                minimum_accuracy: Some(12.34),
1712                accuracy_judge_mode: Some(String::from("my string")),
1713                restart: Some(false),
1714            })
1715        );
1716
1717        let mut d = Deserializer::from_str(json);
1718        let taiko_ac = GameModSeed::Mode {
1719            mode: GameMode::Taiko,
1720            deny_unknown_fields: true,
1721        }
1722        .deserialize(&mut d)
1723        .unwrap();
1724        assert_eq!(
1725            taiko_ac,
1726            GameMod::AccuracyChallengeTaiko(AccuracyChallengeTaiko {
1727                minimum_accuracy: Some(12.34),
1728                accuracy_judge_mode: Some(String::from("my string")),
1729                restart: Some(false),
1730            })
1731        );
1732    }
1733
1734    #[test]
1735    fn deser_mod_data_unknown_field() {
1736        let json = r#"{
1737            "acronym": "HD",
1738            "settings": {
1739                "unknown_field": true
1740            }
1741        }"#;
1742
1743        let mut d = Deserializer::from_str(json);
1744        let unknown_osu = GameModSeed::GuessMode {
1745            deny_unknown_fields: true,
1746        }
1747        .deserialize(&mut d)
1748        .unwrap();
1749        assert_eq!(
1750            unknown_osu,
1751            GameMod::UnknownOsu(UnknownMod {
1752                acronym: Acronym::from_str("HD").unwrap()
1753            })
1754        );
1755
1756        let mut d = Deserializer::from_str(json);
1757        let osu_hd = GameModSeed::GuessMode {
1758            deny_unknown_fields: false,
1759        }
1760        .deserialize(&mut d)
1761        .unwrap();
1762        assert_eq!(osu_hd, GameMod::HiddenOsu(Default::default()));
1763
1764        let mut d = Deserializer::from_str(json);
1765        let err = GameModSeed::Mode {
1766            mode: GameMode::Catch,
1767            deny_unknown_fields: true,
1768        }
1769        .deserialize(&mut d);
1770        assert!(err.is_err());
1771
1772        let mut d = Deserializer::from_str(json);
1773        let hd_catch = GameModSeed::Mode {
1774            mode: GameMode::Catch,
1775            deny_unknown_fields: false,
1776        }
1777        .deserialize(&mut d)
1778        .unwrap();
1779        assert_eq!(hd_catch, GameMod::HiddenCatch(Default::default()));
1780    }
1781
1782    #[test]
1783    fn deser_mod_data_invalid_type() {
1784        let json = r#"{
1785            "acronym": "DT",
1786            "settings": {
1787                "speed_change": "should be number; not string",
1788            }
1789        }"#;
1790
1791        let mut d = Deserializer::from_str(json);
1792        let err = GameModSeed::GuessMode {
1793            deny_unknown_fields: true,
1794        }
1795        .deserialize(&mut d);
1796        assert!(err.is_err());
1797
1798        let mut d = Deserializer::from_str(json);
1799        let err = GameModSeed::Mode {
1800            mode: GameMode::Catch,
1801            deny_unknown_fields: true,
1802        }
1803        .deserialize(&mut d);
1804        assert!(err.is_err());
1805    }
1806
1807    #[test]
1808    fn deser_mods_bits() {
1809        let json = "1048584";
1810
1811        let mut d = Deserializer::from_str(json);
1812        let mania_hdfi = GameModsSeed::SameModeForEachMod {
1813            deny_unknown_fields: true,
1814        }
1815        .deserialize(&mut d)
1816        .unwrap();
1817        let mut expected = GameMods::new();
1818        expected.insert(GameMod::HiddenMania(Default::default()));
1819        expected.insert(GameMod::FadeInMania(Default::default()));
1820        assert_eq!(mania_hdfi, expected);
1821
1822        let mut d = Deserializer::from_str(json);
1823        let osu_hd_mania_fi = GameModsSeed::AllowMultipleModes {
1824            deny_unknown_fields: true,
1825        }
1826        .deserialize(&mut d)
1827        .unwrap();
1828        let mut expected = GameMods::new();
1829        expected.insert(GameMod::HiddenOsu(Default::default()));
1830        expected.insert(GameMod::FadeInMania(Default::default()));
1831        assert_eq!(osu_hd_mania_fi, expected);
1832
1833        let mut d = Deserializer::from_str(json);
1834        let osu_hdfi = GameModsSeed::Mode {
1835            mode: GameMode::Osu,
1836            deny_unknown_fields: true,
1837        }
1838        .deserialize(&mut d)
1839        .unwrap();
1840        let mut expected = GameMods::new();
1841        expected.insert(GameMod::HiddenOsu(Default::default()));
1842        expected.insert(GameMod::UnknownOsu(UnknownMod {
1843            acronym: "FI".parse().unwrap(),
1844        }));
1845        assert_eq!(osu_hdfi, expected);
1846    }
1847
1848    #[test]
1849    fn deser_mods_unknown_bits() {
1850        let json = "2147483648";
1851
1852        let mut d = Deserializer::from_str(json);
1853        let mods = GameModsSeed::SameModeForEachMod {
1854            deny_unknown_fields: true,
1855        }
1856        .deserialize(&mut d)
1857        .unwrap();
1858        assert_eq!(mods.len(), 0);
1859
1860        let mut d = Deserializer::from_str(json);
1861        let mods = GameModsSeed::AllowMultipleModes {
1862            deny_unknown_fields: true,
1863        }
1864        .deserialize(&mut d)
1865        .unwrap();
1866        assert_eq!(mods.len(), 0);
1867
1868        let mut d = Deserializer::from_str(json);
1869        let mods = GameModsSeed::Mode {
1870            mode: GameMode::Mania,
1871            deny_unknown_fields: true,
1872        }
1873        .deserialize(&mut d)
1874        .unwrap();
1875        assert_eq!(mods.len(), 0);
1876    }
1877
1878    #[test]
1879    fn deser_mods_acronyms() {
1880        let json = r#""HDFI""#;
1881
1882        let mut d = Deserializer::from_str(json);
1883        let mania_hdfi = GameModsSeed::SameModeForEachMod {
1884            deny_unknown_fields: true,
1885        }
1886        .deserialize(&mut d)
1887        .unwrap();
1888        let mut expected = GameMods::new();
1889        expected.insert(GameMod::HiddenMania(Default::default()));
1890        expected.insert(GameMod::FadeInMania(Default::default()));
1891        assert_eq!(mania_hdfi, expected);
1892
1893        let mut d = Deserializer::from_str(json);
1894        let osu_hd_mania_fi = GameModsSeed::AllowMultipleModes {
1895            deny_unknown_fields: true,
1896        }
1897        .deserialize(&mut d)
1898        .unwrap();
1899        let mut expected = GameMods::new();
1900        expected.insert(GameMod::HiddenOsu(Default::default()));
1901        expected.insert(GameMod::FadeInMania(Default::default()));
1902        assert_eq!(osu_hd_mania_fi, expected);
1903
1904        let mut d = Deserializer::from_str(json);
1905        let osu_hdfi = GameModsSeed::Mode {
1906            mode: GameMode::Osu,
1907            deny_unknown_fields: true,
1908        }
1909        .deserialize(&mut d)
1910        .unwrap();
1911        let mut expected = GameMods::new();
1912        expected.insert(GameMod::HiddenOsu(Default::default()));
1913        expected.insert(GameMod::UnknownOsu(UnknownMod {
1914            acronym: "FI".parse().unwrap(),
1915        }));
1916        assert_eq!(osu_hdfi, expected);
1917    }
1918
1919    #[test]
1920    fn deser_mods_data() {
1921        let json = r#"[
1922            8,
1923            "FF",
1924            {
1925                "acronym": "WG"
1926            },
1927            {
1928                "acronym": "AC",
1929                "settings": {
1930                    "minimum_accuracy": 12.34,
1931                    "accuracy_judge_mode": "my string",
1932                    "restart": false
1933                }
1934            }
1935        ]"#;
1936
1937        let mut d = Deserializer::from_str(json);
1938        let mods = GameModsSeed::SameModeForEachMod {
1939            deny_unknown_fields: true,
1940        }
1941        .deserialize(&mut d)
1942        .unwrap();
1943        let mut expected = GameMods::new();
1944        expected.insert(GameMod::HiddenOsu(Default::default()));
1945        expected.insert(GameMod::UnknownOsu(UnknownMod {
1946            acronym: "FF".parse().unwrap(),
1947        }));
1948        expected.insert(GameMod::WiggleOsu(Default::default()));
1949        expected.insert(GameMod::AccuracyChallengeOsu(AccuracyChallengeOsu {
1950            minimum_accuracy: Some(12.34),
1951            accuracy_judge_mode: Some(String::from("my string")),
1952            restart: Some(false),
1953        }));
1954        assert_eq!(mods, expected);
1955
1956        let mut d = Deserializer::from_str(json);
1957        let mods = GameModsSeed::AllowMultipleModes {
1958            deny_unknown_fields: true,
1959        }
1960        .deserialize(&mut d)
1961        .unwrap();
1962        let mut expected = GameMods::new();
1963        expected.insert(GameMod::HiddenOsu(Default::default()));
1964        expected.insert(GameMod::FloatingFruitsCatch(Default::default()));
1965        expected.insert(GameMod::WiggleOsu(Default::default()));
1966        expected.insert(GameMod::AccuracyChallengeOsu(AccuracyChallengeOsu {
1967            minimum_accuracy: Some(12.34),
1968            accuracy_judge_mode: Some(String::from("my string")),
1969            restart: Some(false),
1970        }));
1971        assert_eq!(mods, expected);
1972
1973        let mut d = Deserializer::from_str(json);
1974        let mods = GameModsSeed::Mode {
1975            mode: GameMode::Taiko,
1976            deny_unknown_fields: true,
1977        }
1978        .deserialize(&mut d)
1979        .unwrap();
1980        let mut expected = GameMods::new();
1981        expected.insert(GameMod::HiddenTaiko(Default::default()));
1982        expected.insert(GameMod::UnknownTaiko(UnknownMod {
1983            acronym: "FF".parse().unwrap(),
1984        }));
1985        expected.insert(GameMod::UnknownTaiko(UnknownMod {
1986            acronym: "WG".parse().unwrap(),
1987        }));
1988        expected.insert(GameMod::AccuracyChallengeTaiko(AccuracyChallengeTaiko {
1989            minimum_accuracy: Some(12.34),
1990            accuracy_judge_mode: Some(String::from("my string")),
1991            restart: Some(false),
1992        }));
1993        assert_eq!(mods, expected);
1994    }
1995
1996    #[test]
1997    fn deser_mods_single_data() {
1998        let json = r#"{
1999            "acronym": "FI"
2000        }"#;
2001
2002        let mut d = Deserializer::from_str(json);
2003        let mods = GameModsSeed::AllowMultipleModes {
2004            deny_unknown_fields: true,
2005        }
2006        .deserialize(&mut d)
2007        .unwrap();
2008        let mut expected = GameMods::new();
2009        expected.insert(GameMod::FadeInMania(Default::default()));
2010        assert_eq!(mods, expected);
2011
2012        let mut d = Deserializer::from_str(json);
2013        let mods = GameModsSeed::Mode {
2014            mode: GameMode::Taiko,
2015            deny_unknown_fields: true,
2016        }
2017        .deserialize(&mut d)
2018        .unwrap();
2019        let mut expected = GameMods::new();
2020        expected.insert(GameMod::UnknownTaiko(UnknownMod {
2021            acronym: "FI".parse().unwrap(),
2022        }));
2023        assert_eq!(mods, expected);
2024    }
2025
2026    #[test]
2027    fn deser_mods_data_unknown_fields() {
2028        let json = r#"[
2029            {
2030                "acronym": "DA",
2031                "settings": {
2032                    "scroll_speed": 10
2033                }
2034            },
2035            {
2036                "acronym": "FI",
2037                "settings": {
2038                    "unknown_field": true
2039                }
2040            }
2041        ]"#;
2042
2043        let mut d = Deserializer::from_str(json);
2044        let mods = GameModsSeed::AllowMultipleModes {
2045            deny_unknown_fields: true,
2046        }
2047        .deserialize(&mut d)
2048        .unwrap();
2049        let mut expected = GameMods::new();
2050        expected.insert(GameMod::DifficultyAdjustTaiko(DifficultyAdjustTaiko {
2051            scroll_speed: Some(10.0),
2052            ..Default::default()
2053        }));
2054        expected.insert(GameMod::UnknownOsu(UnknownMod {
2055            acronym: Acronym::from_str("FI").unwrap(),
2056        }));
2057        assert_eq!(mods, expected);
2058
2059        let mut d = Deserializer::from_str(json);
2060        let mods = GameModsSeed::Mode {
2061            mode: GameMode::Taiko,
2062            deny_unknown_fields: true,
2063        }
2064        .deserialize(&mut d)
2065        .unwrap();
2066        let mut expected = GameMods::new();
2067        expected.insert(GameMod::DifficultyAdjustTaiko(DifficultyAdjustTaiko {
2068            scroll_speed: Some(10.0),
2069            ..Default::default()
2070        }));
2071        expected.insert(GameMod::UnknownTaiko(UnknownMod {
2072            acronym: Acronym::from_str("FI").unwrap(),
2073        }));
2074        assert_eq!(mods, expected);
2075
2076        let mut d = Deserializer::from_str(json);
2077        let mods = GameModsSeed::AllowMultipleModes {
2078            deny_unknown_fields: false,
2079        }
2080        .deserialize(&mut d)
2081        .unwrap();
2082        let mut expected = GameMods::new();
2083        expected.insert(GameMod::DifficultyAdjustOsu(Default::default()));
2084        expected.insert(GameMod::FadeInMania(Default::default()));
2085        assert_eq!(mods, expected);
2086
2087        let mut d = Deserializer::from_str(json);
2088        let mods = GameModsSeed::Mode {
2089            mode: GameMode::Taiko,
2090            deny_unknown_fields: true,
2091        }
2092        .deserialize(&mut d)
2093        .unwrap();
2094        let mut expected = GameMods::new();
2095        expected.insert(GameMod::DifficultyAdjustTaiko(DifficultyAdjustTaiko {
2096            scroll_speed: Some(10.0),
2097            ..Default::default()
2098        }));
2099        expected.insert(GameMod::UnknownTaiko(UnknownMod {
2100            acronym: Acronym::from_str("FI").unwrap(),
2101        }));
2102        assert_eq!(mods, expected);
2103    }
2104
2105    #[test]
2106    fn deser_mods_same_success() {
2107        let json = r#"[
2108            {
2109                "acronym":"DA",
2110                "settings":{
2111                    "scroll_speed":2
2112                }
2113            },
2114            {
2115                "acronym":"CS"
2116            }
2117        ]"#;
2118
2119        let mut d = Deserializer::from_str(json);
2120        let mods = GameModsSeed::SameModeForEachMod {
2121            deny_unknown_fields: true,
2122        }
2123        .deserialize(&mut d)
2124        .unwrap();
2125        let mut expected = GameMods::new();
2126        expected.insert(GameMod::DifficultyAdjustTaiko(DifficultyAdjustTaiko {
2127            scroll_speed: Some(2.0),
2128            ..Default::default()
2129        }));
2130        expected.insert(GameMod::ConstantSpeedTaiko(Default::default()));
2131        assert_eq!(mods, expected);
2132    }
2133
2134    #[test]
2135    fn deser_mods_same_fail() {
2136        let json = r#"[
2137            {
2138                "acronym":"DA",
2139                "settings":{
2140                    "scroll_speed":2
2141                }
2142            },
2143            {
2144                "acronym":"EZ",
2145                "settings":{
2146                    "retries":2
2147                }
2148            },
2149            "FI",
2150            256
2151        ]"#;
2152
2153        let mut d = Deserializer::from_str(json);
2154        let err = GameModsSeed::SameModeForEachMod {
2155            deny_unknown_fields: true,
2156        }
2157        .deserialize(&mut d)
2158        .unwrap_err();
2159        assert_eq!(err.to_string(), "all modes failed to deserialize mods [GameMod { acronym: \"DA\", settings: [GameModSettingField { name: \"scroll_speed\", value: 2.0 }] }, GameMod { acronym: \"EZ\", settings: [GameModSettingField { name: \"retries\", value: 2.0 }] }, \"FI\", 256] at line 16 column 9");
2160    }
2161}