use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Document {
pub title: Option<String>,
pub directives: Vec<Directive>,
pub blocks: Vec<Block>,
pub attestations: Vec<Attestation>,
}
impl Document {
pub fn new() -> Self {
Self {
title: None,
directives: Vec::new(),
blocks: Vec::new(),
attestations: Vec::new(),
}
}
}
impl Default for Document {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Block {
Heading {
level: u8,
content: Vec<Inline>,
},
Paragraph(Vec<Inline>),
CodeBlock {
language: Option<String>,
content: String,
},
Directive(Directive),
Attestation(Attestation),
ThematicBreak,
BlockQuote(Vec<Block>),
List {
ordered: bool,
items: Vec<Vec<Block>>,
},
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Inline {
Text(String),
Emphasis(Vec<Inline>),
Strong(Vec<Inline>),
Code(String),
Link {
content: Vec<Inline>,
url: String,
},
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Directive {
pub name: String,
pub value: String,
pub attributes: Vec<(String, String)>,
}
impl Directive {
pub fn new(name: impl Into<String>, value: impl Into<String>) -> Self {
Self {
name: name.into(),
value: value.into(),
attributes: Vec::new(),
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Attestation {
pub identity: String,
pub role: String,
pub trust_level: TrustLevel,
pub timestamp: Option<String>,
pub note: Option<String>,
}
impl Attestation {
pub fn new(
identity: impl Into<String>,
role: impl Into<String>,
trust_level: TrustLevel,
) -> Self {
Self {
identity: identity.into(),
role: role.into(),
trust_level,
timestamp: None,
note: None,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub enum TrustLevel {
Unverified,
Automated,
Reviewed,
Verified,
}
impl TrustLevel {
pub fn from_str(s: &str) -> Option<Self> {
match s.to_lowercase().as_str() {
"unverified" => Some(Self::Unverified),
"automated" => Some(Self::Automated),
"reviewed" => Some(Self::Reviewed),
"verified" => Some(Self::Verified),
_ => None,
}
}
pub fn as_str(&self) -> &'static str {
match self {
Self::Unverified => "unverified",
Self::Automated => "automated",
Self::Reviewed => "reviewed",
Self::Verified => "verified",
}
}
}
impl std::fmt::Display for TrustLevel {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(self.as_str())
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Manifest {
pub version: Option<String>,
pub title: Option<String>,
pub directives: Vec<Directive>,
pub attestations: Vec<Attestation>,
}
impl Manifest {
pub fn from_document(doc: &Document) -> Self {
let version = doc
.directives
.iter()
.find(|d| d.name == "version")
.map(|d| d.value.clone());
Self {
version,
title: doc.title.clone(),
directives: doc.directives.clone(),
attestations: doc.attestations.clone(),
}
}
}