Skip to content

Commit 81b6182

Browse files
committed
feat: partial Forge legacy impl
Signed-off-by: Rachel Powers <[email protected]>
1 parent 37c01fd commit 81b6182

File tree

6 files changed

+506
-217
lines changed

6 files changed

+506
-217
lines changed

libmcmeta/src/models/forge.rs

Lines changed: 69 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::models::merge::{self, Merge};
22

3-
use crate::models::GradleSpecifier;
3+
use crate::models::{GradleSpecifier, MojangLibrary};
44
use serde::{Deserialize, Serialize};
55
use serde_valid::Validate;
66
use serde_with::skip_serializing_none;
@@ -601,6 +601,7 @@ pub struct ForgeInstallerProfileInstallSection {
601601
pub profile_name: String,
602602
#[merge(strategy = merge::overwrite)]
603603
pub target: String,
604+
#[merge(strategy = merge::overwrite)]
604605
pub path: GradleSpecifier,
605606
#[merge(strategy = merge::overwrite)]
606607
pub version: String,
@@ -682,7 +683,7 @@ pub struct ForgeOptional {
682683
pub desc: Option<String>,
683684
#[merge(strategy = merge::option::overwrite_some)]
684685
pub url: Option<String>,
685-
#[merge(strategy = merge::option::recurse)]
686+
#[merge(strategy = merge::option::overwrite_some)]
686687
pub artifact: Option<GradleSpecifier>,
687688
#[merge(strategy = merge::option::overwrite_some)]
688689
pub maven: Option<String>,
@@ -716,6 +717,72 @@ pub struct ForgeLegacyInfoList {
716717
pub number: HashMap<String, ForgeLegacyInfo>,
717718
}
718719

720+
#[derive(Deserialize, Serialize, Clone, Debug, Validate, Merge, Default)]
721+
pub struct DataSpec {
722+
#[merge(strategy = merge::option::overwrite_some)]
723+
client: Option<String>,
724+
#[merge(strategy = merge::option::overwrite_some)]
725+
server: Option<String>,
726+
}
727+
728+
#[derive(Deserialize, Serialize, Clone, Debug, Validate, Merge, Default)]
729+
pub struct ProcessorSpec {
730+
#[merge(strategy = merge::option::overwrite_some)]
731+
jar: Option<String>,
732+
#[merge(strategy = merge::option_vec::append_some)]
733+
classpath: Option<Vec<String>>,
734+
#[merge(strategy = merge::option_vec::append_some)]
735+
args: Option<Vec<String>>,
736+
#[merge(strategy = merge::option_hashmap::overwrite_key_some)]
737+
outputs: Option<HashMap<String, String>>,
738+
#[merge(strategy = merge::option_vec::append_some)]
739+
sides: Option<Vec<String>>,
740+
}
741+
742+
#[derive(Deserialize, Serialize, Clone, Debug, Validate, Merge, Default)]
743+
pub struct ForgeInstallerProfileV2 {
744+
#[merge(skip)]
745+
_comment: Option<Vec<String>>,
746+
#[merge(strategy = merge::option::overwrite_some)]
747+
spec: Option<i32>,
748+
#[merge(strategy = merge::option::overwrite_some)]
749+
profile: Option<String>,
750+
#[merge(strategy = merge::option::overwrite_some)]
751+
version: Option<String>,
752+
#[merge(strategy = merge::option::overwrite_some)]
753+
icon: Option<String>,
754+
#[serde(rename = "json")]
755+
#[merge(strategy = merge::option::overwrite_some)]
756+
json_data: Option<String>,
757+
#[merge(strategy = merge::option::overwrite_some)]
758+
path: Option<GradleSpecifier>,
759+
#[merge(strategy = merge::option::overwrite_some)]
760+
logo: Option<String>,
761+
#[merge(strategy = merge::option::overwrite_some)]
762+
minecraft: Option<String>,
763+
#[merge(strategy = merge::option::overwrite_some)]
764+
welcome: Option<String>,
765+
#[merge(strategy = merge::option_hashmap::recurse_some)]
766+
data: Option<HashMap<String, DataSpec>>,
767+
#[merge(strategy = merge::option_vec::append_some)]
768+
processors: Option<Vec<ProcessorSpec>>,
769+
#[merge(strategy = merge::option_vec::append_some)]
770+
libraries: Option<Vec<MojangLibrary>>,
771+
#[serde(rename = "mirrorList")]
772+
#[merge(strategy = merge::option::overwrite_some)]
773+
mirror_list: Option<String>,
774+
#[serde(rename = "erverJarPath")]
775+
#[merge(strategy = merge::option::overwrite_some)]
776+
server_jar_path: Option<String>,
777+
}
778+
779+
#[derive(Deserialize, Serialize, Clone, Debug, Validate, Merge, Default)]
780+
pub struct InstallerInfo {
781+
pub sha1hash: Option<String>,
782+
pub sha256hash: Option<String>,
783+
pub size: Option<u64>,
784+
}
785+
719786
pub struct ForgeProcessedVersion {
720787
pub build: i32,
721788
pub raw_version: String,

libmcmeta/src/models/mod.rs

Lines changed: 127 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -11,23 +11,20 @@ custom_error! { pub ModelError
1111
InvalidGradleSpecifier { specifier: String } = "Invalid Gradle specifier '{specifier}'",
1212
}
1313

14+
static META_FORMAT_VERSION: i32 = 1;
15+
1416
/// A Gradle specifier.
15-
#[derive(Debug, PartialEq, Eq, Clone, merge::Merge, Default)]
17+
#[derive(Debug, PartialEq, Eq, Clone, Default)]
1618
pub struct GradleSpecifier {
1719
/// Group of the artifact.
18-
#[merge(strategy = merge::overwrite)]
1920
pub group: String,
2021
/// Artifact name.
21-
#[merge(strategy = merge::overwrite)]
2222
pub artifact: String,
2323
/// Version of the artifact.
24-
#[merge(strategy = merge::overwrite)]
2524
pub version: String,
2625
/// File extension of the artifact.
27-
#[merge(strategy = merge::overwrite)]
2826
pub extension: Option<String>,
2927
/// Classifier of the artifact.
30-
#[merge(strategy = merge::overwrite)]
3128
pub classifier: Option<String>,
3229
}
3330

@@ -195,29 +192,42 @@ impl<'de> Deserialize<'de> for GradleSpecifier {
195192
#[derive(Deserialize, Serialize, Debug, Clone, Validate, merge::Merge)]
196193
#[serde(rename_all = "camelCase")]
197194
pub struct MojangArtifactBase {
195+
#[merge(strategy = merge::option::overwrite_some)]
198196
pub sha1: Option<String>,
197+
#[merge(strategy = merge::option::overwrite_some)]
199198
pub size: Option<i32>,
199+
#[merge(strategy = merge::overwrite)]
200200
pub url: String,
201201
#[serde(flatten)]
202+
#[merge(strategy = merge::hashmap::overwrite_key)]
202203
pub unknown: HashMap<String, serde_json::Value>,
203204
}
204205

205206
#[derive(Deserialize, Serialize, Debug, Clone, Validate, merge::Merge)]
206207
#[serde(rename_all = "camelCase", deny_unknown_fields)]
207208
pub struct MojangAssets {
209+
#[merge(strategy = merge::option::overwrite_some)]
208210
pub sha1: Option<String>,
211+
#[merge(strategy = merge::option::overwrite_some)]
209212
pub size: Option<i32>,
213+
#[merge(strategy = merge::overwrite)]
210214
pub url: String,
215+
#[merge(strategy = merge::overwrite)]
211216
pub id: String,
217+
#[merge(strategy = merge::overwrite)]
212218
pub total_size: i32,
213219
}
214220

215221
#[derive(Deserialize, Serialize, Debug, Clone, Validate, merge::Merge)]
216222
#[serde(rename_all = "camelCase", deny_unknown_fields)]
217223
pub struct MojangArtifact {
224+
#[merge(strategy = merge::option::overwrite_some)]
218225
pub sha1: Option<String>,
226+
#[merge(strategy = merge::option::overwrite_some)]
219227
pub size: Option<i32>,
228+
#[merge(strategy = merge::overwrite)]
220229
pub url: String,
230+
#[merge(strategy = merge::option::overwrite_some)]
221231
pub path: Option<String>,
222232
}
223233

@@ -260,7 +270,7 @@ pub struct OSRule {
260270
pub version: Option<String>,
261271
}
262272

263-
fn os_rule_name_must_be_os(name: String) -> Result<(), serde_valid::validation::Error> {
273+
fn os_rule_name_must_be_os(name: &String) -> Result<(), serde_valid::validation::Error> {
264274
let valid_os_names = vec![
265275
"osx",
266276
"linux",
@@ -270,8 +280,11 @@ fn os_rule_name_must_be_os(name: String) -> Result<(), serde_valid::validation::
270280
"linux-arm64",
271281
"linux-arm32",
272282
];
273-
if !valid_os_names.contains(&name) {
274-
Err(format!("`{}` not a valid os name", &name))
283+
if !valid_os_names.contains(&name.as_str()) {
284+
Err(serde_valid::validation::Error::Custom(format!(
285+
"`{}` not a valid os name",
286+
&name
287+
)))
275288
} else {
276289
Ok(())
277290
}
@@ -288,13 +301,13 @@ pub struct MojangRule {
288301
}
289302

290303
fn mojang_rule_action_must_be_allow_disallow(
291-
action: String,
304+
action: &String,
292305
) -> Result<(), serde_valid::validation::Error> {
293-
if !vec!["allow", "disallow"].contains(&action) {
294-
Err(format!(
306+
if !vec!["allow", "disallow"].contains(&action.as_str()) {
307+
Err(serde_valid::validation::Error::Custom(format!(
295308
"`{}` not a valid action, must be `allow` or `disallow`",
296309
&action
297-
))
310+
)))
298311
} else {
299312
Ok(())
300313
}
@@ -320,11 +333,11 @@ impl Deref for MojangRules {
320333
pub struct MojangLibrary {
321334
#[merge(strategy = merge::option::recurse)]
322335
pub extract: Option<MojangLibraryExtractRules>,
323-
#[merge(strategy = merge::option::recurse)]
336+
#[merge(strategy = merge::option::overwrite_some)]
324337
pub name: Option<GradleSpecifier>,
325338
#[merge(strategy = merge::option::recurse)]
326339
pub downloads: Option<MojangLibraryDownloads>,
327-
#[merge(strategy = merge::option::recurse)]
340+
#[merge(strategy = merge::option_hashmap::overwrite_key_some)]
328341
pub natives: Option<HashMap<String, String>>,
329342
#[merge(strategy = merge::option::recurse)]
330343
pub rules: Option<MojangRules>,
@@ -335,19 +348,71 @@ pub struct MojangLibrary {
335348
pub struct Library {
336349
#[merge(strategy = merge::option::recurse)]
337350
pub extract: Option<MojangLibraryExtractRules>,
338-
#[merge(strategy = merge::option::recurse)]
351+
#[merge(strategy = merge::option::overwrite_some)]
339352
pub name: Option<GradleSpecifier>,
340353
#[merge(strategy = merge::option::recurse)]
341354
pub downloads: Option<MojangLibraryDownloads>,
342-
#[merge(strategy = merge::option::recurse)]
355+
#[merge(strategy = merge::option_hashmap::overwrite_key_some)]
343356
pub natives: Option<HashMap<String, String>>,
344357
#[merge(strategy = merge::option::recurse)]
345358
pub rules: Option<MojangRules>,
346359
#[merge(strategy = merge::option::overwrite_some)]
347360
url: Option<String>,
348361
#[serde(rename = "MMC-hint")]
349362
#[merge(strategy = merge::option::overwrite_some)]
350-
mmcHint: Option<String>,
363+
mmc_hint: Option<String>,
364+
}
365+
366+
impl From<MojangLibrary> for Library {
367+
fn from(item: MojangLibrary) -> Self {
368+
Self {
369+
extract: item.extract,
370+
name: item.name,
371+
downloads: item.downloads,
372+
natives: item.natives,
373+
rules: item.rules,
374+
url: None,
375+
mmc_hint: None,
376+
}
377+
}
378+
}
379+
380+
impl From<Library> for MojangLibrary {
381+
fn from(item: Library) -> Self {
382+
Self {
383+
extract: item.extract,
384+
name: item.name,
385+
downloads: item.downloads,
386+
natives: item.natives,
387+
rules: item.rules,
388+
}
389+
}
390+
}
391+
392+
impl From<&MojangLibrary> for Library {
393+
fn from(item: &MojangLibrary) -> Self {
394+
Self {
395+
extract: item.extract.clone(),
396+
name: item.name.clone(),
397+
downloads: item.downloads.clone(),
398+
natives: item.natives.clone(),
399+
rules: item.rules.clone(),
400+
url: None,
401+
mmc_hint: None,
402+
}
403+
}
404+
}
405+
406+
impl From<&Library> for MojangLibrary {
407+
fn from(item: &Library) -> Self {
408+
Self {
409+
extract: item.extract.clone(),
410+
name: item.name.clone(),
411+
downloads: item.downloads.clone(),
412+
natives: item.natives.clone(),
413+
rules: item.rules.clone(),
414+
}
415+
}
351416
}
352417

353418
#[derive(Deserialize, Serialize, Debug, Clone, Validate, merge::Merge, Default)]
@@ -364,30 +429,52 @@ pub struct Dependency {
364429
#[derive(Deserialize, Serialize, Debug, Clone, Validate, merge::Merge, Default)]
365430
#[serde(rename_all = "camelCase", deny_unknown_fields)]
366431
pub struct MetaVersion {
432+
#[merge(strategy = merge::overwrite)]
367433
pub format_version: i32,
434+
#[merge(strategy = merge::overwrite)]
368435
pub name: String,
436+
#[merge(strategy = merge::overwrite)]
369437
pub version: String,
438+
#[merge(strategy = merge::overwrite)]
370439
pub uid: String,
371440
#[serde(rename = "type")]
441+
#[merge(strategy = merge::option::overwrite_some)]
372442
pub version_type: Option<String>,
443+
#[merge(strategy = merge::option::overwrite_some)]
373444
pub order: Option<i32>,
445+
#[merge(strategy = merge::option::overwrite_some)]
374446
pub volatile: Option<bool>,
447+
#[merge(strategy = merge::option_vec::append_some)]
375448
pub requires: Option<Vec<Dependency>>,
449+
#[merge(strategy = merge::option_vec::append_some)]
376450
pub conflicts: Option<Vec<Dependency>>,
451+
#[merge(strategy = merge::option_vec::append_some)]
377452
pub libraries: Option<Vec<Library>>,
453+
#[merge(strategy = merge::option::overwrite_some)]
378454
pub asset_index: Option<MojangAssets>,
455+
#[merge(strategy = merge::option_vec::append_some)]
379456
pub maven_files: Option<Vec<Library>>,
457+
#[merge(strategy = merge::option::overwrite_some)]
380458
pub main_jar: Option<Library>,
459+
#[merge(strategy = merge::option_vec::append_some)]
381460
pub jar_mods: Option<Vec<Library>>,
461+
#[merge(strategy = merge::option::overwrite_some)]
382462
pub main_class: Option<String>,
463+
#[merge(strategy = merge::option::overwrite_some)]
383464
pub applet_class: Option<String>,
465+
#[merge(strategy = merge::option::overwrite_some)]
384466
pub minecraft_arguments: Option<String>,
467+
#[merge(strategy = merge::option::overwrite_some)]
385468
pub release_time: Option<String>,
469+
#[merge(strategy = merge::option_vec::append_some)]
386470
pub compatible_java_majors: Option<Vec<i32>>,
471+
#[merge(strategy = merge::option_vec::append_some)]
387472
pub additional_traits: Option<Vec<String>>,
388473
#[serde(rename = "+tweakers")]
474+
#[merge(strategy = merge::option_vec::append_some)]
389475
pub additional_tweakers: Option<Vec<String>>,
390476
#[serde(rename = "+jvmArgs")]
477+
#[merge(strategy = merge::option_vec::append_some)]
391478
pub additional_jvm_args: Option<Vec<String>>,
392479
}
393480

@@ -460,6 +547,14 @@ pub mod merge {
460547
}
461548
}
462549
}
550+
551+
pub fn overwrite_key<K: Eq + Hash, V>(left: &mut HashMap<K, V>, right: HashMap<K, V>) {
552+
use std::collections::hash_map::Entry;
553+
554+
for (k, v) in right {
555+
left.insert(k, v);
556+
}
557+
}
463558
}
464559

465560
/// Merge strategies for `Option<HashMap>`
@@ -480,6 +575,20 @@ pub mod merge {
480575
}
481576
}
482577
}
578+
579+
pub fn overwrite_key_some<K: Eq + Hash, V>(
580+
left: &mut Option<HashMap<K, V>>,
581+
right: Option<HashMap<K, V>>,
582+
) {
583+
use std::collections::hash_map::Entry;
584+
if let Some(new) = right {
585+
if let Some(original) = left {
586+
hashmap::overwrite_key(original, new);
587+
} else {
588+
*left = Some(new);
589+
}
590+
}
591+
}
483592
}
484593

485594
/// Merge strategies for `Option<Vec>`

0 commit comments

Comments
 (0)