1use indexmap::IndexMap;
2use serde::{Deserialize, Serialize};
3use opys_mojang_rules::OsOptions;
4
5use crate::artifact::{
6 artifact_applies, decode_artifact, encode_artifact, Artifact, ArtifactWire,
7};
8use crate::launch::{decode_launch, encode_launch, Launch, LaunchWire};
9use crate::shorthand::ShorthandError;
10use crate::valdefs::{encode_val_defs, parse_val_defs, ValDefWire, ValDefs};
11use crate::DecodeError;
12
13#[derive(Debug, Clone, Default, PartialEq, Eq)]
14pub struct Manifest {
15 pub vars: ValDefs,
16 pub launch: Option<Launch>,
17 pub artifacts: Vec<Artifact>,
18 pub restrict: Option<Vec<String>>,
19}
20
21#[derive(Debug, Clone, Serialize, Deserialize)]
22pub struct ManifestWire {
23 #[serde(default, skip_serializing_if = "Option::is_none")]
24 pub vars: Option<IndexMap<String, ValDefWire>>,
25 #[serde(default, skip_serializing_if = "Option::is_none")]
26 pub launch: Option<LaunchWire>,
27 #[serde(default, skip_serializing_if = "Option::is_none")]
28 pub artifacts: Option<Vec<ArtifactWire>>,
29 #[serde(default, skip_serializing_if = "Option::is_none")]
30 pub restrict: Option<Vec<String>>,
31}
32
33pub fn decode_manifest(raw: ManifestWire) -> Result<Manifest, ShorthandError> {
34 Ok(Manifest {
35 vars: raw.vars.map(parse_val_defs).transpose()?.unwrap_or_default(),
36 launch: raw.launch.map(decode_launch).transpose()?,
37 artifacts: raw
38 .artifacts
39 .map(|v| v.into_iter().map(decode_artifact).collect::<Result<_, _>>())
40 .transpose()?
41 .unwrap_or_default(),
42 restrict: raw.restrict,
43 })
44}
45
46pub fn encode_manifest(u: &Manifest) -> serde_json::Value {
47 let mut m = serde_json::Map::new();
48 m.insert("vars".into(), encode_val_defs(&u.vars));
49 if let Some(launch) = &u.launch {
50 m.insert("launch".into(), encode_launch(launch));
51 }
52 m.insert(
53 "artifacts".into(),
54 serde_json::to_value(u.artifacts.iter().map(encode_artifact).collect::<Vec<_>>()).unwrap(),
55 );
56 if let Some(r) = &u.restrict {
57 if !r.is_empty() {
58 m.insert("restrict".into(), serde_json::to_value(r).unwrap());
59 }
60 }
61 serde_json::Value::Object(m)
62}
63
64pub fn parse_manifest(input: &str) -> Result<Manifest, DecodeError> {
65 let wire: ManifestWire = serde_json::from_str(input)
66 .map_err(|e| DecodeError::Manifest(format!("{e}")))?;
67 decode_manifest(wire).map_err(Into::into)
68}
69
70pub fn filter_manifest(
71 u: &Manifest,
72 os: &OsOptions,
73 feats: &[String],
74) -> Result<Manifest, opys_mojang_rules::RuleError> {
75 let artifacts = u
76 .artifacts
77 .iter()
78 .filter_map(|a| match artifact_applies(a, os, feats) {
79 Ok(true) => Some(Ok(a.clone())),
80 Ok(false) => None,
81 Err(e) => Some(Err(e)),
82 })
83 .collect::<Result<_, _>>()?;
84 Ok(Manifest {
85 artifacts,
86 ..u.clone()
87 })
88}