addonscript-rs/crates/model/src/lib.rs

213 lines
5.3 KiB
Rust

use std::collections::HashSet;
use addonscript_versioning::{Version, VersionRestriction};
use enums::{Side, ArgumentMode};
use error::Error;
use serde::{Deserialize, Serialize};
use url::Url;
pub use self::{
enums::{Flag, InstallAction},
meta::*,
};
pub mod api;
pub mod error;
pub mod enums;
pub mod meta;
#[derive(Debug, Serialize, Deserialize)]
pub struct Manifest {
pub addonscript: AddonScript,
pub id: String,
pub namespace: String,
pub version: Version,
#[serde(default)]
pub files: Vec<File>,
#[serde(default)]
pub relations: Vec<Relation>,
pub flags: Flags,
#[serde(default)]
pub repositories: Vec<Repository>,
#[serde(default)]
pub instance: bool,
#[serde(default)]
#[deprecated]
pub use_builder: bool,
#[serde(default)]
pub patches: Vec<Patch>,
#[serde(skip_serializing_if = "Option::is_none")]
pub meta: Option<Meta>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct VersionlessManifest {
#[serde(skip_serializing_if = "Option::is_none")]
pub addonscript: Option<AddonScript>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct AddonScript {
pub version: u8,
}
impl Default for AddonScript {
fn default() -> Self {
Self { version: 2 }
}
}
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct AddonDescriptor {
pub id: String,
pub namespace: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub version: Option<Version>,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Repository {
pub namespace: String,
pub instances: Vec<Url>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Relation {
pub id: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub namespace: Option<String>,
pub version: VersionRestriction,
#[serde(skip_serializing_if = "Option::is_none")]
pub repositories: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub flags: Option<Flags>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct File {
pub qualifier: String,
pub link: Vec<String>,
#[serde(default)]
pub install: Vec<Install>,
#[serde(skip_serializing_if = "Option::is_none")]
pub flags: Option<Flags>,
#[serde(skip_serializing_if = "Option::is_none")]
pub hashes: Option<Hashes>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Hashes {
#[serde(skip_serializing_if = "Option::is_none")]
pub sha1: Option<String>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Install {
pub action: InstallAction,
#[serde(default)]
pub args: Vec<String>,
#[serde(default)]
pub side: Side,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Flags {
#[serde(skip_serializing_if = "Option::is_none")]
pub client: Option<HashSet<Flag>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub server: Option<HashSet<Flag>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub both: Option<HashSet<Flag>>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Patch {
pub side: Side,
#[serde(skip_serializing_if = "Option::is_none")]
pub main_class: Option<String>,
#[serde(default)]
pub arguments: Vec<GameArgument>,
#[serde(default)]
pub jvm_arguments: Vec<String>,
#[serde(default)]
pub replace_jvm_arguments: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub java_version: Option<u16>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct GameArgument {
pub mode: ArgumentMode,
#[serde(skip_serializing_if = "Option::is_none")]
pub key: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub value: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub raw: Option<String>,
}
impl VersionlessManifest {
pub fn get_version(&self) -> u8 {
match &self.addonscript {
Some(addonscript) => addonscript.version,
None => 1,
}
}
pub fn is_version_valid(&self) -> bool {
self.get_version() == 2
}
}
impl Flags {
pub fn has_client_flag(&self, flag: &Flag) -> bool {
if let Some(flags) = &self.client {
if flags.contains(flag) {
return true;
}
}
if let Some(flags) = &self.both {
if flags.contains(flag) {
return true;
}
}
false
}
pub fn has_server_flag(&self, flag: &Flag) -> bool {
if let Some(flags) = &self.server {
if flags.contains(flag) {
return true;
}
}
if let Some(flags) = &self.both {
if flags.contains(flag) {
return true;
}
}
false
}
}
impl Manifest {
pub fn get_file(&self, qualifier: String) -> Option<&File> {
for file in &self.files {
if file.qualifier == qualifier {
return Some(file);
}
}
None
}
}
impl GameArgument {
pub fn format_argument(&self) -> Result<String, Error> {
if let Some(raw) = &self.raw {
Ok(raw.clone())
} else {
let key = self.key.clone().ok_or(Error::InvalidFormat)?;
let value = self.value.clone().unwrap_or_else(|| "".to_string());
Ok(format!("--{} {}", key, value))
}
}
}