1pub mod library;
14pub mod logging;
15pub mod rule;
16
17use std::fmt;
18use std::str::FromStr;
19
20use library::Library;
21use logging::Logging;
22use rule::Rule;
23use serde::de::{Error, MapAccess, SeqAccess, Visitor};
24use serde::{de, Deserialize, Deserializer, Serialize};
25
26use crate::VersionKind;
27
28
29#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize)]
30pub struct Argument {
31 pub rules: Vec<Rule>,
32 pub values: Vec<String>,
33}
34
35#[derive(Debug, Clone, Eq, PartialEq, Hash)]
36struct ArrayOrStringHelper(pub Vec<String>);
37
38impl<'de> Deserialize<'de> for ArrayOrStringHelper {
40 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
41 where
42 D: Deserializer<'de>,
43 {
44 struct ArrayOrStringVisitor;
45
46 impl<'de> Visitor<'de> for ArrayOrStringVisitor {
47 type Value = ArrayOrStringHelper;
48
49 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
50 formatter.write_str("string or array of strings")
51 }
52
53 fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
54 where
55 E: de::Error,
56 {
57 Ok(ArrayOrStringHelper(vec![s.to_owned()]))
58 }
59
60 fn visit_seq<S>(self, mut seq: S) -> Result<Self::Value, S::Error>
61 where
62 S: SeqAccess<'de>,
63 {
64 let mut vec = Vec::new();
65 while let Some(elem) = seq.next_element::<String>()? {
66 vec.push(elem);
67 }
68 Ok(ArrayOrStringHelper(vec))
69 }
70 }
71
72 deserializer.deserialize_any(ArrayOrStringVisitor)
73 }
74}
75
76impl FromStr for Argument {
77 type Err = ();
78
79 fn from_str(s: &str) -> Result<Self, Self::Err> {
80 Ok(Argument {
81 rules: vec![],
82 values: vec![s.to_owned()],
83 })
84 }
85}
86
87impl<'de> Deserialize<'de> for Argument {
88 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
89 where
90 D: Deserializer<'de>,
91 {
92 struct ArgumentVisitor;
93
94 impl<'de> Visitor<'de> for ArgumentVisitor {
95 type Value = Argument;
96
97 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
98 formatter.write_str("string or object with rules and value fields")
99 }
100
101 fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
102 where
103 E: de::Error,
104 {
105 Ok(Argument {
106 rules: vec![],
107 values: vec![s.to_owned()],
108 })
109 }
110
111 fn visit_map<M>(self, mut map: M) -> Result<Self::Value, M::Error>
112 where
113 M: MapAccess<'de>,
114 {
115 let mut rules = None;
116 let mut value = None;
117
118 while let Some(key) = map.next_key::<String>()? {
119 match key.as_str() {
120 "rules" => {
121 if rules.is_some() {
122 return Err(de::Error::duplicate_field("rules"));
123 }
124 rules = Some(map.next_value()?);
125 }
126 "value" => {
127 if value.is_some() {
128 return Err(de::Error::duplicate_field("value"));
129 }
130 value = Some(map.next_value::<ArrayOrStringHelper>()?.0);
131 }
132 _ => {
133 return Err(Error::unknown_field(&key, &["rules", "value"]));
134 }
135 }
136 }
137
138 let rules = rules.ok_or_else(|| de::Error::missing_field("rules"))?;
139 let value = value.ok_or_else(|| de::Error::missing_field("value"))?;
140
141 Ok(Argument {
142 rules,
143 values: value,
144 })
145 }
146 }
147
148 deserializer.deserialize_any(ArgumentVisitor)
149 }
150}
151
152#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
153#[serde(deny_unknown_fields)]
154pub struct Arguments {
155 pub game: Vec<Argument>,
156 pub jvm: Vec<Argument>,
157}
158
159#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
160#[serde(deny_unknown_fields, rename_all = "camelCase")]
161pub struct AssetIndex {
162 pub id: String,
163 pub sha1: String,
164 pub size: u64,
165 pub total_size: u64,
166 pub url: String,
167}
168
169#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
170#[serde(deny_unknown_fields)]
171pub struct Download {
172 pub sha1: String,
173 pub size: u64,
174 pub url: String,
175}
176
177#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
178#[serde(deny_unknown_fields)]
179pub struct Downloads {
180 pub client: Download,
181 #[serde(default)]
182 pub client_mappings: Option<Download>,
183 #[serde(default)]
184 pub server: Option<Download>,
185 #[serde(default)]
186 pub server_mappings: Option<Download>,
187 #[serde(default)]
188 pub windows_server: Option<Download>,
189}
190
191#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
192#[serde(deny_unknown_fields, rename_all = "camelCase")]
193pub struct JavaVersion {
194 pub component: String,
195 pub major_version: u8,
196}
197
198#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
199#[serde(rename_all = "camelCase")]
200#[serde(deny_unknown_fields)]
201pub struct Version {
202 #[serde(default)]
203 pub arguments: Option<Arguments>,
204 #[serde(default)]
205 pub minecraft_arguments: Option<String>,
206 pub asset_index: AssetIndex,
207 pub assets: String,
208 #[serde(default)]
209 pub compliance_level: Option<u8>,
210 pub downloads: Downloads,
211 pub id: String,
212 #[serde(default)]
213 pub java_version: Option<JavaVersion>,
214 pub libraries: Vec<Library>,
215 #[serde(default)]
216 pub logging: Option<Logging>,
217 pub main_class: String,
218 pub minimum_launcher_version: u8,
219 pub release_time: String,
220 pub time: String,
221 #[serde(rename = "type")]
222 pub kind: VersionKind,
223}