@@ -2,7 +2,7 @@ use crate::spritesheet::SpriteSheet;
22use crate :: NiceUnwrap ;
33use clap:: ValueEnum ;
44use semver:: { Version , VersionReq } ;
5- use serde:: { Deserialize , Deserializer } ;
5+ use serde:: { Deserialize , Deserializer , de :: Error } ;
66use std:: collections:: { HashMap , HashSet } ;
77use std:: fmt:: Display ;
88use std:: fs;
@@ -122,7 +122,7 @@ where
122122 Ok ( <HashMap < String , BitmapFont > >:: deserialize ( deserializer) ?
123123 . into_iter ( )
124124 . map ( |( name, mut font) | {
125- font. name = name . clone ( ) ;
125+ font. name . clone_from ( & name ) ;
126126 font. path = std:: env:: current_dir ( ) . unwrap ( ) . join ( font. path ) ;
127127 ( name, font)
128128 } )
@@ -286,18 +286,104 @@ pub enum DependencyImportance {
286286 Suggested ,
287287}
288288
289- #[ derive( Default , Deserialize , PartialEq ) ]
289+ #[ derive( Deserialize , PartialEq ) ]
290290pub struct Dependency {
291+ #[ serde( skip) ]
291292 pub id : String ,
292293 #[ serde( deserialize_with = "parse_comparable_version" ) ]
293294 pub version : VersionReq ,
294295 #[ serde( default ) ]
295296 pub importance : DependencyImportance ,
296- pub required : Option < bool > ,
297297 #[ serde( default = "all_platforms" ) ]
298298 pub platforms : HashSet < PlatformName > ,
299299}
300300
301+ #[ derive( Deserialize , PartialEq ) ]
302+ pub struct LegacyDependency {
303+ pub id : String ,
304+ #[ serde( deserialize_with = "parse_comparable_version" ) ]
305+ pub version : VersionReq ,
306+ #[ serde( default ) ]
307+ pub importance : DependencyImportance ,
308+ #[ serde( default = "all_platforms" ) ]
309+ pub platforms : HashSet < PlatformName > ,
310+ }
311+
312+ #[ derive( PartialEq ) ]
313+ pub struct Dependencies ( HashMap < String , Dependency > ) ;
314+
315+ impl Dependencies {
316+ pub fn is_empty ( & self ) -> bool {
317+ self . 0 . is_empty ( )
318+ }
319+ }
320+
321+ impl < ' a > IntoIterator for & ' a Dependencies {
322+ type IntoIter = std:: collections:: hash_map:: Values < ' a , String , Dependency > ;
323+ type Item = & ' a Dependency ;
324+ fn into_iter ( self ) -> Self :: IntoIter {
325+ self . 0 . values ( )
326+ }
327+ }
328+
329+ // No it can't clippy Dependency doesn't impl Default
330+ #[ allow( clippy:: derivable_impls) ]
331+ impl Default for Dependencies {
332+ fn default ( ) -> Self {
333+ Self ( HashMap :: new ( ) )
334+ }
335+ }
336+
337+ fn parse_dependencies < ' de , D > ( deserializer : D ) -> Result < Dependencies , D :: Error >
338+ where
339+ D : Deserializer < ' de > ,
340+ {
341+ // This is all to avoid union types having terrible errors
342+ // (they just log "failed to parse any variant of X")
343+
344+ // This is needed because deserializer is moved
345+ let value = serde_json:: Value :: deserialize ( deserializer) ?;
346+
347+ match <HashMap < String , serde_json:: Value > >:: deserialize ( value. clone ( ) ) {
348+ Ok ( deps) => Ok ( Dependencies (
349+ deps. into_iter ( ) . map ( |( id, json) | {
350+ // Shorthand is just "[mod.id]": "[version]"
351+ match parse_comparable_version ( json. clone ( ) ) {
352+ Ok ( version) => Ok ( Dependency {
353+ id : id. clone ( ) ,
354+ version,
355+ importance : DependencyImportance :: Required ,
356+ platforms : all_platforms ( ) ,
357+ } ) ,
358+ // Longhand is "[mod.id]": { ... }
359+ Err ( _) => Dependency :: deserialize ( json)
360+ // The ID isn't parsed from the object itself but is the key
361+ . map ( |mut d| { d. id . clone_from ( & id) ; d } )
362+ . map_err ( D :: Error :: custom)
363+ } . map ( |r| ( id, r) )
364+ } ) . collect :: < Result < _ , _ > > ( ) ?
365+ ) ) ,
366+ Err ( e) => {
367+ // Can be removed after Geode hits v5
368+ match <Vec < LegacyDependency > >:: deserialize ( value) {
369+ Ok ( deps) => {
370+ let mut res = Dependencies :: default ( ) ;
371+ for dep in deps {
372+ res. 0 . insert ( dep. id . clone ( ) , Dependency {
373+ id : dep. id ,
374+ version : dep. version ,
375+ importance : dep. importance ,
376+ platforms : dep. platforms
377+ } ) ;
378+ }
379+ Ok ( res)
380+ }
381+ Err ( _) => Err ( D :: Error :: custom ( e) )
382+ }
383+ }
384+ }
385+ }
386+
301387#[ derive( Default , Deserialize , PartialEq ) ]
302388pub struct ModApi {
303389 #[ serde( deserialize_with = "parse_glob_rel" ) ]
@@ -347,8 +433,8 @@ pub struct ModFileInfo {
347433 pub description : String ,
348434 #[ serde( default ) ]
349435 pub resources : ModResources ,
350- #[ serde( default ) ]
351- pub dependencies : Vec < Dependency > ,
436+ #[ serde( default , deserialize_with = "parse_dependencies" ) ]
437+ pub dependencies : Dependencies ,
352438 pub api : Option < ModApi > ,
353439}
354440
0 commit comments