1use crate::imports::*;
6use crate::utils::ErrorMap;
7
8use percent_encoding::{utf8_percent_encode,NON_ALPHANUMERIC};
9
10#[derive(Debug,Clone,Eq,PartialEq)]
11#[derive(Serialize,Deserialize)]
12pub struct Html(pub String);
13
14#[derive(Debug,Eq,PartialEq)]
15#[derive(Serialize,Deserialize)]
16pub struct HtmlRef<'r>(pub &'r str);
17
18impl Html {
19 pub fn from_literal(lit : &str) -> Html {
20 Html(htmlescape::encode_minimal(lit))
21 }
22 pub fn as_ref(&self) -> HtmlRef { HtmlRef(self.0.as_ref()) }
23}
24
25impl HtmlRef<'_> {
26 pub fn to_owned(&self) -> Html { Html(self.0.to_owned()) }
27}
28
29pub const INDEX_BASENAME : &str = "index";
30pub const INDEX : &str = "index.html";
31
32pub struct IndexWriter {
33 f : BufWriter<File>,
34 deferred_error : Result<(),io::Error>,
35}
36
37enum TableState {
38 Unstarted(Html),
39 Working,
40}
41use TableState::*;
42
43pub struct TableWriter<'i> {
44 i : &'i mut IndexWriter,
45 s : TableState,
46}
47
48impl IndexWriter {
49 #[throws(E)]
50 pub fn new(outdir : &str, title : &HtmlRef) -> IndexWriter {
51 let f = File::create(outdir.to_owned() + "/" + INDEX).cxm(||format!(
52 "create index file {}", INDEX))?;
53 let mut f = BufWriter::new(f);
54
55 writeln!(&mut f,
56 r#"<html><head><title>{}</title><head><body>"#,
57 title.0)?;
58
59 IndexWriter { f, deferred_error : Ok(()) }
60 }
61
62 #[throws(E)]
63 fn check(&mut self) {
64 replace(&mut self.deferred_error, Ok(()))?;
65 }
66
67 #[throws(E)]
68 pub fn table(&mut self, heading : Html) -> TableWriter {
69 self.check()?;
70 TableWriter { i : self, s : Unstarted(heading) }
71 }
72
73 #[throws(E)]
74 pub fn finish(mut self) {
75 self.check()?;
76 writeln!(&mut self.f,
77 r#"</body></html>"#)?;
78 self.f.flush()?;
79 }
80}
81
82impl TableWriter<'_> {
83 #[throws(E)]
84 pub fn entry(&mut self, filename : &str, desc : &HtmlRef) {
85 match &mut self.s {
86 Unstarted(ref mut heading) => {
87 writeln!(&mut self.i.f,
88 r#"<h1>{}</h1><table>"#,
89 heading.0)?;
90 self.s = Working;
91 },
92 Working => { },
93 }
94
95 writeln!(&mut self.i.f,
96 r#"<tr><th align="left"><a href="{}">{}</a></th><td>{}</td>"#,
97 utf8_percent_encode(filename, NON_ALPHANUMERIC),
98 Html::from_literal(filename).0,
99 desc.0
100 )?;
101 }
102}
103
104impl Drop for TableWriter<'_> {
105 fn drop(&mut self) {
106 match self.s {
107 Unstarted(_) => { }
108 Working => {
109 self.i.deferred_error =
110 writeln!(&mut self.i.f, r#"</table>"#);
111 }
112 }
113 }
114}