2022-09-16 06:49:51 +00:00
|
|
|
use std::io::{Read, Seek};
|
|
|
|
|
2022-11-02 19:43:25 +00:00
|
|
|
use serde::de::Error as _;
|
|
|
|
use serde::Deserialize;
|
2022-12-01 00:09:26 +00:00
|
|
|
use serde_json::StreamDeserializer;
|
2022-11-02 19:43:25 +00:00
|
|
|
use serde_json::de::IoRead;
|
2022-09-21 13:17:46 +00:00
|
|
|
pub use zip::{read::ZipFile, ZipArchive};
|
2022-09-16 06:49:51 +00:00
|
|
|
|
|
|
|
use crate::error::{Error, Result};
|
2022-11-02 19:43:25 +00:00
|
|
|
use crate::model::{ModPack, SimpleMod};
|
|
|
|
use crate::model::manifest_kind::ManifestKind;
|
2022-09-16 06:49:51 +00:00
|
|
|
|
|
|
|
pub mod model;
|
|
|
|
pub mod error;
|
|
|
|
pub(crate) mod tracking_reader;
|
|
|
|
pub mod ttmp_extractor;
|
2022-12-01 00:09:26 +00:00
|
|
|
pub mod mpd_encoder;
|
|
|
|
pub(crate) mod util;
|
2022-09-16 06:49:51 +00:00
|
|
|
|
2022-11-18 00:48:04 +00:00
|
|
|
pub fn from_value(value: serde_json::Value) -> Result<ManifestKind> {
|
|
|
|
let manifest = if value.is_array() {
|
|
|
|
ManifestKind::V1(serde_json::from_value(value).map_err(Error::InvalidManifest)?)
|
|
|
|
} else {
|
|
|
|
ManifestKind::V2(serde_json::from_value(value).map_err(Error::InvalidManifest)?)
|
|
|
|
};
|
|
|
|
|
|
|
|
Ok(manifest)
|
|
|
|
}
|
|
|
|
|
2022-11-02 19:43:25 +00:00
|
|
|
pub fn from_reader<R: Read + Seek>(reader: R) -> Result<(ManifestKind, ZipArchive<R>)> {
|
2022-09-16 06:49:51 +00:00
|
|
|
let mut zip = ZipArchive::new(reader).map_err(Error::Zip)?;
|
|
|
|
let manifest = zip.by_name("TTMPL.mpl").map_err(Error::Zip)?;
|
2022-11-02 19:43:25 +00:00
|
|
|
let mut manifest = StreamDeserializer::new(IoRead::new(manifest))
|
|
|
|
.collect::<Result<Vec<DesManifest>, _>>()
|
|
|
|
.map_err(Error::InvalidManifest)?;
|
|
|
|
|
|
|
|
#[derive(Deserialize)]
|
|
|
|
#[serde(untagged)]
|
|
|
|
enum DesManifest {
|
|
|
|
V1(SimpleMod),
|
|
|
|
V2(ModPack),
|
|
|
|
}
|
|
|
|
|
|
|
|
let all_v1 = manifest.iter().all(|inner| matches!(inner, DesManifest::V1(_)));
|
|
|
|
let transformed = if all_v1 {
|
|
|
|
let mods: Vec<SimpleMod> = manifest.into_iter()
|
|
|
|
.map(|inner| match inner {
|
|
|
|
DesManifest::V1(inner) => inner,
|
|
|
|
_ => unreachable!(),
|
|
|
|
})
|
|
|
|
.collect();
|
|
|
|
ManifestKind::V1(mods)
|
|
|
|
} else if manifest.len() == 1 && matches!(&manifest[0], DesManifest::V2(_)) {
|
|
|
|
ManifestKind::V2(match manifest.remove(0) {
|
|
|
|
DesManifest::V2(pack) => pack,
|
|
|
|
_ => unreachable!(),
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
return Err(Error::InvalidManifest(serde_json::Error::custom("unrecognised manifest")));
|
|
|
|
};
|
|
|
|
|
|
|
|
Ok((transformed, zip))
|
2022-09-16 06:49:51 +00:00
|
|
|
}
|