diff options
Diffstat (limited to 'src/version.rs')
| -rw-r--r-- | src/version.rs | 65 |
1 files changed, 57 insertions, 8 deletions
diff --git a/src/version.rs b/src/version.rs index 6354143..462ba3b 100644 --- a/src/version.rs +++ b/src/version.rs @@ -1,10 +1,12 @@ use core::fmt; use std::{collections::BTreeMap, convert::Infallible, marker::PhantomData, ops::Deref, str::FromStr}; use std::collections::HashMap; -use chrono::{DateTime, Utc}; +use chrono::{DateTime, NaiveDateTime, Utc}; +use chrono::format::ParseErrorKind; +use indexmap::IndexMap; use regex::Regex; use serde::{de::{self, Visitor}, Deserialize, Deserializer}; -use serde::de::SeqAccess; +use serde::de::{Error, SeqAccess}; use sha1_smol::Digest; pub mod manifest; @@ -203,7 +205,17 @@ pub struct Library { pub extract: Option<LibraryExtractRule>, pub natives: Option<BTreeMap<OperatingSystem, String>>, pub rules: Option<Vec<CompatibilityRule>>, - pub url: Option<String> // old format + + // old format + pub url: Option<String>, + pub size: Option<usize>, + pub sha1: Option<Digest> +} + +impl Library { + pub fn get_canonical_name(&self) -> String { + canonicalize_library_name(self.name.as_str()) + } } impl LibraryDownloads { @@ -227,7 +239,7 @@ pub struct ClientLogging { #[derive(Deserialize, Debug, Clone)] pub struct Logging { - pub client: ClientLogging // other fields unknown + pub client: Option<ClientLogging> // other fields unknown } #[derive(Deserialize, Debug, Clone)] @@ -247,7 +259,7 @@ pub struct CompleteVersion { pub downloads: BTreeMap<DownloadType, DownloadInfo>, #[serde(default, deserialize_with = "deserialize_libraries")] - pub libraries: HashMap<String, Library>, + pub libraries: IndexMap<String, Library>, pub id: String, pub jar: Option<String>, // used as the jar filename if specified? (no longer used officially) @@ -256,7 +268,10 @@ pub struct CompleteVersion { pub main_class: Option<String>, pub minimum_launcher_version: Option<u32>, + + #[serde(deserialize_with = "deserialize_datetime_lenient")] pub release_time: Option<DateTime<Utc>>, + #[serde(deserialize_with = "deserialize_datetime_lenient")] pub time: Option<DateTime<Utc>>, #[serde(rename = "type")] @@ -338,14 +353,48 @@ fn canonicalize_library_name(name: &str) -> String { .join(":") } -fn deserialize_libraries<'de, D>(deserializer: D) -> Result<HashMap<String, Library>, D::Error> +fn deserialize_datetime_lenient<'de, D>(deserializer: D) -> Result<Option<DateTime<Utc>>, D::Error> +where + D: Deserializer<'de> +{ + struct DateTimeVisitor; + + impl<'de> Visitor<'de> for DateTimeVisitor { + type Value = Option<DateTime<Utc>>; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a valid datetime") + } + + fn visit_str<E>(self, value: &str) -> Result<Self::Value, E> + where + E: Error + { + match value.parse::<DateTime<Utc>>() { + Ok(dt) => Ok(Some(dt)), + Err(e) if e.kind() == ParseErrorKind::TooShort => { + // this probably just doesn't have an offset for some reason + match value.parse::<NaiveDateTime>() { + Ok(ndt) => Ok(Some(ndt.and_utc())), + Err(e) => Err(Error::custom(e)) + } + }, + Err(e) => Err(Error::custom(e)) + } + } + } + + deserializer.deserialize_str(DateTimeVisitor) +} + +fn deserialize_libraries<'de, D>(deserializer: D) -> Result<IndexMap<String, Library>, D::Error> where D: Deserializer<'de> { struct LibrariesVisitor; impl<'de> Visitor<'de> for LibrariesVisitor { - type Value = HashMap<String, Library>; + type Value = IndexMap<String, Library>; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("an array of libraries") @@ -355,7 +404,7 @@ where where A: SeqAccess<'de>, { - let mut map = HashMap::new(); + let mut map = IndexMap::new(); while let Some(lib) = seq.next_element::<Library>()? { //map.insert(canonicalize_library_name(lib.name.as_str()), lib); |
