1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
use {
crate::*,
serde::Serialize,
std::{
fs::File,
io::{self, Read},
path::PathBuf,
},
};
pub const DOLL_JS: &str = include_str!("../rsc/dom-doll.js");
pub const VIS_JS: &str = include_str!("../rsc/vis-timeline-graph2d.min.js");
pub const VIS_CSS: &str = include_str!("../rsc/vis-timeline-graph2d.min.css");
pub const SQL_JS: &str = include_str!("../rsc/sql-wasm.js");
pub const SQL_WASM: &[u8] = include_bytes!("../rsc/sql-wasm.wasm");
pub const VIEWER_JS: &str = include_str!("../rsc/viewer.js");
pub const VIEWER_CSS: &str = include_str!("../rsc/viewer.css");
#[derive(Debug, Serialize)]
struct Conf<'b> {
bench_name: &'b str,
task_name: Option<&'b str>,
gb_version: String,
}
pub struct HtmlViewer<'b> {
conf: Conf<'b>,
}
impl<'b> HtmlViewer<'b> {
pub fn new(bench_name: &'b str, task_name: Option<&'b str>) -> Self {
Self {
conf: Conf {
bench_name,
task_name,
gb_version: env!("CARGO_PKG_VERSION").to_string(),
},
}
}
pub fn open_in_browser(&self) -> Result<(), GlassBenchError> {
let (mut w, path) = make_temp_file()?;
self.write_html(&mut w)?;
open::that(path)?;
Ok(())
}
pub fn write_html<W: io::Write>(&self, mut w: W) -> Result<(), GlassBenchError> {
writeln!(w, "<!DOCTYPE HTML>")?;
writeln!(w, "<html>")?;
writeln!(w, "<head>")?;
writeln!(w, "<meta charset=UTF-8>")?;
writeln!(w, "<style type=text/css>{}</style>", VIEWER_CSS)?;
writeln!(w, "<style type=text/css>{}</style>", VIS_CSS)?;
writeln!(w, "<script>{}</script>", VIS_JS)?;
writeln!(w, "<script>{}</script>", SQL_JS)?;
writeln!(w, "<script>{}</script>", DOLL_JS)?;
writeln!(w, "<script charset=UTF-8>{}</script>", VIEWER_JS)?;
write_db(&mut w)?;
writeln!(w, "</head>")?;
writeln!(w, "<body>")?;
writeln!(w, "<script>")?;
writeln!(w, "const gb_conf = {}", serde_json::to_string(&self.conf)?)?;
writeln!(
w,
r#"const sql_conf = {{ locateFile: filename=>"data:application/wasm;base64,{}" }};"#,
base64::encode(SQL_WASM),
)?;
writeln!(w, "main(sql_conf);")?;
writeln!(w, "</script>")?;
writeln!(w, "</body>")?;
writeln!(w, "</html>")?;
Ok(())
}
}
pub fn make_temp_file() -> io::Result<(File, PathBuf)> {
tempfile::Builder::new()
.prefix("glassbench-")
.suffix(".html")
.rand_bytes(12)
.tempfile()?
.keep()
.map_err(|_| io::Error::new(
io::ErrorKind::Other,
"temp file can't be kept",
))
}
pub fn write_db<W: io::Write>(mut w: W) -> Result<(), GlassBenchError> {
let mut file = File::open(Db::path()?)?;
let mut bytes = Vec::new();
file.read_to_end(&mut bytes)?;
writeln!(w,
r#"<script>const db64="{}"</script>"#,
base64::encode(&bytes),
)?;
Ok(())
}