diff --git a/src/types/mod_json.rs b/src/types/mod_json.rs index f54af57..a756e00 100644 --- a/src/types/mod_json.rs +++ b/src/types/mod_json.rs @@ -78,12 +78,30 @@ pub enum ModJsonDependencyType { } #[derive(Deserialize, Debug)] -pub struct ModJsonDependency { +pub struct ModJsonDependencyOnlyVersion { + version: String, +} + +#[derive(Deserialize, Debug)] +pub struct ModJsonDependencyWithImportance { version: String, - #[serde(default)] importance: DependencyImportance, } +#[derive(Deserialize, Debug)] +pub struct ModJsonDependencyWithRequired { + version: String, + required: bool, +} + +#[derive(Deserialize, Debug)] +#[serde(untagged)] +pub enum ModJsonDependency { + WithImportance(ModJsonDependencyWithImportance), + WithRequired(ModJsonDependencyWithRequired), + OnlyVersion(ModJsonDependencyOnlyVersion), +} + #[derive(Deserialize, Debug)] pub struct OldModJsonDependency { pub id: String, @@ -107,10 +125,27 @@ pub enum ModJsonIncompatibilityType { } #[derive(Deserialize, Debug)] -pub struct ModJsonIncompatibility { +pub struct ModJsonIncompatibilityOnlyVersion { version: String, - #[serde(default)] - pub importance: IncompatibilityImportance, +} + +#[derive(Deserialize, Debug)] +pub struct ModJsonIncompatibilityWithImportance { + version: String, + importance: IncompatibilityImportance, +} + +#[derive(Deserialize, Debug)] +pub struct ModJsonIncompatibilityWithBreaking { + version: String, + breaking: bool, +} + +#[derive(Deserialize, Debug)] +pub enum ModJsonIncompatibility { + WithImportance(ModJsonIncompatibilityWithImportance), + WithBreaking(ModJsonIncompatibilityWithBreaking), + OnlyVersion(ModJsonIncompatibilityOnlyVersion), } #[derive(Deserialize, Debug)] @@ -250,18 +285,33 @@ impl ModJson { }); } ModJsonDependencyType::Detailed(detailed) => { - let (dependency_ver, compare) = - split_version_and_compare(&(detailed.version)).map_err(|_| { + let (dep_ver, importance) = match detailed { + ModJsonDependency::OnlyVersion(data) => { + (&data.version, DependencyImportance::default()) + } + ModJsonDependency::WithRequired(data) => ( + &data.version, + match data.required { + true => DependencyImportance::Required, + false => DependencyImportance::Recommended, + }, + ), + ModJsonDependency::WithImportance(data) => { + (&data.version, data.importance) + } + }; + let (dependency_ver, compare) = split_version_and_compare(dep_ver) + .map_err(|_| { ModZipError::InvalidModJson(format!( "Invalid semver {}", - detailed.version + dep_ver )) })?; ret.push(DependencyCreate { dependency_id: id.clone(), version: dependency_ver.to_string(), compare, - importance: detailed.importance, + importance, }); } } @@ -336,18 +386,33 @@ impl ModJson { }); } ModJsonIncompatibilityType::Detailed(detailed) => { - let (ver, compare) = split_version_and_compare(&(detailed.version)) - .map_err(|_| { + let (inc_ver, importance) = match detailed { + ModJsonIncompatibility::OnlyVersion(data) => { + (&data.version, IncompatibilityImportance::default()) + } + ModJsonIncompatibility::WithBreaking(data) => ( + &data.version, + match data.breaking { + true => IncompatibilityImportance::Breaking, + false => IncompatibilityImportance::Conflicting, + }, + ), + ModJsonIncompatibility::WithImportance(data) => { + (&data.version, data.importance) + } + }; + let (ver, compare) = + split_version_and_compare(inc_ver).map_err(|_| { ModZipError::InvalidModJson(format!( "Invalid semver {}", - detailed.version + inc_ver )) })?; ret.push(IncompatibilityCreate { incompatibility_id: id.clone(), version: ver.to_string(), compare, - importance: detailed.importance, + importance, }); } } @@ -393,6 +458,28 @@ impl ModJson { )); } + let v5: bool = { + let geode = Version::parse(self.geode.trim_start_matches('v')) + .map_err(|_| ModZipError::InvalidModJson("Invalid geode version".into()))?; + geode.major >= 5 + }; + + // Don't allow array syntax for geode >= v5 + if let Some(ModJsonDependencies::Old(_)) = &self.dependencies + && v5 + { + return Err(ModZipError::InvalidModJson( + "Invalid dependencies key: should be an object".into(), + )); + } + if let Some(ModJsonIncompatibilities::Old(_)) = &self.incompatibilities + && v5 + { + return Err(ModZipError::InvalidModJson( + "Invalid incompatibilities key: should be an object".into(), + )); + } + if let Some(l) = &self.links { if let Some(community) = &l.community { if let Err(e) = Url::parse(community) { diff --git a/src/types/models/dependency.rs b/src/types/models/dependency.rs index e477106..4e12cd8 100644 --- a/src/types/models/dependency.rs +++ b/src/types/models/dependency.rs @@ -21,6 +21,7 @@ pub struct ResponseDependency { pub mod_id: String, pub version: String, pub importance: DependencyImportance, + pub required: bool, } #[derive(sqlx::FromRow, Clone, Debug)] @@ -44,6 +45,7 @@ impl FetchedDependency { } }, importance: self.importance, + required: self.importance == DependencyImportance::Required } } pub fn to_response(&self) -> ResponseDependency { @@ -57,6 +59,7 @@ impl FetchedDependency { } }, importance: self.importance, + required: self.importance == DependencyImportance::Required } } } @@ -93,7 +96,7 @@ impl Display for ModVersionCompare { } } -#[derive(sqlx::Type, Debug, Deserialize, Serialize, Clone, Copy, Default)] +#[derive(sqlx::Type, Debug, Deserialize, Serialize, Clone, Copy, Default, PartialEq)] #[sqlx(type_name = "dependency_importance", rename_all = "lowercase")] #[serde(rename_all = "lowercase")] pub enum DependencyImportance { diff --git a/src/types/models/incompatibility.rs b/src/types/models/incompatibility.rs index f44ab5d..e9dec24 100644 --- a/src/types/models/incompatibility.rs +++ b/src/types/models/incompatibility.rs @@ -54,6 +54,7 @@ pub struct ResponseIncompatibility { pub mod_id: String, pub version: String, pub importance: IncompatibilityImportance, + pub breaking: bool, } impl FetchedIncompatibility { @@ -68,6 +69,7 @@ impl FetchedIncompatibility { } }, importance: self.importance, + breaking: self.importance == IncompatibilityImportance::Breaking, } } @@ -82,6 +84,7 @@ impl FetchedIncompatibility { } }, importance: self.importance, + breaking: self.importance == IncompatibilityImportance::Breaking, } } }