dvcompute_experiment_cons 2.0.1

Discrete event simulation library (support of experiments for conservative distributed simulation)
Documentation
// Copyright (c) 2020-2022  David Sorokin <davsor@mail.ru>, based in Yoshkar-Ola, Russia
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

use std::io;
use std::io::*;

use urlencoding;

/// Write the HTML code.
pub fn write_html(w: &mut dyn Write, code: &str) -> io::Result<()> {
    write!(w, "{}", code)
}

/// Write the HTML code line.
pub fn write_html_ln(w: &mut dyn Write, code: &str) -> io::Result<()> {
    write!(w, "{}", code)?;
    write!(w, "\n")
}

/// Write the text in HTML.
pub fn write_html_text(w: &mut dyn Write, text: &str) -> io::Result<()> {
    write!(w, "{}", encode_html_text(text))
}

const HTTP_PROTOCOL: &str = "http://";
const HTTPS_PROTOCOL: &str = "https://";

/// Write the HTML link with the specified URI and contents.
pub fn write_html_link(w: &mut dyn Write, uri: &str, text: &str) -> io::Result<()> {
    write_html(w, "<a href=\"")?;
    if uri.starts_with("#") {
        write_html(w, "#")?;
        write_html(w, &urlencoding::encode(&uri[1..]).to_owned())?;

    } else if uri.starts_with(HTTP_PROTOCOL) {
        write_html(w, HTTP_PROTOCOL)?;
        write_html(w, &urlencoding::encode(&uri[HTTP_PROTOCOL.len() ..]).to_owned())?;

    } else if uri.starts_with(HTTPS_PROTOCOL) {
        write_html(w, HTTPS_PROTOCOL)?;
        write_html(w, &urlencoding::encode(&uri[HTTPS_PROTOCOL.len() ..]).to_owned())?;

    } else {
        write_html(w, &urlencoding::encode(uri).to_owned())?;
    }
    write_html(w, "\">")?;
    write_html_text(w, text)?;
    write_html(w, "</a>")
}

/// Write the HTML image by the specified URI.
pub fn write_html_image(w: &mut dyn Write, uri: &str) -> io::Result<()> {
    write_html(w, "<img src=\"")?;
    if uri.starts_with(HTTP_PROTOCOL) {
        write_html(w, HTTP_PROTOCOL)?;
        write_html(w, &urlencoding::encode(&uri[HTTP_PROTOCOL.len() ..]).to_owned())?;

    } else if uri.starts_with(HTTPS_PROTOCOL) {
        write_html(w, HTTPS_PROTOCOL)?;
        write_html(w, &urlencoding::encode(&uri[HTTPS_PROTOCOL.len() ..]).to_owned())?;

    } else {
        write_html(w, &urlencoding::encode(uri).to_owned())?;
    }
    write_html(w, "\" />")
}

/// Begin the HTML paragraph.
pub fn begin_html_paragraph(w: &mut dyn Write) -> io::Result<()> {
    write_html_ln(w, "<p>")
}

/// Begin the HTML paragraph by the specified identifier.
pub fn begin_html_paragraph_by_id(w: &mut dyn Write, id: &str) -> io::Result<()> {
    write_html(w, "<p id=\"")?;
    write_html(w, &urlencoding::encode(id).to_owned())?;
    write_html_ln(w, "\">")
}

/// Begin the HTML paragraph.
pub fn end_html_paragraph(w: &mut dyn Write) -> io::Result<()> {
    write_html_ln(w, "</p>")
}

/// Write the HTML header of type 1.
pub fn write_html_header1(w: &mut dyn Write, text: &str) -> io::Result<()> {
    write_html(w, "<h1>")?;
    write_html_text(w, text)?;
    write_html_ln(w, "</h1>")
}

/// Write the HTML header of type 1 by the specified identifier.
pub fn write_html_header1_by_id(w: &mut dyn Write, id: &str, text: &str) -> io::Result<()> {
    write_html(w, "<h1 id=\"")?;
    write_html(w, &urlencoding::encode(id).to_owned())?;
    write_html(w, "\">")?;
    write_html_text(w, text)?;
    write_html_ln(w, "</h1>")
}

/// Write the HTML header of type 2.
pub fn write_html_header2(w: &mut dyn Write, text: &str) -> io::Result<()> {
    write_html(w, "<h2>")?;
    write_html_text(w, text)?;
    write_html_ln(w, "</h2>")
}

/// Write the HTML header of type 2 by the specified identifier.
pub fn write_html_header2_by_id(w: &mut dyn Write, id: &str, text: &str) -> io::Result<()> {
    write_html(w, "<h2 id=\"")?;
    write_html(w, &urlencoding::encode(id).to_owned())?;
    write_html(w, "\">")?;
    write_html_text(w, text)?;
    write_html_ln(w, "</h2>")
}

/// Write the HTML header of type 3.
pub fn write_html_header3(w: &mut dyn Write, text: &str) -> io::Result<()> {
    write_html(w, "<h3>")?;
    write_html_text(w, text)?;
    write_html_ln(w, "</h3>")
}

/// Write the HTML header of type 3 by the specified identifier.
pub fn write_html_header3_by_id(w: &mut dyn Write, id: &str, text: &str) -> io::Result<()> {
    write_html(w, "<h3 id=\"")?;
    write_html(w, &urlencoding::encode(id).to_owned())?;
    write_html(w, "\">")?;
    write_html_text(w, text)?;
    write_html_ln(w, "</h3>")
}

/// Write the HTML header of type 4.
pub fn write_html_header4(w: &mut dyn Write, text: &str) -> io::Result<()> {
    write_html(w, "<h4>")?;
    write_html_text(w, text)?;
    write_html_ln(w, "</h4>")
}

/// Write the HTML header of type 4 by the specified identifier.
pub fn write_html_header4_by_id(w: &mut dyn Write, id: &str, text: &str) -> io::Result<()> {
    write_html(w, "<h4 id=\"")?;
    write_html(w, &urlencoding::encode(id).to_owned())?;
    write_html(w, "\">")?;
    write_html_text(w, text)?;
    write_html_ln(w, "</h4>")
}

/// Write the HTML header of type 5.
pub fn write_html_header5(w: &mut dyn Write, text: &str) -> io::Result<()> {
    write_html(w, "<h5>")?;
    write_html_text(w, text)?;
    write_html_ln(w, "</h5>")
}

/// Write the HTML header of type 5 by the specified identifier.
pub fn write_html_header5_by_id(w: &mut dyn Write, id: &str, text: &str) -> io::Result<()> {
    write_html(w, "<h5 id=\"")?;
    write_html(w, &urlencoding::encode(id).to_owned())?;
    write_html(w, "\">")?;
    write_html_text(w, text)?;
    write_html_ln(w, "</h5>")
}

/// Write the HTML header of type 6.
pub fn write_html_header6(w: &mut dyn Write, text: &str) -> io::Result<()> {
    write_html(w, "<h6>")?;
    write_html_text(w, text)?;
    write_html_ln(w, "</h6>")
}

/// Write the HTML header of type 6 by the specified identifier.
pub fn write_html_header6_by_id(w: &mut dyn Write, id: &str, text: &str) -> io::Result<()> {
    write_html(w, "<h6 id=\"")?;
    write_html(w, &urlencoding::encode(id).to_owned())?;
    write_html(w, "\">")?;
    write_html_text(w, text)?;
    write_html_ln(w, "</h6>")
}

/// Write the HTML break element.
pub fn write_html_break(w: &mut dyn Write) -> io::Result<()> {
    write_html_ln(w, "<br />")
}

/// Begin the HTML list element.
pub fn begin_html_list(w: &mut dyn Write) -> io::Result<()> {
    write_html_ln(w, "<ul>")
}

/// End the HTML list element.
pub fn end_html_list(w: &mut dyn Write) -> io::Result<()> {
    write_html_ln(w, "</ul>")
}

/// Begin the HTML list item.
pub fn begin_html_list_item(w: &mut dyn Write) -> io::Result<()> {
    write_html(w, "<li>")
}

/// End the HTML list item.
pub fn end_html_list_item(w: &mut dyn Write) -> io::Result<()> {
    write_html_ln(w, "</li>")
}

/// Begin the HTML document.
pub fn begin_html_document(w: &mut dyn Write, title: &str) -> io::Result<()> {
    write_html_ln(w, "<html>")?;
    write_html_ln(w, "<head>")?;
    write_html_ln(w, "<meta http-equiv='Content-Type' content='text/html; charset=utf-8' />")?;
    write_html(w, "<title>")?;
    write_html_text(w, title)?;
    write_html_ln(w, "</title>")?;
    write_html_css(w)?;
    write_html_ln(w, "</head>")?;
    write_html_ln(w, "<body>")?;
    write_html_header1(w, title)
}

/// End the HTML document.
pub fn end_html_document(w: &mut dyn Write) -> io::Result<()> {
    write_html_break(w)?;
    begin_html_paragraph(w)?;
    write_html(w, "<font size=\"-1\">Automatically generated by ")?;
    write_html(w, "<a href='https://gitflic.ru/project/dsorokin/dvcompute'>DVCompute Simulator</a>")?;
    write_html_ln(w, "</font>")?;
    end_html_paragraph(w)?;
    write_html_ln(w, "</body>")?;
    write_html_ln(w, "</html>")
}

/// Write the CSS definition.
fn write_html_css(w: &mut dyn Write) -> io::Result<()> {
    write_html_ln(w, "<style type=\"text/css\">")?;
    write_html_ln(w, "* { margin: 0; padding: 0 }")?;
    write_html_ln(w, "")?;
    write_html_ln(w, "html {")?;
    write_html_ln(w, "  background-color: white;")?;
    write_html_ln(w, "  width: 100%;")?;
    write_html_ln(w, "  height: 100%;")?;
    write_html_ln(w, "}")?;
    write_html_ln(w, "")?;
    write_html_ln(w, "body {")?;
    write_html_ln(w, "  background: white;")?;
    write_html_ln(w, "  color: black;")?;
    write_html_ln(w, "  text-align: left;")?;
    write_html_ln(w, "  min-height: 100%;")?;
    write_html_ln(w, "  width: 90%;")?;
    write_html_ln(w, "  margin: 0px auto 0px auto;")?;
    write_html_ln(w, "  position: relative;")?;
    write_html_ln(w, "}")?;
    write_html_ln(w, "")?;
    write_html_ln(w, "p {")?;
    write_html_ln(w, "  margin: 0.8em 0;")?;
    write_html_ln(w, "}")?;
    write_html_ln(w, "")?;
    write_html_ln(w, "ul, ol {")?;
    write_html_ln(w, "  margin: 0.8em 0 0.8em 2em;")?;
    write_html_ln(w, "}")?;
    write_html_ln(w, "")?;
    write_html_ln(w, "dl {")?;
    write_html_ln(w, "  margin: 0.8em 0;")?;
    write_html_ln(w, "}")?;
    write_html_ln(w, "")?;
    write_html_ln(w, "dt {")?;
    write_html_ln(w, "  font-weight: bold;")?;
    write_html_ln(w, "}")?;
    write_html_ln(w, "")?;
    write_html_ln(w, "dd {")?;
    write_html_ln(w, "  margin-left: 2em;")?;
    write_html_ln(w, "}")?;
    write_html_ln(w, "")?;
    write_html_ln(w, "a { text-decoration: none; }")?;
    write_html_ln(w, "a[href]:link { color: rgb(196,69,29); }")?;
    write_html_ln(w, "a[href]:visited { color: rgb(171,105,84); }")?;
    write_html_ln(w, "a[href]:hover { text-decoration:underline; }")?;
    write_html_ln(w, "")?;
    write_html_ln(w, "body {")?;
    write_html_ln(w, "  font-size:medium;")?;
    write_html_ln(w, "}")?;
    write_html_ln(w, "")?;
    write_html_ln(w, "h1 { font-size: 146.5%; /* 19pt */ } ")?;
    write_html_ln(w, "h2 { font-size: 131%;   /* 17pt */ }")?;
    write_html_ln(w, "h3 { font-size: 116%;   /* 15pt */ }")?;
    write_html_ln(w, "h4 { font-size: 100%;   /* 13pt */ }")?;
    write_html_ln(w, "h5 { font-size: 100%;   /* 13pt */ }")?;
    write_html_ln(w, "")?;
    write_html_ln(w, "select, input, button, textarea {")?;
    write_html_ln(w, "  font:99% sans-serif;")?;
    write_html_ln(w, "}")?;
    write_html_ln(w, "")?;
    write_html_ln(w, "table {")?;
    write_html_ln(w, "  font-size:inherit;")?;
    write_html_ln(w, "  font:100%;")?;
    write_html_ln(w, "}")?;
    write_html_ln(w, "")?;
    write_html_ln(w, "pre, code, kbd, samp, tt, .src {")?;
    write_html_ln(w, "  font-family:monospace;")?;
    write_html_ln(w, "  *font-size:108%;")?;
    write_html_ln(w, "  line-height: 124%;")?;
    write_html_ln(w, "}")?;
    write_html_ln(w, "")?;
    write_html_ln(w, ".links, .link {")?;
    write_html_ln(w, "  font-size: 85%; /* 11pt */")?;
    write_html_ln(w, "}")?;
    write_html_ln(w, ".info  {")?;
    write_html_ln(w, "  font-size: 85%; /* 11pt */")?;
    write_html_ln(w, "}")?;
    write_html_ln(w, "")?;
    write_html_ln(w, ".caption, h1, h2, h3, h4, h5, h6 { ")?;
    write_html_ln(w, "  font-weight: bold;")?;
    write_html_ln(w, "  color: rgb(78,98,114);")?;
    write_html_ln(w, "  margin: 0.8em 0 0.4em;")?;
    write_html_ln(w, "}")?;
    write_html_ln(w, "")?;
    write_html_ln(w, "* + h1, * + h2, * + h3, * + h4, * + h5, * + h6 {")?;
    write_html_ln(w, "  margin-top: 2em;")?;
    write_html_ln(w, "}")?;
    write_html_ln(w, "")?;
    write_html_ln(w, "h1 + h2, h2 + h3, h3 + h4, h4 + h5, h5 + h6 {")?;
    write_html_ln(w, "  margin-top: inherit;")?;
    write_html_ln(w, "}")?;
    write_html_ln(w, "")?;
    write_html_ln(w, "ul.links {")?;
    write_html_ln(w, "  list-style: none;")?;
    write_html_ln(w, "  text-align: left;")?;
    write_html_ln(w, "  float: right;")?;
    write_html_ln(w, "  display: inline-table;")?;
    write_html_ln(w, "  margin: 0 0 0 1em;")?;
    write_html_ln(w, "}")?;
    write_html_ln(w, "")?;
    write_html_ln(w, "ul.links li {")?;
    write_html_ln(w, "  display: inline;")?;
    write_html_ln(w, "  border-left: 1px solid #d5d5d5; ")?;
    write_html_ln(w, "  white-space: nowrap;")?;
    write_html_ln(w, "  padding: 0;")?;
    write_html_ln(w, "}")?;
    write_html_ln(w, "")?;
    write_html_ln(w, "ul.links li a {")?;
    write_html_ln(w, "  padding: 0.2em 0.5em;")?;
    write_html_ln(w, "}")?;
    write_html_ln(w, "</style>")
}

/// Escape special HTML characters in the `String`.
/// It is based on one function from the Haskell package Web-Encodings,
/// which is licensed under BSD3 but obsolete now.
fn encode_html_text(s: &str) -> String {
    s.chars()
        .map(|c| { escape_html_char(c)} )
        .collect::<String>()
}

/// Escape a character.
fn escape_html_char(c: char) -> String {
    match c {
        '<'  => "&lt;".to_string(),
        '>'  => "&gt;".to_string(),
        '&'  => "&amp;".to_string(),
        '"'  => "&quot;".to_string(),
        '\'' => "&#39;".to_string(),
        c    => c.to_string()
    }
}