flams_math_archives/
artifacts.rs1use crate::utils::{
2 errors::{ArtifactSaveError, FileError, WriteError},
3 lazy_file::LazyFileWriter,
4 path_ext::PathExt,
5};
6use ftml_ontology::{
7 domain::modules::Module,
8 narrative::{DocumentRange, documents::Document},
9 utils::Css,
10};
11use std::path::{Path, PathBuf};
12
13pub enum FileOrString {
14 File(PathBuf),
15 Str(Box<str>),
16}
17
18pub trait Artifact: std::any::Any {
19 fn kind(&self) -> &'static str;
20 fn write(&self, into: &Path) -> Result<(), ArtifactSaveError>;
22 fn as_any_mut(&mut self) -> &mut dyn std::any::Any;
23 fn as_any(&self) -> &dyn std::any::Any;
24}
25
26pub trait FileArtifact: std::any::Any {
27 fn kind(&self) -> &'static str;
28 fn as_any_mut(&mut self) -> &mut dyn std::any::Any;
29 fn as_any(&self) -> &dyn std::any::Any;
30 fn source(&self) -> &Path;
31}
32impl<F: FileArtifact> Artifact for F {
33 #[inline]
34 fn kind(&self) -> &'static str {
35 <Self as FileArtifact>::kind(self)
36 }
37 #[inline]
38 fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
39 <Self as FileArtifact>::as_any_mut(self)
40 }
41 #[inline]
42 fn as_any(&self) -> &dyn std::any::Any {
43 <Self as FileArtifact>::as_any(self)
44 }
45 fn write(&self, into: &Path) -> Result<(), ArtifactSaveError> {
46 self.source().rename_safe(&into)?;
47 Ok(())
48 }
49}
50
51pub struct FtmlString(pub Box<str>);
52impl Artifact for FtmlString {
53 #[inline]
54 fn kind(&self) -> &'static str {
55 "ftml"
56 }
57 #[inline]
58 fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
59 self as _
60 }
61 #[inline]
62 fn as_any(&self) -> &dyn std::any::Any {
63 self as _
64 }
65 fn write(&self, into: &Path) -> Result<(), ArtifactSaveError> {
66 std::fs::write(into, self.0.as_bytes())
67 .map_err(|e| ArtifactSaveError::Fs(FileError::Write(into.to_path_buf(), e)))
68 }
69}
70pub struct FtmlFile(pub PathBuf);
71impl Artifact for FtmlFile {
72 #[inline]
73 fn kind(&self) -> &'static str {
74 "ftml"
75 }
76 #[inline]
77 fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
78 self as _
79 }
80 #[inline]
81 fn as_any(&self) -> &dyn std::any::Any {
82 self as _
83 }
84 fn write(&self, into: &Path) -> Result<(), ArtifactSaveError> {
85 std::fs::copy(&self.0, into)
86 .map(|_| ())
87 .map_err(|e| ArtifactSaveError::Fs(FileError::Write(into.to_path_buf(), e)))
88 }
89}
90
91#[derive(Debug)]
92pub struct ContentResult {
93 pub document: Document,
94 pub modules: Vec<Module>,
95 pub data: Box<[u8]>,
96 pub body: DocumentRange,
97 pub inner_offset: u32,
98 pub css: Box<[Css]>,
99 pub ftml: Box<str>,
100 #[cfg(feature = "rdf")]
101 pub triples: Vec<ulo::rdf_types::Triple>,
102}
103impl Artifact for ContentResult {
104 #[inline]
105 fn kind(&self) -> &'static str {
106 "content"
107 }
108 #[inline]
109 fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
110 self as _
111 }
112 #[inline]
113 fn as_any(&self) -> &dyn std::any::Any {
114 self as _
115 }
116 fn write(&self, into: &Path) -> Result<(), ArtifactSaveError> {
117 let mut writer = match LazyFileWriter::<6>::new(into) {
118 Ok(w) => w,
119 Err(e) => {
120 return Err(ArtifactSaveError::Fs(FileError::Write(
121 into.to_path_buf(),
122 e,
123 )));
124 }
125 };
126 macro_rules! err {
127 ($e:expr) => {
128 if let Err(e) = $e {
129 match e {
130 WriteError::Io(e) => {
131 return Err(ArtifactSaveError::Fs(FileError::Write(
132 into.to_path_buf(),
133 e,
134 )));
135 }
136 WriteError::Encode(e) => return Err(ArtifactSaveError::Encode(e)),
137 _ => unreachable!(),
138 }
139 }
140 };
141 }
142 err!(writer.write(&self.body));
143 err!(writer.write(&self.inner_offset));
144 err!(writer.write(&self.css));
145 err!(writer.write_bytes(&self.data));
146 err!(writer.write(&self.document));
147 err!(writer.write_string(&self.ftml));
148 Ok(())
149 }
150}