#![allow(dead_code)] use semver::VersionReq; use crate::errors::JsonError; use url::Url; use serde::Deserialize; use std::{ collections::HashMap, path::{ PathBuf, Path }, fs }; use mlua::prelude::{ LuaResult, LuaError }; #[derive(Deserialize, Debug)] pub struct Manifest { #[serde(skip, default = "default_url")] pub url: Url, pub plugins: Vec, pub repos: Option> } #[derive(Deserialize, Debug)] pub struct PluginReference { pub optional: Option, pub version: Option } #[derive(Deserialize, Debug)] struct File { pub url: Url, pub checksum: String, pub arch: String, pub path: PathBuf } #[derive(Deserialize, Debug)] pub struct Plugin { pub name: String, pub description: String, pub version: VersionReq, pub mod_version: Option, pub provides: Option>, pub dependencies: Option>, pub conflicts: Option>, pub path: Option, pub remote: Option, pub url: Option, pub checksum: Option, } fn default_url() -> Url { Url::parse("https://example.com").unwrap() } impl Manifest { pub fn parse

(path: P, url: Url) -> LuaResult where P: AsRef { let data = fs::read(path)?; let mut manifest: Manifest = serde_json::from_slice(data.as_slice()).map_err(JsonError)?; (&mut manifest).url = url; // Make sure that a plugin doesn't contain both 'url'/'checksum' and 'remote' for p in manifest.plugins.iter() { if p.url.is_some() && p.checksum.is_none() { return Err(LuaError::external(format!("Could not parse manifest from {}!\nField 'url' depends on field 'checksum'", manifest.url))); } else if p.url.is_none() && p.checksum.is_some() { return Err(LuaError::external(format!("Could not parse manifest from {}!\nField 'checksum' depends on field 'url'", manifest.url))); }; if p.remote.is_some() && p.url.is_some() { return Err(LuaError::external(format!("Could not parse manifest from {}!\nConflicting fields 'remote' and 'url'", manifest.url))); } } Ok(manifest) } }