use crate::Uri;
use serde::{Deserialize, Serialize};
use std::{
collections::HashMap,
fmt::{Display, Formatter, Result as FmtResult},
ops::{Deref, DerefMut},
str::FromStr,
};
#[derive(Clone, Serialize, Deserialize)]
pub struct SchemaList {
#[serde(rename = "$schema")]
pub schema: String,
pub version: f32,
pub schemas: Vec<SchemaInfo>,
}
impl Display for SchemaList {
fn fmt(&self, f: &mut Formatter) -> FmtResult {
for schema in &self.schemas {
schema.fmt(f)?;
}
Ok(())
}
}
#[derive(Clone, Serialize, Deserialize)]
pub struct SchemaInfo {
pub name: String,
pub url: Wrapped<Uri>,
pub description: String,
#[serde(rename = "fileMatch")]
pub file_match: Option<Vec<String>>,
pub versions: Option<HashMap<String, Wrapped<Uri>>>,
}
impl Display for SchemaInfo {
fn fmt(&self, f: &mut Formatter) -> FmtResult {
"- name: ".fmt(f)?;
self.name.fmt(f)?;
"\n description: ".fmt(f)?;
self.description.fmt(f)?;
"\n url: ".fmt(f)?;
self.url.fmt(f)?;
if let Some(file_match) = &self.file_match {
"\n file_match:".fmt(f)?;
for file_match in file_match {
"\n - ".fmt(f)?;
file_match.fmt(f)?;
}
}
if let Some(versions) = &self.versions {
"\n versions:".fmt(f)?;
for (version, url) in versions {
"\n ".fmt(f)?;
version.fmt(f)?;
": ".fmt(f)?;
url.fmt(f)?;
}
}
"\n".fmt(f)
}
}
#[derive(Clone, Serialize, Deserialize)]
pub struct Wrapped<T>(
#[serde(
with = "serde_with::rust::display_fromstr",
bound = "T: Display + FromStr, T::Err: Display"
)]
T,
);
impl<T> AsRef<T> for Wrapped<T> {
fn as_ref(&self) -> &T {
&self.0
}
}
impl<T> Deref for Wrapped<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T> DerefMut for Wrapped<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl<T> Display for Wrapped<T>
where
T: Display,
{
fn fmt(&self, f: &mut Formatter) -> FmtResult {
self.0.fmt(f)
}
}