use std::path::Path;
use laterite_ags4_core::index::Sidecar;
use laterite_ags4_validator::CheckOptions;
use super::{Document, resolve_edition};
use crate::{Error, ErrorKind};
pub struct Certify<'a> {
pub(crate) doc: &'a Document,
pub(crate) edition: Option<String>,
}
impl Certify<'_> {
#[must_use]
pub fn edition(mut self, edition: impl Into<String>) -> Self {
self.edition = Some(edition.into());
self
}
fn mint(&self) -> Result<Sidecar, Error> {
let opts = CheckOptions {
dict_version: self.edition.as_deref().map(resolve_edition).transpose()?,
custom_dict: None,
include_warnings: true,
include_fyi: true,
check_files: false,
encoding: laterite_ags4_parse::resolve_encoding(self.doc.encoding.as_deref())
.ok_or_else(|| {
Error::new(
ErrorKind::InvalidArgument,
format!(
"unknown encoding {:?}",
self.doc.encoding.as_deref().unwrap_or_default()
),
)
})?,
};
laterite_ags4_trust::mint(
&self.doc.source_bytes,
&opts,
chrono::Utc::now().to_rfc3339(),
None,
)
.map_err(|e| {
let kind = match &e {
laterite_ags4_trust::MintError::NotCertifiable { .. } => ErrorKind::InvalidArgument,
_ => ErrorKind::Other,
};
Error::with_source(kind, "cannot certify", e)
})
}
pub fn to_bytes(self) -> Result<Vec<u8>, Error> {
self.mint()?
.to_json()
.map_err(|e| Error::with_source(ErrorKind::Other, "cannot serialise certificate", e))
}
pub fn to_path(self, dest: impl AsRef<Path>) -> Result<(), Error> {
let dest = dest.as_ref();
let bytes = self.to_bytes()?;
std::fs::write(dest, bytes).map_err(|e| {
Error::with_source(ErrorKind::Io, format!("cannot write {}", dest.display()), e)
})
}
}
impl std::fmt::Debug for Certify<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Certify")
.field("edition", &self.edition)
.finish_non_exhaustive()
}
}
pub(crate) fn parse_cert(bytes: &[u8]) -> Result<Sidecar, Error> {
Sidecar::from_json(bytes).map_err(|e| {
Error::with_source(ErrorKind::InvalidArgument, "cannot read the certificate", e)
})
}