initial commit

This commit is contained in:
Harald Hoyer 2018-12-20 14:55:19 +01:00
commit cb1bf6dd17
42 changed files with 14060 additions and 0 deletions

4
FontAwesome/css/font-awesome.css vendored Normal file

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load diff

After

Width:  |  Height:  |  Size: 434 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

41
ace.js Normal file

File diff suppressed because one or more lines are too long

71
ayu-highlight.css Normal file
View file

@ -0,0 +1,71 @@
/*
Based off of the Ayu theme
Original by Dempfi (https://github.com/dempfi/ayu)
*/
.hljs {
display: block;
overflow-x: auto;
background: #191f26;
color: #e6e1cf;
padding: 0.5em;
}
.hljs-comment,
.hljs-quote,
.hljs-meta {
color: #5c6773;
font-style: italic;
}
.hljs-variable,
.hljs-template-variable,
.hljs-attribute,
.hljs-attr,
.hljs-regexp,
.hljs-link,
.hljs-selector-id,
.hljs-selector-class {
color: #ff7733;
}
.hljs-number,
.hljs-builtin-name,
.hljs-literal,
.hljs-type,
.hljs-params {
color: #ffee99;
}
.hljs-string,
.hljs-bullet {
color: #b8cc52;
}
.hljs-title,
.hljs-built_in,
.hljs-section {
color: #ffb454;
}
.hljs-keyword,
.hljs-selector-tag,
.hljs-symbol {
color: #ff7733;
}
.hljs-name {
color: #36a3d9;
}
.hljs-tag {
color: #00568d;
}
.hljs-emphasis {
font-style: italic;
}
.hljs-strong {
font-weight: bold;
}

611
book.js Normal file
View file

@ -0,0 +1,611 @@
"use strict";
// Fix back button cache problem
window.onunload = function () { };
// Global variable, shared between modules
function playpen_text(playpen) {
let code_block = playpen.querySelector("code");
if (window.ace && code_block.classList.contains("editable")) {
let editor = window.ace.edit(code_block);
return editor.getValue();
} else {
return code_block.textContent;
}
}
(function codeSnippets() {
// Hide Rust code lines prepended with a specific character
var hiding_character = "#";
function fetch_with_timeout(url, options, timeout = 6000) {
return Promise.race([
fetch(url, options),
new Promise((_, reject) => setTimeout(() => reject(new Error('timeout')), timeout))
]);
}
var playpens = Array.from(document.querySelectorAll(".playpen"));
if (playpens.length > 0) {
fetch_with_timeout("https://play.rust-lang.org/meta/crates", {
headers: {
'Content-Type': "application/json",
},
method: 'POST',
mode: 'cors',
})
.then(response => response.json())
.then(response => {
// get list of crates available in the rust playground
let playground_crates = response.crates.map(item => item["id"]);
playpens.forEach(block => handle_crate_list_update(block, playground_crates));
});
}
function handle_crate_list_update(playpen_block, playground_crates) {
// update the play buttons after receiving the response
update_play_button(playpen_block, playground_crates);
// and install on change listener to dynamically update ACE editors
if (window.ace) {
let code_block = playpen_block.querySelector("code");
if (code_block.classList.contains("editable")) {
let editor = window.ace.edit(code_block);
editor.addEventListener("change", function (e) {
update_play_button(playpen_block, playground_crates);
});
}
}
}
// updates the visibility of play button based on `no_run` class and
// used crates vs ones available on http://play.rust-lang.org
function update_play_button(pre_block, playground_crates) {
var play_button = pre_block.querySelector(".play-button");
// skip if code is `no_run`
if (pre_block.querySelector('code').classList.contains("no_run")) {
play_button.classList.add("hidden");
return;
}
// get list of `extern crate`'s from snippet
var txt = playpen_text(pre_block);
var re = /extern\s+crate\s+([a-zA-Z_0-9]+)\s*;/g;
var snippet_crates = [];
var item;
while (item = re.exec(txt)) {
snippet_crates.push(item[1]);
}
// check if all used crates are available on play.rust-lang.org
var all_available = snippet_crates.every(function (elem) {
return playground_crates.indexOf(elem) > -1;
});
if (all_available) {
play_button.classList.remove("hidden");
} else {
play_button.classList.add("hidden");
}
}
function run_rust_code(code_block) {
var result_block = code_block.querySelector(".result");
if (!result_block) {
result_block = document.createElement('code');
result_block.className = 'result hljs language-bash';
code_block.append(result_block);
}
let text = playpen_text(code_block);
var params = {
channel: "stable",
mode: "debug",
edition: "2018",
crateType: "bin",
tests: false,
code: text
};
if (text.indexOf("#![feature") !== -1) {
params.channel = "nightly";
}
if (text.indexOf("#[test]") !== -1) {
params.tests = "true";
}
if (text.indexOf("#![crate_type=\"lib\"]") !== -1) {
params.crateType = "lib";
}
result_block.innerText = "Running...";
fetch_with_timeout("https://play.rust-lang.org/execute", {
headers: {
'Content-Type': "application/json",
},
method: 'POST',
mode: 'cors',
body: JSON.stringify(params)
})
.then(response => response.json())
.then(response => result_block.innerText = response.stderr + "\n\n" + response.stdout)
.catch(error => result_block.innerText = "Playground Communication: " + error.message);
}
// Syntax highlighting Configuration
hljs.configure({
tabReplace: ' ', // 4 spaces
languages: [], // Languages used for auto-detection
});
if (window.ace) {
// language-rust class needs to be removed for editable
// blocks or highlightjs will capture events
Array
.from(document.querySelectorAll('code.editable'))
.forEach(function (block) { block.classList.remove('language-rust'); });
Array
.from(document.querySelectorAll('code:not(.editable)'))
.forEach(function (block) { hljs.highlightBlock(block); });
} else {
Array
.from(document.querySelectorAll('code'))
.forEach(function (block) { hljs.highlightBlock(block); });
}
// Adding the hljs class gives code blocks the color css
// even if highlighting doesn't apply
Array
.from(document.querySelectorAll('code'))
.forEach(function (block) { block.classList.add('hljs'); });
Array.from(document.querySelectorAll("code.language-rust")).forEach(function (block) {
var code_block = block;
var pre_block = block.parentNode;
// hide lines
var lines = code_block.innerHTML.split("\n");
var first_non_hidden_line = false;
var lines_hidden = false;
var trimmed_line = "";
for (var n = 0; n < lines.length; n++) {
trimmed_line = lines[n].trim();
if (trimmed_line[0] == hiding_character && trimmed_line[1] != hiding_character) {
if (first_non_hidden_line) {
lines[n] = "<span class=\"hidden\">" + "\n" + lines[n].replace(/(\s*)# ?/, "$1") + "</span>";
}
else {
lines[n] = "<span class=\"hidden\">" + lines[n].replace(/(\s*)# ?/, "$1") + "\n" + "</span>";
}
lines_hidden = true;
}
else if (first_non_hidden_line) {
lines[n] = "\n" + lines[n];
}
else {
first_non_hidden_line = true;
}
if (trimmed_line[0] == hiding_character && trimmed_line[1] == hiding_character) {
lines[n] = lines[n].replace("##", "#")
}
}
code_block.innerHTML = lines.join("");
// If no lines were hidden, return
if (!lines_hidden) { return; }
var buttons = document.createElement('div');
buttons.className = 'buttons';
buttons.innerHTML = "<button class=\"fa fa-expand\" title=\"Show hidden lines\" aria-label=\"Show hidden lines\"></button>";
// add expand button
pre_block.insertBefore(buttons, pre_block.firstChild);
pre_block.querySelector('.buttons').addEventListener('click', function (e) {
if (e.target.classList.contains('fa-expand')) {
var lines = pre_block.querySelectorAll('span.hidden');
e.target.classList.remove('fa-expand');
e.target.classList.add('fa-compress');
e.target.title = 'Hide lines';
e.target.setAttribute('aria-label', e.target.title);
Array.from(lines).forEach(function (line) {
line.classList.remove('hidden');
line.classList.add('unhidden');
});
} else if (e.target.classList.contains('fa-compress')) {
var lines = pre_block.querySelectorAll('span.unhidden');
e.target.classList.remove('fa-compress');
e.target.classList.add('fa-expand');
e.target.title = 'Show hidden lines';
e.target.setAttribute('aria-label', e.target.title);
Array.from(lines).forEach(function (line) {
line.classList.remove('unhidden');
line.classList.add('hidden');
});
}
});
});
Array.from(document.querySelectorAll('pre code')).forEach(function (block) {
var pre_block = block.parentNode;
if (!pre_block.classList.contains('playpen')) {
var buttons = pre_block.querySelector(".buttons");
if (!buttons) {
buttons = document.createElement('div');
buttons.className = 'buttons';
pre_block.insertBefore(buttons, pre_block.firstChild);
}
var clipButton = document.createElement('button');
clipButton.className = 'fa fa-copy clip-button';
clipButton.title = 'Copy to clipboard';
clipButton.setAttribute('aria-label', clipButton.title);
clipButton.innerHTML = '<i class=\"tooltiptext\"></i>';
buttons.insertBefore(clipButton, buttons.firstChild);
}
});
// Process playpen code blocks
Array.from(document.querySelectorAll(".playpen")).forEach(function (pre_block) {
// Add play button
var buttons = pre_block.querySelector(".buttons");
if (!buttons) {
buttons = document.createElement('div');
buttons.className = 'buttons';
pre_block.insertBefore(buttons, pre_block.firstChild);
}
var runCodeButton = document.createElement('button');
runCodeButton.className = 'fa fa-play play-button';
runCodeButton.hidden = true;
runCodeButton.title = 'Run this code';
runCodeButton.setAttribute('aria-label', runCodeButton.title);
var copyCodeClipboardButton = document.createElement('button');
copyCodeClipboardButton.className = 'fa fa-copy clip-button';
copyCodeClipboardButton.innerHTML = '<i class="tooltiptext"></i>';
copyCodeClipboardButton.title = 'Copy to clipboard';
copyCodeClipboardButton.setAttribute('aria-label', copyCodeClipboardButton.title);
buttons.insertBefore(runCodeButton, buttons.firstChild);
buttons.insertBefore(copyCodeClipboardButton, buttons.firstChild);
runCodeButton.addEventListener('click', function (e) {
run_rust_code(pre_block);
});
let code_block = pre_block.querySelector("code");
if (window.ace && code_block.classList.contains("editable")) {
var undoChangesButton = document.createElement('button');
undoChangesButton.className = 'fa fa-history reset-button';
undoChangesButton.title = 'Undo changes';
undoChangesButton.setAttribute('aria-label', undoChangesButton.title);
buttons.insertBefore(undoChangesButton, buttons.firstChild);
undoChangesButton.addEventListener('click', function () {
let editor = window.ace.edit(code_block);
editor.setValue(editor.originalCode);
editor.clearSelection();
});
}
});
})();
(function themes() {
var html = document.querySelector('html');
var themeToggleButton = document.getElementById('theme-toggle');
var themePopup = document.getElementById('theme-list');
var themeColorMetaTag = document.querySelector('meta[name="theme-color"]');
var stylesheets = {
ayuHighlight: document.querySelector("[href$='ayu-highlight.css']"),
tomorrowNight: document.querySelector("[href$='tomorrow-night.css']"),
highlight: document.querySelector("[href$='highlight.css']"),
};
function showThemes() {
themePopup.style.display = 'block';
themeToggleButton.setAttribute('aria-expanded', true);
themePopup.querySelector("button#" + document.body.className).focus();
}
function hideThemes() {
themePopup.style.display = 'none';
themeToggleButton.setAttribute('aria-expanded', false);
themeToggleButton.focus();
}
function set_theme(theme) {
let ace_theme;
if (theme == 'coal' || theme == 'navy') {
stylesheets.ayuHighlight.disabled = true;
stylesheets.tomorrowNight.disabled = false;
stylesheets.highlight.disabled = true;
ace_theme = "ace/theme/tomorrow_night";
} else if (theme == 'ayu') {
stylesheets.ayuHighlight.disabled = false;
stylesheets.tomorrowNight.disabled = true;
stylesheets.highlight.disabled = true;
ace_theme = "ace/theme/tomorrow_night";
} else {
stylesheets.ayuHighlight.disabled = true;
stylesheets.tomorrowNight.disabled = true;
stylesheets.highlight.disabled = false;
ace_theme = "ace/theme/dawn";
}
setTimeout(function () {
themeColorMetaTag.content = getComputedStyle(document.body).backgroundColor;
}, 1);
if (window.ace && window.editors) {
window.editors.forEach(function (editor) {
editor.setTheme(ace_theme);
});
}
var previousTheme;
try { previousTheme = localStorage.getItem('mdbook-theme'); } catch (e) { }
if (previousTheme === null || previousTheme === undefined) { previousTheme = default_theme; }
try { localStorage.setItem('mdbook-theme', theme); } catch (e) { }
document.body.className = theme;
html.classList.remove(previousTheme);
html.classList.add(theme);
}
// Set theme
var theme;
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
if (theme === null || theme === undefined) { theme = default_theme; }
set_theme(theme);
themeToggleButton.addEventListener('click', function () {
if (themePopup.style.display === 'block') {
hideThemes();
} else {
showThemes();
}
});
themePopup.addEventListener('click', function (e) {
var theme = e.target.id || e.target.parentElement.id;
set_theme(theme);
});
themePopup.addEventListener('focusout', function(e) {
// e.relatedTarget is null in Safari and Firefox on macOS (see workaround below)
if (!!e.relatedTarget && !themeToggleButton.contains(e.relatedTarget) && !themePopup.contains(e.relatedTarget)) {
hideThemes();
}
});
// Should not be needed, but it works around an issue on macOS & iOS: https://github.com/rust-lang-nursery/mdBook/issues/628
document.addEventListener('click', function(e) {
if (themePopup.style.display === 'block' && !themeToggleButton.contains(e.target) && !themePopup.contains(e.target)) {
hideThemes();
}
});
document.addEventListener('keydown', function (e) {
if (e.altKey || e.ctrlKey || e.metaKey || e.shiftKey) { return; }
if (!themePopup.contains(e.target)) { return; }
switch (e.key) {
case 'Escape':
e.preventDefault();
hideThemes();
break;
case 'ArrowUp':
e.preventDefault();
var li = document.activeElement.parentElement;
if (li && li.previousElementSibling) {
li.previousElementSibling.querySelector('button').focus();
}
break;
case 'ArrowDown':
e.preventDefault();
var li = document.activeElement.parentElement;
if (li && li.nextElementSibling) {
li.nextElementSibling.querySelector('button').focus();
}
break;
case 'Home':
e.preventDefault();
themePopup.querySelector('li:first-child button').focus();
break;
case 'End':
e.preventDefault();
themePopup.querySelector('li:last-child button').focus();
break;
}
});
})();
(function sidebar() {
var html = document.querySelector("html");
var sidebar = document.getElementById("sidebar");
var sidebarLinks = document.querySelectorAll('#sidebar a');
var sidebarToggleButton = document.getElementById("sidebar-toggle");
var firstContact = null;
function showSidebar() {
html.classList.remove('sidebar-hidden')
html.classList.add('sidebar-visible');
Array.from(sidebarLinks).forEach(function (link) {
link.setAttribute('tabIndex', 0);
});
sidebarToggleButton.setAttribute('aria-expanded', true);
sidebar.setAttribute('aria-hidden', false);
try { localStorage.setItem('mdbook-sidebar', 'visible'); } catch (e) { }
}
function hideSidebar() {
html.classList.remove('sidebar-visible')
html.classList.add('sidebar-hidden');
Array.from(sidebarLinks).forEach(function (link) {
link.setAttribute('tabIndex', -1);
});
sidebarToggleButton.setAttribute('aria-expanded', false);
sidebar.setAttribute('aria-hidden', true);
try { localStorage.setItem('mdbook-sidebar', 'hidden'); } catch (e) { }
}
// Toggle sidebar
sidebarToggleButton.addEventListener('click', function sidebarToggle() {
if (html.classList.contains("sidebar-hidden")) {
showSidebar();
} else if (html.classList.contains("sidebar-visible")) {
hideSidebar();
} else {
if (getComputedStyle(sidebar)['transform'] === 'none') {
hideSidebar();
} else {
showSidebar();
}
}
});
document.addEventListener('touchstart', function (e) {
firstContact = {
x: e.touches[0].clientX,
time: Date.now()
};
}, { passive: true });
document.addEventListener('touchmove', function (e) {
if (!firstContact)
return;
var curX = e.touches[0].clientX;
var xDiff = curX - firstContact.x,
tDiff = Date.now() - firstContact.time;
if (tDiff < 250 && Math.abs(xDiff) >= 150) {
if (xDiff >= 0 && firstContact.x < Math.min(document.body.clientWidth * 0.25, 300))
showSidebar();
else if (xDiff < 0 && curX < 300)
hideSidebar();
firstContact = null;
}
}, { passive: true });
// Scroll sidebar to current active section
var activeSection = sidebar.querySelector(".active");
if (activeSection) {
sidebar.scrollTop = activeSection.offsetTop;
}
})();
(function chapterNavigation() {
document.addEventListener('keydown', function (e) {
if (e.altKey || e.ctrlKey || e.metaKey || e.shiftKey) { return; }
if (window.search && window.search.hasFocus()) { return; }
switch (e.key) {
case 'ArrowRight':
e.preventDefault();
var nextButton = document.querySelector('.nav-chapters.next');
if (nextButton) {
window.location.href = nextButton.href;
}
break;
case 'ArrowLeft':
e.preventDefault();
var previousButton = document.querySelector('.nav-chapters.previous');
if (previousButton) {
window.location.href = previousButton.href;
}
break;
}
});
})();
(function clipboard() {
var clipButtons = document.querySelectorAll('.clip-button');
function hideTooltip(elem) {
elem.firstChild.innerText = "";
elem.className = 'fa fa-copy clip-button';
}
function showTooltip(elem, msg) {
elem.firstChild.innerText = msg;
elem.className = 'fa fa-copy tooltipped';
}
var clipboardSnippets = new Clipboard('.clip-button', {
text: function (trigger) {
hideTooltip(trigger);
let playpen = trigger.closest("pre");
return playpen_text(playpen);
}
});
Array.from(clipButtons).forEach(function (clipButton) {
clipButton.addEventListener('mouseout', function (e) {
hideTooltip(e.currentTarget);
});
});
clipboardSnippets.on('success', function (e) {
e.clearSelection();
showTooltip(e.trigger, "Copied!");
});
clipboardSnippets.on('error', function (e) {
showTooltip(e.trigger, "Clipboard error!");
});
})();
(function scrollToTop () {
var menuTitle = document.querySelector('.menu-title');
menuTitle.addEventListener('click', function () {
document.scrollingElement.scrollTo({ top: 0, behavior: 'smooth' });
});
})();
(function autoHideMenu() {
var menu = document.getElementById('menu-bar');
var previousScrollTop = document.scrollingElement.scrollTop;
document.addEventListener('scroll', function () {
if (menu.classList.contains('folded') && document.scrollingElement.scrollTop < previousScrollTop) {
menu.classList.remove('folded');
} else if (!menu.classList.contains('folded') && document.scrollingElement.scrollTop > previousScrollTop) {
menu.classList.add('folded');
}
if (!menu.classList.contains('bordered') && document.scrollingElement.scrollTop > 0) {
menu.classList.add('bordered');
}
if (menu.classList.contains('bordered') && document.scrollingElement.scrollTop === 0) {
menu.classList.remove('bordered');
}
previousScrollTop = document.scrollingElement.scrollTop;
}, { passive: true });
})();

7
clipboard.min.js vendored Normal file

File diff suppressed because one or more lines are too long

420
css/chrome.css Normal file
View file

@ -0,0 +1,420 @@
/* CSS for UI elements (a.k.a. chrome) */
@import 'variables.css';
::-webkit-scrollbar {
background: var(--bg);
}
::-webkit-scrollbar-thumb {
background: var(--scrollbar);
}
#searchresults a,
.content a:link,
a:visited,
a > .hljs {
color: var(--links);
}
/* Menu Bar */
#menu-bar {
position: -webkit-sticky;
position: sticky;
top: 0;
z-index: 101;
margin: auto calc(0px - var(--page-padding));
}
#menu-bar > #menu-bar-sticky-container {
display: flex;
flex-wrap: wrap;
background-color: var(--bg);
border-bottom-color: var(--bg);
border-bottom-width: 1px;
border-bottom-style: solid;
}
.js #menu-bar > #menu-bar-sticky-container {
transition: transform 0.3s;
}
#menu-bar.bordered > #menu-bar-sticky-container {
border-bottom-color: var(--table-border-color);
}
#menu-bar i, #menu-bar .icon-button {
position: relative;
padding: 0 8px;
z-index: 10;
line-height: 50px;
cursor: pointer;
transition: color 0.5s;
}
@media only screen and (max-width: 420px) {
#menu-bar i, #menu-bar .icon-button {
padding: 0 5px;
}
}
.icon-button {
border: none;
background: none;
padding: 0;
color: inherit;
}
.icon-button i {
margin: 0;
}
.right-buttons {
margin: 0 15px;
}
.right-buttons a {
text-decoration: none;
}
html:not(.sidebar-visible) #menu-bar:not(:hover).folded > #menu-bar-sticky-container {
transform: translateY(-60px);
}
.left-buttons {
display: flex;
margin: 0 5px;
}
.no-js .left-buttons {
display: none;
}
.menu-title {
display: inline-block;
font-weight: 200;
font-size: 20px;
line-height: 50px;
text-align: center;
margin: 0;
flex: 1;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.js .menu-title {
cursor: pointer;
}
.menu-bar,
.menu-bar:visited,
.nav-chapters,
.nav-chapters:visited,
.mobile-nav-chapters,
.mobile-nav-chapters:visited,
.menu-bar .icon-button,
.menu-bar a i {
color: var(--icons);
}
.menu-bar i:hover,
.menu-bar .icon-button:hover,
.nav-chapters:hover,
.mobile-nav-chapters i:hover {
color: var(--icons-hover);
}
/* Nav Icons */
.nav-chapters {
font-size: 2.5em;
text-align: center;
text-decoration: none;
position: fixed;
top: 50px; /* Height of menu-bar */
bottom: 0;
margin: 0;
max-width: 150px;
min-width: 90px;
display: flex;
justify-content: center;
align-content: center;
flex-direction: column;
transition: color 0.5s;
}
.nav-chapters:hover { text-decoration: none; }
.nav-wrapper {
margin-top: 50px;
display: none;
}
.mobile-nav-chapters {
font-size: 2.5em;
text-align: center;
text-decoration: none;
width: 90px;
border-radius: 5px;
background-color: var(--sidebar-bg);
}
.previous {
float: left;
}
.next {
float: right;
right: var(--page-padding);
}
@media only screen and (max-width: 1080px) {
.nav-wide-wrapper { display: none; }
.nav-wrapper { display: block; }
}
@media only screen and (max-width: 1380px) {
.sidebar-visible .nav-wide-wrapper { display: none; }
.sidebar-visible .nav-wrapper { display: block; }
}
/* Inline code */
:not(pre) > .hljs {
display: inline-block;
vertical-align: middle;
padding: 0.1em 0.3em;
border-radius: 3px;
color: var(--inline-code-color);
}
a:hover > .hljs {
text-decoration: underline;
}
pre {
position: relative;
}
pre > .buttons {
position: absolute;
z-index: 100;
right: 5px;
top: 5px;
color: var(--sidebar-fg);
cursor: pointer;
}
pre > .buttons :hover {
color: var(--sidebar-active);
}
pre > .buttons i {
margin-left: 8px;
}
pre > .buttons button {
color: inherit;
background: transparent;
border: none;
cursor: inherit;
}
pre > .result {
margin-top: 10px;
}
/* Search */
#searchresults a {
text-decoration: none;
}
mark {
border-radius: 2px;
padding: 0 3px 1px 3px;
margin: 0 -3px -1px -3px;
background-color: var(--search-mark-bg);
transition: background-color 300ms linear;
cursor: pointer;
}
mark.fade-out {
background-color: rgba(0,0,0,0) !important;
cursor: auto;
}
.searchbar-outer {
margin-left: auto;
margin-right: auto;
max-width: var(--content-max-width);
}
#searchbar {
width: 100%;
margin: 5px auto 0px auto;
padding: 10px 16px;
transition: box-shadow 300ms ease-in-out;
border: 1px solid var(--searchbar-border-color);
border-radius: 3px;
background-color: var(--searchbar-bg);
color: var(--searchbar-fg);
}
#searchbar:focus,
#searchbar.active {
box-shadow: 0 0 3px var(--searchbar-shadow-color);
}
.searchresults-header {
font-weight: bold;
font-size: 1em;
padding: 18px 0 0 5px;
color: var(--searchresults-header-fg);
}
.searchresults-outer {
margin-left: auto;
margin-right: auto;
max-width: var(--content-max-width);
border-bottom: 1px dashed var(--searchresults-border-color);
}
ul#searchresults {
list-style: none;
padding-left: 20px;
}
ul#searchresults li {
margin: 10px 0px;
padding: 2px;
border-radius: 2px;
}
ul#searchresults li.focus {
background-color: var(--searchresults-li-bg);
}
ul#searchresults span.teaser {
display: block;
clear: both;
margin: 5px 0 0 20px;
font-size: 0.8em;
}
ul#searchresults span.teaser em {
font-weight: bold;
font-style: normal;
}
/* Sidebar */
.sidebar {
position: fixed;
left: 0;
top: 0;
bottom: 0;
width: var(--sidebar-width);
overflow-y: auto;
padding: 10px 10px;
font-size: 0.875em;
box-sizing: border-box;
-webkit-overflow-scrolling: touch;
overscroll-behavior-y: contain;
background-color: var(--sidebar-bg);
color: var(--sidebar-fg);
}
.js .sidebar {
transition: transform 0.3s; /* Animation: slide away */
}
.sidebar code {
line-height: 2em;
}
.sidebar-hidden .sidebar {
transform: translateX(calc(0px - var(--sidebar-width)));
}
.sidebar::-webkit-scrollbar {
background: var(--sidebar-bg);
}
.sidebar::-webkit-scrollbar-thumb {
background: var(--scrollbar);
}
.sidebar-visible .page-wrapper {
transform: translateX(var(--sidebar-width));
}
@media only screen and (min-width: 620px) {
.sidebar-visible .page-wrapper {
transform: none;
margin-left: var(--sidebar-width);
}
}
.chapter {
list-style: none outside none;
padding-left: 0;
line-height: 2.2em;
}
.chapter li {
color: var(--sidebar-non-existant);
}
.chapter li a {
color: var(--sidebar-fg);
display: block;
padding: 0;
text-decoration: none;
}
.chapter li a:hover { text-decoration: none }
.chapter li .active,
a:hover {
/* Animate color change */
color: var(--sidebar-active);
}
.spacer {
width: 100%;
height: 3px;
margin: 5px 0px;
}
.chapter .spacer {
background-color: var(--sidebar-spacer);
}
@media (-moz-touch-enabled: 1), (pointer: coarse) {
.chapter li a { padding: 5px 0; }
.spacer { margin: 10px 0; }
}
.section {
list-style: none outside none;
padding-left: 20px;
line-height: 1.9em;
}
/* Theme Menu Popup */
.theme-popup {
position: absolute;
left: 10px;
top: 50px;
z-index: 1000;
border-radius: 4px;
font-size: 0.7em;
color: var(--fg);
background: var(--theme-popup-bg);
border: 1px solid var(--theme-popup-border);
margin: 0;
padding: 0;
list-style: none;
display: none;
}
.theme-popup .default {
color: var(--icons);
}
.theme-popup .theme {
width: 100%;
border: 0;
margin: 0;
padding: 2px 10px;
line-height: 25px;
white-space: nowrap;
text-align: left;
cursor: pointer;
color: inherit;
background: inherit;
font-size: inherit;
}
.theme-popup .theme:hover {
background-color: var(--theme-hover);
}
.theme-popup .theme:hover:first-child,
.theme-popup .theme:hover:last-child {
border-top-left-radius: inherit;
border-top-right-radius: inherit;
}

144
css/general.css Normal file
View file

@ -0,0 +1,144 @@
/* Base styles and content styles */
@import 'variables.css';
html {
font-family: "Open Sans", sans-serif;
color: var(--fg);
background-color: var(--bg);
text-size-adjust: none;
}
body {
margin: 0;
font-size: 1rem;
overflow-x: hidden;
}
code {
font-family: "Source Code Pro", Consolas, "Ubuntu Mono", Menlo, "DejaVu Sans Mono", monospace, monospace;
font-size: 0.875em; /* please adjust the ace font size accordingly in editor.js */
}
.left { float: left; }
.right { float: right; }
.hidden { display: none; }
.play-button.hidden { display: none; }
h2, h3 { margin-top: 2.5em; }
h4, h5 { margin-top: 2em; }
.header + .header h3,
.header + .header h4,
.header + .header h5 {
margin-top: 1em;
}
a.header:target h1:before,
a.header:target h2:before,
a.header:target h3:before,
a.header:target h4:before {
display: inline-block;
content: "»";
margin-left: -30px;
width: 30px;
}
.page {
outline: 0;
padding: 0 var(--page-padding);
}
.page-wrapper {
box-sizing: border-box;
}
.js .page-wrapper {
transition: margin-left 0.3s ease, transform 0.3s ease; /* Animation: slide away */
}
.content {
overflow-y: auto;
padding: 0 15px;
padding-bottom: 50px;
}
.content main {
margin-left: auto;
margin-right: auto;
max-width: var(--content-max-width);
}
.content a { text-decoration: none; }
.content a:hover { text-decoration: underline; }
.content img { max-width: 100%; }
.content .header:link,
.content .header:visited {
color: var(--fg);
}
.content .header:link,
.content .header:visited:hover {
text-decoration: none;
}
table {
margin: 0 auto;
border-collapse: collapse;
}
table td {
padding: 3px 20px;
border: 1px var(--table-border-color) solid;
}
table thead {
background: var(--table-header-bg);
}
table thead td {
font-weight: 700;
border: none;
}
table thead tr {
border: 1px var(--table-header-bg) solid;
}
/* Alternate background colors for rows */
table tbody tr:nth-child(2n) {
background: var(--table-alternate-bg);
}
blockquote {
margin: 20px 0;
padding: 0 20px;
color: var(--fg);
background-color: var(--quote-bg);
border-top: .1em solid var(--quote-border);
border-bottom: .1em solid var(--quote-border);
}
:not(.footnote-definition) + .footnote-definition,
.footnote-definition + :not(.footnote-definition) {
margin-top: 2em;
}
.footnote-definition {
font-size: 0.9em;
margin: 0.5em 0;
}
.footnote-definition p {
display: inline;
}
.tooltiptext {
position: absolute;
visibility: hidden;
color: #fff;
background-color: #333;
transform: translateX(-50%); /* Center by moving tooltip 50% of its width left */
left: -8px; /* Half of the width of the icon */
top: -35px;
font-size: 0.8em;
text-align: center;
border-radius: 6px;
padding: 5px 8px;
margin: 5px;
z-index: 1000;
}
.tooltipped .tooltiptext {
visibility: visible;
}

54
css/print.css Normal file
View file

@ -0,0 +1,54 @@
#sidebar,
#menu-bar,
.nav-chapters,
.mobile-nav-chapters {
display: none;
}
#page-wrapper.page-wrapper {
transform: none;
margin-left: 0px;
overflow-y: initial;
}
#content {
max-width: none;
margin: 0;
padding: 0;
}
.page {
overflow-y: initial;
}
code {
background-color: #666666;
border-radius: 5px;
/* Force background to be printed in Chrome */
-webkit-print-color-adjust: exact;
}
pre > .buttons {
z-index: 2;
}
a, a:visited, a:active, a:hover {
color: #4183c4;
text-decoration: none;
}
h1, h2, h3, h4, h5, h6 {
page-break-inside: avoid;
page-break-after: avoid;
}
pre, code {
page-break-inside: avoid;
white-space: pre-wrap;
}
.fa {
display: none !important;
}

210
css/variables.css Normal file
View file

@ -0,0 +1,210 @@
/* Globals */
:root {
--sidebar-width: 300px;
--page-padding: 15px;
--content-max-width: 750px;
}
/* Themes */
.ayu {
--bg: hsl(210, 25%, 8%);
--fg: #c5c5c5;
--sidebar-bg: #14191f;
--sidebar-fg: #c8c9db;
--sidebar-non-existant: #5c6773;
--sidebar-active: #ffb454;
--sidebar-spacer: #2d334f;
--scrollbar: var(--sidebar-fg);
--icons: #737480;
--icons-hover: #b7b9cc;
--links: #0096cf;
--inline-code-color: #ffb454;
--theme-popup-bg: #14191f;
--theme-popup-border: #5c6773;
--theme-hover: #191f26;
--quote-bg: hsl(226, 15%, 17%);
--quote-border: hsl(226, 15%, 22%);
--table-border-color: hsl(210, 25%, 13%);
--table-header-bg: hsl(210, 25%, 28%);
--table-alternate-bg: hsl(210, 25%, 11%);
--searchbar-border-color: #848484;
--searchbar-bg: #424242;
--searchbar-fg: #fff;
--searchbar-shadow-color: #d4c89f;
--searchresults-header-fg: #666;
--searchresults-border-color: #888;
--searchresults-li-bg: #252932;
--search-mark-bg: #e3b171;
}
.coal {
--bg: hsl(200, 7%, 8%);
--fg: #98a3ad;
--sidebar-bg: #292c2f;
--sidebar-fg: #a1adb8;
--sidebar-non-existant: #505254;
--sidebar-active: #3473ad;
--sidebar-spacer: #393939;
--scrollbar: var(--sidebar-fg);
--icons: #43484d;
--icons-hover: #b3c0cc;
--links: #2b79a2;
--inline-code-color: #c5c8c6;;
--theme-popup-bg: #141617;
--theme-popup-border: #43484d;
--theme-hover: #1f2124;
--quote-bg: hsl(234, 21%, 18%);
--quote-border: hsl(234, 21%, 23%);
--table-border-color: hsl(200, 7%, 13%);
--table-header-bg: hsl(200, 7%, 28%);
--table-alternate-bg: hsl(200, 7%, 11%);
--searchbar-border-color: #aaa;
--searchbar-bg: #b7b7b7;
--searchbar-fg: #000;
--searchbar-shadow-color: #aaa;
--searchresults-header-fg: #666;
--searchresults-border-color: #98a3ad;
--searchresults-li-bg: #2b2b2f;
--search-mark-bg: #355c7d;
}
.light {
--bg: hsl(0, 0%, 100%);
--fg: #333333;
--sidebar-bg: #fafafa;
--sidebar-fg: #364149;
--sidebar-non-existant: #aaaaaa;
--sidebar-active: #008cff;
--sidebar-spacer: #f4f4f4;
--scrollbar: #cccccc;
--icons: #cccccc;
--icons-hover: #333333;
--links: #4183c4;
--inline-code-color: #6e6b5e;
--theme-popup-bg: #fafafa;
--theme-popup-border: #cccccc;
--theme-hover: #e6e6e6;
--quote-bg: hsl(197, 37%, 96%);
--quote-border: hsl(197, 37%, 91%);
--table-border-color: hsl(0, 0%, 95%);
--table-header-bg: hsl(0, 0%, 80%);
--table-alternate-bg: hsl(0, 0%, 97%);
--searchbar-border-color: #aaa;
--searchbar-bg: #fafafa;
--searchbar-fg: #000;
--searchbar-shadow-color: #aaa;
--searchresults-header-fg: #666;
--searchresults-border-color: #888;
--searchresults-li-bg: #e4f2fe;
--search-mark-bg: #a2cff5;
}
.navy {
--bg: hsl(226, 23%, 11%);
--fg: #bcbdd0;
--sidebar-bg: #282d3f;
--sidebar-fg: #c8c9db;
--sidebar-non-existant: #505274;
--sidebar-active: #2b79a2;
--sidebar-spacer: #2d334f;
--scrollbar: var(--sidebar-fg);
--icons: #737480;
--icons-hover: #b7b9cc;
--links: #2b79a2;
--inline-code-color: #c5c8c6;;
--theme-popup-bg: #161923;
--theme-popup-border: #737480;
--theme-hover: #282e40;
--quote-bg: hsl(226, 15%, 17%);
--quote-border: hsl(226, 15%, 22%);
--table-border-color: hsl(226, 23%, 16%);
--table-header-bg: hsl(226, 23%, 31%);
--table-alternate-bg: hsl(226, 23%, 14%);
--searchbar-border-color: #aaa;
--searchbar-bg: #aeaec6;
--searchbar-fg: #000;
--searchbar-shadow-color: #aaa;
--searchresults-header-fg: #5f5f71;
--searchresults-border-color: #5c5c68;
--searchresults-li-bg: #242430;
--search-mark-bg: #a2cff5;
}
.rust {
--bg: hsl(60, 9%, 87%);
--fg: #262625;
--sidebar-bg: #3b2e2a;
--sidebar-fg: #c8c9db;
--sidebar-non-existant: #505254;
--sidebar-active: #e69f67;
--sidebar-spacer: #45373a;
--scrollbar: var(--sidebar-fg);
--icons: #737480;
--icons-hover: #262625;
--links: #2b79a2;
--inline-code-color: #6e6b5e;
--theme-popup-bg: #e1e1db;
--theme-popup-border: #b38f6b;
--theme-hover: #99908a;
--quote-bg: hsl(60, 5%, 75%);
--quote-border: hsl(60, 5%, 70%);
--table-border-color: hsl(60, 9%, 82%);
--table-header-bg: #b3a497;
--table-alternate-bg: hsl(60, 9%, 84%);
--searchbar-border-color: #aaa;
--searchbar-bg: #fafafa;
--searchbar-fg: #000;
--searchbar-shadow-color: #aaa;
--searchresults-header-fg: #666;
--searchresults-border-color: #888;
--searchresults-li-bg: #dec2a2;
--search-mark-bg: #e69f67;
}

1
docs/.nojekyll Normal file
View file

@ -0,0 +1 @@
This file makes sure that Github Pages doesn't process mdBook's output.

27
editor.js Normal file
View file

@ -0,0 +1,27 @@
"use strict";
window.editors = [];
(function(editors) {
if (typeof(ace) === 'undefined' || !ace) {
return;
}
Array.from(document.querySelectorAll('.editable')).forEach(function(editable) {
let editor = ace.edit(editable);
editor.setOptions({
highlightActiveLine: false,
showPrintMargin: false,
showLineNumbers: false,
showGutter: false,
maxLines: Infinity,
fontSize: "0.875em" // please adjust the font size of the code in general.styl
});
editor.$blockScrolling = Infinity;
editor.getSession().setMode("ace/mode/rust");
editor.originalCode = editor.getValue();
editors.push(editor);
});
})(window.editors);

10
elasticlunr.min.js vendored Normal file

File diff suppressed because one or more lines are too long

BIN
favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

69
highlight.css Normal file
View file

@ -0,0 +1,69 @@
/* Base16 Atelier Dune Light - Theme */
/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/dune) */
/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */
/* Atelier-Dune Comment */
.hljs-comment,
.hljs-quote {
color: #AAA;
}
/* Atelier-Dune Red */
.hljs-variable,
.hljs-template-variable,
.hljs-attribute,
.hljs-tag,
.hljs-name,
.hljs-regexp,
.hljs-link,
.hljs-name,
.hljs-selector-id,
.hljs-selector-class {
color: #d73737;
}
/* Atelier-Dune Orange */
.hljs-number,
.hljs-meta,
.hljs-built_in,
.hljs-builtin-name,
.hljs-literal,
.hljs-type,
.hljs-params {
color: #b65611;
}
/* Atelier-Dune Green */
.hljs-string,
.hljs-symbol,
.hljs-bullet {
color: #60ac39;
}
/* Atelier-Dune Blue */
.hljs-title,
.hljs-section {
color: #6684e1;
}
/* Atelier-Dune Purple */
.hljs-keyword,
.hljs-selector-tag {
color: #b854d4;
}
.hljs {
display: block;
overflow-x: auto;
background: #f1f1f1;
color: #6e6b5e;
padding: 0.5em;
}
.hljs-emphasis {
font-style: italic;
}
.hljs-strong {
font-weight: bold;
}

2
highlight.js Normal file

File diff suppressed because one or more lines are too long

219
index.html Normal file
View file

@ -0,0 +1,219 @@
<!DOCTYPE HTML>
<html lang="en" class="sidebar-visible no-js">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>Chapter 1 - chainerror</title>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#ffffff" />
<link rel="shortcut icon" href="favicon.png">
<link rel="stylesheet" href="css/variables.css">
<link rel="stylesheet" href="css/general.css">
<link rel="stylesheet" href="css/chrome.css">
<link rel="stylesheet" href="css/print.css" media="print">
<!-- Fonts -->
<link rel="stylesheet" href="FontAwesome/css/font-awesome.css">
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800" rel="stylesheet" type="text/css">
<link href="https://fonts.googleapis.com/css?family=Source+Code+Pro:500" rel="stylesheet" type="text/css">
<!-- Highlight.js Stylesheets -->
<link rel="stylesheet" href="highlight.css">
<link rel="stylesheet" href="tomorrow-night.css">
<link rel="stylesheet" href="ayu-highlight.css">
<!-- Custom theme stylesheets -->
</head>
<body class="light">
<!-- Provide site root to javascript -->
<script type="text/javascript">
var path_to_root = "";
var default_theme = "light";
</script>
<!-- Work around some values being stored in localStorage wrapped in quotes -->
<script type="text/javascript">
try {
var theme = localStorage.getItem('mdbook-theme');
var sidebar = localStorage.getItem('mdbook-sidebar');
if (theme.startsWith('"') && theme.endsWith('"')) {
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
}
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
}
} catch (e) { }
</script>
<!-- Set the theme before any content is loaded, prevents flash -->
<script type="text/javascript">
var theme;
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
if (theme === null || theme === undefined) { theme = default_theme; }
document.body.className = theme;
document.querySelector('html').className = theme + ' js';
</script>
<!-- Hide / unhide sidebar before it is displayed -->
<script type="text/javascript">
var html = document.querySelector('html');
var sidebar = 'hidden';
if (document.body.clientWidth >= 1080) {
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
sidebar = sidebar || 'visible';
}
html.classList.remove('sidebar-visible');
html.classList.add("sidebar-" + sidebar);
</script>
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
<ol class="chapter"><li><a href="tutorial1.html"><strong aria-hidden="true">1.</strong> Chapter 1</a></li><li><a href="tutorial2.html"><strong aria-hidden="true">2.</strong> Chapter 2</a></li><li><a href="tutorial3.html"><strong aria-hidden="true">3.</strong> Chapter 3</a></li><li><a href="tutorial4.html"><strong aria-hidden="true">4.</strong> Chapter 4</a></li><li><a href="tutorial5.html"><strong aria-hidden="true">5.</strong> Chapter 5</a></li><li><a href="tutorial6.html"><strong aria-hidden="true">6.</strong> Chapter 6</a></li><li><a href="tutorial7.html"><strong aria-hidden="true">7.</strong> Chapter 7</a></li><li><a href="tutorial8.html"><strong aria-hidden="true">8.</strong> Chapter 8</a></li><li><a href="tutorial9.html"><strong aria-hidden="true">9.</strong> Chapter 9</a></li><li><a href="tutorial10.html"><strong aria-hidden="true">10.</strong> Chapter 10</a></li><li><a href="tutorial11.html"><strong aria-hidden="true">11.</strong> Chapter 11</a></li></ol>
</nav>
<div id="page-wrapper" class="page-wrapper">
<div class="page">
<div id="menu-bar" class="menu-bar">
<div id="menu-bar-sticky-container">
<div class="left-buttons">
<button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
<i class="fa fa-bars"></i>
</button>
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
<i class="fa fa-paint-brush"></i>
</button>
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
<li role="none"><button role="menuitem" class="theme" id="light">Light (default)</button></li>
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
</ul>
<button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
<i class="fa fa-search"></i>
</button>
</div>
<h1 class="menu-title">chainerror</h1>
<div class="right-buttons">
<a href="print.html" title="Print this book" aria-label="Print this book">
<i id="print-button" class="fa fa-print"></i>
</a>
</div>
</div>
</div>
<div id="search-wrapper" class="hidden">
<form id="searchbar-outer" class="searchbar-outer">
<input type="search" name="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
</form>
<div id="searchresults-outer" class="searchresults-outer hidden">
<div id="searchresults-header" class="searchresults-header"></div>
<ul id="searchresults">
</ul>
</div>
</div>
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
<script type="text/javascript">
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
});
</script>
<div id="content" class="content">
<main>
<pre><pre class="playpen"><code class="language-rust">use std::error::Error;
use std::result::Result;
fn do_some_io() -&gt; Result&lt;(), Box&lt;Error&gt;&gt; {
Err(&quot;do_some_io error&quot;)?;
Ok(())
}
fn func2() -&gt; Result&lt;(), Box&lt;Error&gt;&gt; {
if let Err(_) = do_some_io() {
Err(&quot;func2 error&quot;)?;
}
Ok(())
}
fn func1() -&gt; Result&lt;(), Box&lt;Error&gt;&gt; {
if let Err(_) = func2() {
Err(&quot;func1 error&quot;)?;
}
Ok(())
}
fn main() -&gt; Result&lt;(), Box&lt;Error&gt;&gt; {
func1()
}
</code></pre></pre>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<div style="clear: both"></div>
</nav>
</div>
</div>
<nav class="nav-wide-wrapper" aria-label="Page navigation">
</nav>
</div>
<script src="ace.js" type="text/javascript" charset="utf-8"></script>
<script src="editor.js" type="text/javascript" charset="utf-8"></script>
<script src="mode-rust.js" type="text/javascript" charset="utf-8"></script>
<script src="theme-dawn.js" type="text/javascript" charset="utf-8"></script>
<script src="theme-tomorrow_night.js" type="text/javascript" charset="utf-8"></script>
<script src="elasticlunr.min.js" type="text/javascript" charset="utf-8"></script>
<script src="mark.min.js" type="text/javascript" charset="utf-8"></script>
<script src="searcher.js" type="text/javascript" charset="utf-8"></script>
<script src="clipboard.min.js" type="text/javascript" charset="utf-8"></script>
<script src="highlight.js" type="text/javascript" charset="utf-8"></script>
<script src="book.js" type="text/javascript" charset="utf-8"></script>
<!-- Custom JS scripts -->
</body>
</html>

7
mark.min.js vendored Normal file

File diff suppressed because one or more lines are too long

1
mode-rust.js Normal file

File diff suppressed because one or more lines are too long

3416
print.html Normal file

File diff suppressed because it is too large Load diff

477
searcher.js Normal file
View file

@ -0,0 +1,477 @@
"use strict";
window.search = window.search || {};
(function search(search) {
// Search functionality
//
// You can use !hasFocus() to prevent keyhandling in your key
// event handlers while the user is typing their search.
if (!Mark || !elasticlunr) {
return;
}
//IE 11 Compatibility from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith
if (!String.prototype.startsWith) {
String.prototype.startsWith = function(search, pos) {
return this.substr(!pos || pos < 0 ? 0 : +pos, search.length) === search;
};
}
var search_wrap = document.getElementById('search-wrapper'),
searchbar = document.getElementById('searchbar'),
searchbar_outer = document.getElementById('searchbar-outer'),
searchresults = document.getElementById('searchresults'),
searchresults_outer = document.getElementById('searchresults-outer'),
searchresults_header = document.getElementById('searchresults-header'),
searchicon = document.getElementById('search-toggle'),
content = document.getElementById('content'),
searchindex = null,
doc_urls = [],
results_options = {
teaser_word_count: 30,
limit_results: 30,
},
search_options = {
bool: "AND",
expand: true,
fields: {
title: {boost: 1},
body: {boost: 1},
breadcrumbs: {boost: 0}
}
},
mark_exclude = [],
marker = new Mark(content),
current_searchterm = "",
URL_SEARCH_PARAM = 'search',
URL_MARK_PARAM = 'highlight',
teaser_count = 0,
SEARCH_HOTKEY_KEYCODE = 83,
ESCAPE_KEYCODE = 27,
DOWN_KEYCODE = 40,
UP_KEYCODE = 38,
SELECT_KEYCODE = 13;
function hasFocus() {
return searchbar === document.activeElement;
}
function removeChildren(elem) {
while (elem.firstChild) {
elem.removeChild(elem.firstChild);
}
}
// Helper to parse a url into its building blocks.
function parseURL(url) {
var a = document.createElement('a');
a.href = url;
return {
source: url,
protocol: a.protocol.replace(':',''),
host: a.hostname,
port: a.port,
params: (function(){
var ret = {};
var seg = a.search.replace(/^\?/,'').split('&');
var len = seg.length, i = 0, s;
for (;i<len;i++) {
if (!seg[i]) { continue; }
s = seg[i].split('=');
ret[s[0]] = s[1];
}
return ret;
})(),
file: (a.pathname.match(/\/([^/?#]+)$/i) || [,''])[1],
hash: a.hash.replace('#',''),
path: a.pathname.replace(/^([^/])/,'/$1')
};
}
// Helper to recreate a url string from its building blocks.
function renderURL(urlobject) {
var url = urlobject.protocol + "://" + urlobject.host;
if (urlobject.port != "") {
url += ":" + urlobject.port;
}
url += urlobject.path;
var joiner = "?";
for(var prop in urlobject.params) {
if(urlobject.params.hasOwnProperty(prop)) {
url += joiner + prop + "=" + urlobject.params[prop];
joiner = "&";
}
}
if (urlobject.hash != "") {
url += "#" + urlobject.hash;
}
return url;
}
// Helper to escape html special chars for displaying the teasers
var escapeHTML = (function() {
var MAP = {
'&': '&amp;',
'<': '&lt;',
'>': '&gt;',
'"': '&#34;',
"'": '&#39;'
};
var repl = function(c) { return MAP[c]; };
return function(s) {
return s.replace(/[&<>'"]/g, repl);
};
})();
function formatSearchMetric(count, searchterm) {
if (count == 1) {
return count + " search result for '" + searchterm + "':";
} else if (count == 0) {
return "No search results for '" + searchterm + "'.";
} else {
return count + " search results for '" + searchterm + "':";
}
}
function formatSearchResult(result, searchterms) {
var teaser = makeTeaser(escapeHTML(result.doc.body), searchterms);
teaser_count++;
// The ?URL_MARK_PARAM= parameter belongs inbetween the page and the #heading-anchor
var url = doc_urls[result.ref].split("#");
if (url.length == 1) { // no anchor found
url.push("");
}
return '<a href="' + path_to_root + url[0] + '?' + URL_MARK_PARAM + '=' + searchterms + '#' + url[1]
+ '" aria-details="teaser_' + teaser_count + '">' + result.doc.breadcrumbs + '</a>'
+ '<span class="teaser" id="teaser_' + teaser_count + '" aria-label="Search Result Teaser">'
+ teaser + '</span>';
}
function makeTeaser(body, searchterms) {
// The strategy is as follows:
// First, assign a value to each word in the document:
// Words that correspond to search terms (stemmer aware): 40
// Normal words: 2
// First word in a sentence: 8
// Then use a sliding window with a constant number of words and count the
// sum of the values of the words within the window. Then use the window that got the
// maximum sum. If there are multiple maximas, then get the last one.
// Enclose the terms in <em>.
var stemmed_searchterms = searchterms.map(function(w) {
return elasticlunr.stemmer(w.toLowerCase());
});
var searchterm_weight = 40;
var weighted = []; // contains elements of ["word", weight, index_in_document]
// split in sentences, then words
var sentences = body.toLowerCase().split('. ');
var index = 0;
var value = 0;
var searchterm_found = false;
for (var sentenceindex in sentences) {
var words = sentences[sentenceindex].split(' ');
value = 8;
for (var wordindex in words) {
var word = words[wordindex];
if (word.length > 0) {
for (var searchtermindex in stemmed_searchterms) {
if (elasticlunr.stemmer(word).startsWith(stemmed_searchterms[searchtermindex])) {
value = searchterm_weight;
searchterm_found = true;
}
};
weighted.push([word, value, index]);
value = 2;
}
index += word.length;
index += 1; // ' ' or '.' if last word in sentence
};
index += 1; // because we split at a two-char boundary '. '
};
if (weighted.length == 0) {
return body;
}
var window_weight = [];
var window_size = Math.min(weighted.length, results_options.teaser_word_count);
var cur_sum = 0;
for (var wordindex = 0; wordindex < window_size; wordindex++) {
cur_sum += weighted[wordindex][1];
};
window_weight.push(cur_sum);
for (var wordindex = 0; wordindex < weighted.length - window_size; wordindex++) {
cur_sum -= weighted[wordindex][1];
cur_sum += weighted[wordindex + window_size][1];
window_weight.push(cur_sum);
};
if (searchterm_found) {
var max_sum = 0;
var max_sum_window_index = 0;
// backwards
for (var i = window_weight.length - 1; i >= 0; i--) {
if (window_weight[i] > max_sum) {
max_sum = window_weight[i];
max_sum_window_index = i;
}
};
} else {
max_sum_window_index = 0;
}
// add <em/> around searchterms
var teaser_split = [];
var index = weighted[max_sum_window_index][2];
for (var i = max_sum_window_index; i < max_sum_window_index+window_size; i++) {
var word = weighted[i];
if (index < word[2]) {
// missing text from index to start of `word`
teaser_split.push(body.substring(index, word[2]));
index = word[2];
}
if (word[1] == searchterm_weight) {
teaser_split.push("<em>")
}
index = word[2] + word[0].length;
teaser_split.push(body.substring(word[2], index));
if (word[1] == searchterm_weight) {
teaser_split.push("</em>")
}
};
return teaser_split.join('');
}
function init(config) {
results_options = config.results_options;
search_options = config.search_options;
searchbar_outer = config.searchbar_outer;
doc_urls = config.doc_urls;
searchindex = elasticlunr.Index.load(config.index);
// Set up events
searchicon.addEventListener('click', function(e) { searchIconClickHandler(); }, false);
searchbar.addEventListener('keyup', function(e) { searchbarKeyUpHandler(); }, false);
document.addEventListener('keydown', function(e) { globalKeyHandler(e); }, false);
// If the user uses the browser buttons, do the same as if a reload happened
window.onpopstate = function(e) { doSearchOrMarkFromUrl(); };
// Suppress "submit" events so the page doesn't reload when the user presses Enter
document.addEventListener('submit', function(e) { e.preventDefault(); }, false);
// If reloaded, do the search or mark again, depending on the current url parameters
doSearchOrMarkFromUrl();
}
function unfocusSearchbar() {
// hacky, but just focusing a div only works once
var tmp = document.createElement('input');
tmp.setAttribute('style', 'position: absolute; opacity: 0;');
searchicon.appendChild(tmp);
tmp.focus();
tmp.remove();
}
// On reload or browser history backwards/forwards events, parse the url and do search or mark
function doSearchOrMarkFromUrl() {
// Check current URL for search request
var url = parseURL(window.location.href);
if (url.params.hasOwnProperty(URL_SEARCH_PARAM)
&& url.params[URL_SEARCH_PARAM] != "") {
showSearch(true);
searchbar.value = decodeURIComponent(
(url.params[URL_SEARCH_PARAM]+'').replace(/\+/g, '%20'));
searchbarKeyUpHandler(); // -> doSearch()
} else {
showSearch(false);
}
if (url.params.hasOwnProperty(URL_MARK_PARAM)) {
var words = url.params[URL_MARK_PARAM].split(' ');
marker.mark(words, {
exclude: mark_exclude
});
var markers = document.querySelectorAll("mark");
function hide() {
for (var i = 0; i < markers.length; i++) {
markers[i].classList.add("fade-out");
window.setTimeout(function(e) { marker.unmark(); }, 300);
}
}
for (var i = 0; i < markers.length; i++) {
markers[i].addEventListener('click', hide);
}
}
}
// Eventhandler for keyevents on `document`
function globalKeyHandler(e) {
if (e.altKey || e.ctrlKey || e.metaKey || e.shiftKey || e.target.type === 'textarea') { return; }
if (e.keyCode === ESCAPE_KEYCODE) {
e.preventDefault();
searchbar.classList.remove("active");
setSearchUrlParameters("",
(searchbar.value.trim() !== "") ? "push" : "replace");
if (hasFocus()) {
unfocusSearchbar();
}
showSearch(false);
marker.unmark();
} else if (!hasFocus() && e.keyCode === SEARCH_HOTKEY_KEYCODE) {
e.preventDefault();
showSearch(true);
window.scrollTo(0, 0);
searchbar.select();
} else if (hasFocus() && e.keyCode === DOWN_KEYCODE) {
e.preventDefault();
unfocusSearchbar();
searchresults.firstElementChild.classList.add("focus");
} else if (!hasFocus() && (e.keyCode === DOWN_KEYCODE
|| e.keyCode === UP_KEYCODE
|| e.keyCode === SELECT_KEYCODE)) {
// not `:focus` because browser does annoying scrolling
var focused = searchresults.querySelector("li.focus");
if (!focused) return;
e.preventDefault();
if (e.keyCode === DOWN_KEYCODE) {
var next = focused.nextElementSibling;
if (next) {
focused.classList.remove("focus");
next.classList.add("focus");
}
} else if (e.keyCode === UP_KEYCODE) {
focused.classList.remove("focus");
var prev = focused.previousElementSibling;
if (prev) {
prev.classList.add("focus");
} else {
searchbar.select();
}
} else { // SELECT_KEYCODE
window.location.assign(focused.querySelector('a'));
}
}
}
function showSearch(yes) {
if (yes) {
search_wrap.classList.remove('hidden');
searchicon.setAttribute('aria-expanded', 'true');
} else {
search_wrap.classList.add('hidden');
searchicon.setAttribute('aria-expanded', 'false');
var results = searchresults.children;
for (var i = 0; i < results.length; i++) {
results[i].classList.remove("focus");
}
}
}
function showResults(yes) {
if (yes) {
searchresults_outer.classList.remove('hidden');
} else {
searchresults_outer.classList.add('hidden');
}
}
// Eventhandler for search icon
function searchIconClickHandler() {
if (search_wrap.classList.contains('hidden')) {
showSearch(true);
window.scrollTo(0, 0);
searchbar.select();
} else {
showSearch(false);
}
}
// Eventhandler for keyevents while the searchbar is focused
function searchbarKeyUpHandler() {
var searchterm = searchbar.value.trim();
if (searchterm != "") {
searchbar.classList.add("active");
doSearch(searchterm);
} else {
searchbar.classList.remove("active");
showResults(false);
removeChildren(searchresults);
}
setSearchUrlParameters(searchterm, "push_if_new_search_else_replace");
// Remove marks
marker.unmark();
}
// Update current url with ?URL_SEARCH_PARAM= parameter, remove ?URL_MARK_PARAM and #heading-anchor .
// `action` can be one of "push", "replace", "push_if_new_search_else_replace"
// and replaces or pushes a new browser history item.
// "push_if_new_search_else_replace" pushes if there is no `?URL_SEARCH_PARAM=abc` yet.
function setSearchUrlParameters(searchterm, action) {
var url = parseURL(window.location.href);
var first_search = ! url.params.hasOwnProperty(URL_SEARCH_PARAM);
if (searchterm != "" || action == "push_if_new_search_else_replace") {
url.params[URL_SEARCH_PARAM] = searchterm;
delete url.params[URL_MARK_PARAM];
url.hash = "";
} else {
delete url.params[URL_SEARCH_PARAM];
}
// A new search will also add a new history item, so the user can go back
// to the page prior to searching. A updated search term will only replace
// the url.
if (action == "push" || (action == "push_if_new_search_else_replace" && first_search) ) {
history.pushState({}, document.title, renderURL(url));
} else if (action == "replace" || (action == "push_if_new_search_else_replace" && !first_search) ) {
history.replaceState({}, document.title, renderURL(url));
}
}
function doSearch(searchterm) {
// Don't search the same twice
if (current_searchterm == searchterm) { return; }
else { current_searchterm = searchterm; }
if (searchindex == null) { return; }
// Do the actual search
var results = searchindex.search(searchterm, search_options);
var resultcount = Math.min(results.length, results_options.limit_results);
// Display search metrics
searchresults_header.innerText = formatSearchMetric(resultcount, searchterm);
// Clear and insert results
var searchterms = searchterm.split(' ');
removeChildren(searchresults);
for(var i = 0; i < resultcount ; i++){
var resultElem = document.createElement('li');
resultElem.innerHTML = formatSearchResult(results[i], searchterms);
searchresults.appendChild(resultElem);
}
// Display results
showResults(true);
}
fetch(path_to_root + 'searchindex.json')
.then(response => response.json())
.then(json => init(json))
.catch(error => { // Try to load searchindex.js if fetch failed
var script = document.createElement('script');
script.src = path_to_root + 'searchindex.js';
script.onload = () => init(window.search);
document.head.appendChild(script);
});
// Exported functions
search.hasFocus = hasFocus;
})(window.search);

1
searchindex.js Normal file
View file

@ -0,0 +1 @@
window.search = {"doc_urls":[],"index":{"documentStore":{"docInfo":{},"docs":{},"length":0,"save":true},"fields":["title","body","breadcrumbs"],"index":{"body":{"root":{"df":0,"docs":{}}},"breadcrumbs":{"root":{"df":0,"docs":{}}},"title":{"root":{"df":0,"docs":{}}}},"pipeline":["trimmer","stopWordFilter","stemmer"],"ref":"id","version":"0.9.5"},"results_options":{"limit_results":30,"teaser_word_count":30},"search_options":{"bool":"OR","expand":true,"fields":{"body":{"boost":1},"breadcrumbs":{"boost":1},"title":{"boost":2}}}};

1
searchindex.json Normal file
View file

@ -0,0 +1 @@
{"doc_urls":[],"index":{"documentStore":{"docInfo":{},"docs":{},"length":0,"save":true},"fields":["title","body","breadcrumbs"],"index":{"body":{"root":{"df":0,"docs":{}}},"breadcrumbs":{"root":{"df":0,"docs":{}}},"title":{"root":{"df":0,"docs":{}}}},"pipeline":["trimmer","stopWordFilter","stemmer"],"ref":"id","version":"0.9.5"},"results_options":{"limit_results":30,"teaser_word_count":30},"search_options":{"bool":"OR","expand":true,"fields":{"body":{"boost":1},"breadcrumbs":{"boost":1},"title":{"boost":2}}}}

1
theme-dawn.js Normal file
View file

@ -0,0 +1 @@
ace.define("ace/theme/dawn",["require","exports","module","ace/lib/dom"],function(e,t,n){t.isDark=!1,t.cssClass="ace-dawn",t.cssText=".ace-dawn .ace_gutter {background: #ebebeb;color: #333}.ace-dawn .ace_print-margin {width: 1px;background: #e8e8e8}.ace-dawn {background-color: #F9F9F9;color: #080808}.ace-dawn .ace_cursor {color: #000000}.ace-dawn .ace_marker-layer .ace_selection {background: rgba(39, 95, 255, 0.30)}.ace-dawn.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px #F9F9F9;}.ace-dawn .ace_marker-layer .ace_step {background: rgb(255, 255, 0)}.ace-dawn .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid rgba(75, 75, 126, 0.50)}.ace-dawn .ace_marker-layer .ace_active-line {background: rgba(36, 99, 180, 0.12)}.ace-dawn .ace_gutter-active-line {background-color : #dcdcdc}.ace-dawn .ace_marker-layer .ace_selected-word {border: 1px solid rgba(39, 95, 255, 0.30)}.ace-dawn .ace_invisible {color: rgba(75, 75, 126, 0.50)}.ace-dawn .ace_keyword,.ace-dawn .ace_meta {color: #794938}.ace-dawn .ace_constant,.ace-dawn .ace_constant.ace_character,.ace-dawn .ace_constant.ace_character.ace_escape,.ace-dawn .ace_constant.ace_other {color: #811F24}.ace-dawn .ace_invalid.ace_illegal {text-decoration: underline;font-style: italic;color: #F8F8F8;background-color: #B52A1D}.ace-dawn .ace_invalid.ace_deprecated {text-decoration: underline;font-style: italic;color: #B52A1D}.ace-dawn .ace_support {color: #691C97}.ace-dawn .ace_support.ace_constant {color: #B4371F}.ace-dawn .ace_fold {background-color: #794938;border-color: #080808}.ace-dawn .ace_list,.ace-dawn .ace_markup.ace_list,.ace-dawn .ace_support.ace_function {color: #693A17}.ace-dawn .ace_storage {font-style: italic;color: #A71D5D}.ace-dawn .ace_string {color: #0B6125}.ace-dawn .ace_string.ace_regexp {color: #CF5628}.ace-dawn .ace_comment {font-style: italic;color: #5A525F}.ace-dawn .ace_heading,.ace-dawn .ace_markup.ace_heading {color: #19356D}.ace-dawn .ace_variable {color: #234A97}.ace-dawn .ace_indent-guide {background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWNgYGBgYLh/5+x/AAizA4hxNNsZAAAAAElFTkSuQmCC) right repeat-y}";var r=e("../lib/dom");r.importCssString(t.cssText,t.cssClass)})

1
theme-tomorrow_night.js Normal file
View file

@ -0,0 +1 @@
ace.define("ace/theme/tomorrow_night",["require","exports","module","ace/lib/dom"],function(e,t,n){t.isDark=!0,t.cssClass="ace-tomorrow-night",t.cssText=".ace-tomorrow-night .ace_gutter {background: #25282c;color: #C5C8C6}.ace-tomorrow-night .ace_print-margin {width: 1px;background: #25282c}.ace-tomorrow-night {background-color: #1D1F21;color: #C5C8C6}.ace-tomorrow-night .ace_cursor {color: #AEAFAD}.ace-tomorrow-night .ace_marker-layer .ace_selection {background: #373B41}.ace-tomorrow-night.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px #1D1F21;}.ace-tomorrow-night .ace_marker-layer .ace_step {background: rgb(102, 82, 0)}.ace-tomorrow-night .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid #4B4E55}.ace-tomorrow-night .ace_marker-layer .ace_active-line {background: #282A2E}.ace-tomorrow-night .ace_gutter-active-line {background-color: #282A2E}.ace-tomorrow-night .ace_marker-layer .ace_selected-word {border: 1px solid #373B41}.ace-tomorrow-night .ace_invisible {color: #4B4E55}.ace-tomorrow-night .ace_keyword,.ace-tomorrow-night .ace_meta,.ace-tomorrow-night .ace_storage,.ace-tomorrow-night .ace_storage.ace_type,.ace-tomorrow-night .ace_support.ace_type {color: #B294BB}.ace-tomorrow-night .ace_keyword.ace_operator {color: #8ABEB7}.ace-tomorrow-night .ace_constant.ace_character,.ace-tomorrow-night .ace_constant.ace_language,.ace-tomorrow-night .ace_constant.ace_numeric,.ace-tomorrow-night .ace_keyword.ace_other.ace_unit,.ace-tomorrow-night .ace_support.ace_constant,.ace-tomorrow-night .ace_variable.ace_parameter {color: #DE935F}.ace-tomorrow-night .ace_constant.ace_other {color: #CED1CF}.ace-tomorrow-night .ace_invalid {color: #CED2CF;background-color: #DF5F5F}.ace-tomorrow-night .ace_invalid.ace_deprecated {color: #CED2CF;background-color: #B798BF}.ace-tomorrow-night .ace_fold {background-color: #81A2BE;border-color: #C5C8C6}.ace-tomorrow-night .ace_entity.ace_name.ace_function,.ace-tomorrow-night .ace_support.ace_function,.ace-tomorrow-night .ace_variable {color: #81A2BE}.ace-tomorrow-night .ace_support.ace_class,.ace-tomorrow-night .ace_support.ace_type {color: #F0C674}.ace-tomorrow-night .ace_heading,.ace-tomorrow-night .ace_markup.ace_heading,.ace-tomorrow-night .ace_string {color: #B5BD68}.ace-tomorrow-night .ace_entity.ace_name.ace_tag,.ace-tomorrow-night .ace_entity.ace_other.ace_attribute-name,.ace-tomorrow-night .ace_meta.ace_tag,.ace-tomorrow-night .ace_string.ace_regexp,.ace-tomorrow-night .ace_variable {color: #CC6666}.ace-tomorrow-night .ace_comment {color: #969896}.ace-tomorrow-night .ace_indent-guide {background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWNgYGBgYHB3d/8PAAOIAdULw8qMAAAAAElFTkSuQmCC) right repeat-y}";var r=e("../lib/dom");r.importCssString(t.cssText,t.cssClass)})

96
tomorrow-night.css Normal file
View file

@ -0,0 +1,96 @@
/* Tomorrow Night Theme */
/* http://jmblog.github.com/color-themes-for-google-code-highlightjs */
/* Original theme - https://github.com/chriskempson/tomorrow-theme */
/* http://jmblog.github.com/color-themes-for-google-code-highlightjs */
/* Tomorrow Comment */
.hljs-comment {
color: #969896;
}
/* Tomorrow Red */
.hljs-variable,
.hljs-attribute,
.hljs-tag,
.hljs-regexp,
.ruby .hljs-constant,
.xml .hljs-tag .hljs-title,
.xml .hljs-pi,
.xml .hljs-doctype,
.html .hljs-doctype,
.css .hljs-id,
.css .hljs-class,
.css .hljs-pseudo {
color: #cc6666;
}
/* Tomorrow Orange */
.hljs-number,
.hljs-preprocessor,
.hljs-pragma,
.hljs-built_in,
.hljs-literal,
.hljs-params,
.hljs-constant {
color: #de935f;
}
/* Tomorrow Yellow */
.ruby .hljs-class .hljs-title,
.css .hljs-rule .hljs-attribute {
color: #f0c674;
}
/* Tomorrow Green */
.hljs-string,
.hljs-value,
.hljs-inheritance,
.hljs-header,
.hljs-name,
.ruby .hljs-symbol,
.xml .hljs-cdata {
color: #b5bd68;
}
/* Tomorrow Aqua */
.hljs-title,
.css .hljs-hexcolor {
color: #8abeb7;
}
/* Tomorrow Blue */
.hljs-function,
.python .hljs-decorator,
.python .hljs-title,
.ruby .hljs-function .hljs-title,
.ruby .hljs-title .hljs-keyword,
.perl .hljs-sub,
.javascript .hljs-title,
.coffeescript .hljs-title {
color: #81a2be;
}
/* Tomorrow Purple */
.hljs-keyword,
.javascript .hljs-function {
color: #b294bb;
}
.hljs {
display: block;
overflow-x: auto;
background: #1d1f21;
color: #c5c8c6;
padding: 0.5em;
-webkit-text-size-adjust: none;
}
.coffeescript .javascript,
.javascript .xml,
.tex .hljs-formula,
.xml .javascript,
.xml .vbscript,
.xml .css,
.xml .hljs-cdata {
opacity: 0.5;
}

227
tutorial1.html Normal file
View file

@ -0,0 +1,227 @@
<!DOCTYPE HTML>
<html lang="en" class="sidebar-visible no-js">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>Chapter 1 - chainerror</title>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#ffffff" />
<link rel="shortcut icon" href="favicon.png">
<link rel="stylesheet" href="css/variables.css">
<link rel="stylesheet" href="css/general.css">
<link rel="stylesheet" href="css/chrome.css">
<link rel="stylesheet" href="css/print.css" media="print">
<!-- Fonts -->
<link rel="stylesheet" href="FontAwesome/css/font-awesome.css">
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800" rel="stylesheet" type="text/css">
<link href="https://fonts.googleapis.com/css?family=Source+Code+Pro:500" rel="stylesheet" type="text/css">
<!-- Highlight.js Stylesheets -->
<link rel="stylesheet" href="highlight.css">
<link rel="stylesheet" href="tomorrow-night.css">
<link rel="stylesheet" href="ayu-highlight.css">
<!-- Custom theme stylesheets -->
</head>
<body class="light">
<!-- Provide site root to javascript -->
<script type="text/javascript">
var path_to_root = "";
var default_theme = "light";
</script>
<!-- Work around some values being stored in localStorage wrapped in quotes -->
<script type="text/javascript">
try {
var theme = localStorage.getItem('mdbook-theme');
var sidebar = localStorage.getItem('mdbook-sidebar');
if (theme.startsWith('"') && theme.endsWith('"')) {
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
}
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
}
} catch (e) { }
</script>
<!-- Set the theme before any content is loaded, prevents flash -->
<script type="text/javascript">
var theme;
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
if (theme === null || theme === undefined) { theme = default_theme; }
document.body.className = theme;
document.querySelector('html').className = theme + ' js';
</script>
<!-- Hide / unhide sidebar before it is displayed -->
<script type="text/javascript">
var html = document.querySelector('html');
var sidebar = 'hidden';
if (document.body.clientWidth >= 1080) {
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
sidebar = sidebar || 'visible';
}
html.classList.remove('sidebar-visible');
html.classList.add("sidebar-" + sidebar);
</script>
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
<ol class="chapter"><li><a href="tutorial1.html" class="active"><strong aria-hidden="true">1.</strong> Chapter 1</a></li><li><a href="tutorial2.html"><strong aria-hidden="true">2.</strong> Chapter 2</a></li><li><a href="tutorial3.html"><strong aria-hidden="true">3.</strong> Chapter 3</a></li><li><a href="tutorial4.html"><strong aria-hidden="true">4.</strong> Chapter 4</a></li><li><a href="tutorial5.html"><strong aria-hidden="true">5.</strong> Chapter 5</a></li><li><a href="tutorial6.html"><strong aria-hidden="true">6.</strong> Chapter 6</a></li><li><a href="tutorial7.html"><strong aria-hidden="true">7.</strong> Chapter 7</a></li><li><a href="tutorial8.html"><strong aria-hidden="true">8.</strong> Chapter 8</a></li><li><a href="tutorial9.html"><strong aria-hidden="true">9.</strong> Chapter 9</a></li><li><a href="tutorial10.html"><strong aria-hidden="true">10.</strong> Chapter 10</a></li><li><a href="tutorial11.html"><strong aria-hidden="true">11.</strong> Chapter 11</a></li></ol>
</nav>
<div id="page-wrapper" class="page-wrapper">
<div class="page">
<div id="menu-bar" class="menu-bar">
<div id="menu-bar-sticky-container">
<div class="left-buttons">
<button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
<i class="fa fa-bars"></i>
</button>
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
<i class="fa fa-paint-brush"></i>
</button>
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
<li role="none"><button role="menuitem" class="theme" id="light">Light (default)</button></li>
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
</ul>
<button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
<i class="fa fa-search"></i>
</button>
</div>
<h1 class="menu-title">chainerror</h1>
<div class="right-buttons">
<a href="print.html" title="Print this book" aria-label="Print this book">
<i id="print-button" class="fa fa-print"></i>
</a>
</div>
</div>
</div>
<div id="search-wrapper" class="hidden">
<form id="searchbar-outer" class="searchbar-outer">
<input type="search" name="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
</form>
<div id="searchresults-outer" class="searchresults-outer hidden">
<div id="searchresults-header" class="searchresults-header"></div>
<ul id="searchresults">
</ul>
</div>
</div>
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
<script type="text/javascript">
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
});
</script>
<div id="content" class="content">
<main>
<pre><pre class="playpen"><code class="language-rust">use std::error::Error;
use std::result::Result;
fn do_some_io() -&gt; Result&lt;(), Box&lt;Error&gt;&gt; {
Err(&quot;do_some_io error&quot;)?;
Ok(())
}
fn func2() -&gt; Result&lt;(), Box&lt;Error&gt;&gt; {
if let Err(_) = do_some_io() {
Err(&quot;func2 error&quot;)?;
}
Ok(())
}
fn func1() -&gt; Result&lt;(), Box&lt;Error&gt;&gt; {
if let Err(_) = func2() {
Err(&quot;func1 error&quot;)?;
}
Ok(())
}
fn main() -&gt; Result&lt;(), Box&lt;Error&gt;&gt; {
func1()
}
</code></pre></pre>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="next" href="tutorial2.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
<div style="clear: both"></div>
</nav>
</div>
</div>
<nav class="nav-wide-wrapper" aria-label="Page navigation">
<a href="tutorial2.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
</nav>
</div>
<script src="ace.js" type="text/javascript" charset="utf-8"></script>
<script src="editor.js" type="text/javascript" charset="utf-8"></script>
<script src="mode-rust.js" type="text/javascript" charset="utf-8"></script>
<script src="theme-dawn.js" type="text/javascript" charset="utf-8"></script>
<script src="theme-tomorrow_night.js" type="text/javascript" charset="utf-8"></script>
<script src="elasticlunr.min.js" type="text/javascript" charset="utf-8"></script>
<script src="mark.min.js" type="text/javascript" charset="utf-8"></script>
<script src="searcher.js" type="text/javascript" charset="utf-8"></script>
<script src="clipboard.min.js" type="text/javascript" charset="utf-8"></script>
<script src="highlight.js" type="text/javascript" charset="utf-8"></script>
<script src="book.js" type="text/javascript" charset="utf-8"></script>
<!-- Custom JS scripts -->
</body>
</html>

546
tutorial10.html Normal file
View file

@ -0,0 +1,546 @@
<!DOCTYPE HTML>
<html lang="en" class="sidebar-visible no-js">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>Chapter 10 - chainerror</title>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#ffffff" />
<link rel="shortcut icon" href="favicon.png">
<link rel="stylesheet" href="css/variables.css">
<link rel="stylesheet" href="css/general.css">
<link rel="stylesheet" href="css/chrome.css">
<link rel="stylesheet" href="css/print.css" media="print">
<!-- Fonts -->
<link rel="stylesheet" href="FontAwesome/css/font-awesome.css">
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800" rel="stylesheet" type="text/css">
<link href="https://fonts.googleapis.com/css?family=Source+Code+Pro:500" rel="stylesheet" type="text/css">
<!-- Highlight.js Stylesheets -->
<link rel="stylesheet" href="highlight.css">
<link rel="stylesheet" href="tomorrow-night.css">
<link rel="stylesheet" href="ayu-highlight.css">
<!-- Custom theme stylesheets -->
</head>
<body class="light">
<!-- Provide site root to javascript -->
<script type="text/javascript">
var path_to_root = "";
var default_theme = "light";
</script>
<!-- Work around some values being stored in localStorage wrapped in quotes -->
<script type="text/javascript">
try {
var theme = localStorage.getItem('mdbook-theme');
var sidebar = localStorage.getItem('mdbook-sidebar');
if (theme.startsWith('"') && theme.endsWith('"')) {
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
}
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
}
} catch (e) { }
</script>
<!-- Set the theme before any content is loaded, prevents flash -->
<script type="text/javascript">
var theme;
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
if (theme === null || theme === undefined) { theme = default_theme; }
document.body.className = theme;
document.querySelector('html').className = theme + ' js';
</script>
<!-- Hide / unhide sidebar before it is displayed -->
<script type="text/javascript">
var html = document.querySelector('html');
var sidebar = 'hidden';
if (document.body.clientWidth >= 1080) {
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
sidebar = sidebar || 'visible';
}
html.classList.remove('sidebar-visible');
html.classList.add("sidebar-" + sidebar);
</script>
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
<ol class="chapter"><li><a href="tutorial1.html"><strong aria-hidden="true">1.</strong> Chapter 1</a></li><li><a href="tutorial2.html"><strong aria-hidden="true">2.</strong> Chapter 2</a></li><li><a href="tutorial3.html"><strong aria-hidden="true">3.</strong> Chapter 3</a></li><li><a href="tutorial4.html"><strong aria-hidden="true">4.</strong> Chapter 4</a></li><li><a href="tutorial5.html"><strong aria-hidden="true">5.</strong> Chapter 5</a></li><li><a href="tutorial6.html"><strong aria-hidden="true">6.</strong> Chapter 6</a></li><li><a href="tutorial7.html"><strong aria-hidden="true">7.</strong> Chapter 7</a></li><li><a href="tutorial8.html"><strong aria-hidden="true">8.</strong> Chapter 8</a></li><li><a href="tutorial9.html"><strong aria-hidden="true">9.</strong> Chapter 9</a></li><li><a href="tutorial10.html" class="active"><strong aria-hidden="true">10.</strong> Chapter 10</a></li><li><a href="tutorial11.html"><strong aria-hidden="true">11.</strong> Chapter 11</a></li></ol>
</nav>
<div id="page-wrapper" class="page-wrapper">
<div class="page">
<div id="menu-bar" class="menu-bar">
<div id="menu-bar-sticky-container">
<div class="left-buttons">
<button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
<i class="fa fa-bars"></i>
</button>
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
<i class="fa fa-paint-brush"></i>
</button>
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
<li role="none"><button role="menuitem" class="theme" id="light">Light (default)</button></li>
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
</ul>
<button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
<i class="fa fa-search"></i>
</button>
</div>
<h1 class="menu-title">chainerror</h1>
<div class="right-buttons">
<a href="print.html" title="Print this book" aria-label="Print this book">
<i id="print-button" class="fa fa-print"></i>
</a>
</div>
</div>
</div>
<div id="search-wrapper" class="hidden">
<form id="searchbar-outer" class="searchbar-outer">
<input type="search" name="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
</form>
<div id="searchresults-outer" class="searchresults-outer hidden">
<div id="searchresults-header" class="searchresults-header"></div>
<ul id="searchresults">
</ul>
</div>
</div>
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
<script type="text/javascript">
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
});
</script>
<div id="content" class="content">
<main>
<pre><pre class="playpen"><code class="language-rust">use crate::chainerror::*;
use std::error::Error;
use std::io;
use std::result::Result;
fn do_some_io() -&gt; Result&lt;(), Box&lt;Error&gt;&gt; {
Err(io::Error::from(io::ErrorKind::NotFound))?;
Ok(())
}
derive_str_cherr!(Func2Error);
fn func2() -&gt; Result&lt;(), Box&lt;Error&gt;&gt; {
let filename = &quot;foo.txt&quot;;
do_some_io().map_err(mstrerr!(Func2Error, &quot;Error reading '{}'&quot;, filename))?;
Ok(())
}
#[derive(Debug)]
enum Func1Error {
Func2,
IO(String),
}
impl ::std::fmt::Display for Func1Error {
fn fmt(&amp;self, f: &amp;mut ::std::fmt::Formatter) -&gt; ::std::fmt::Result {
match self {
Func1Error::Func2 =&gt; write!(f, &quot;func1 error calling func2&quot;),
Func1Error::IO(filename) =&gt; write!(f, &quot;Error reading '{}'&quot;, filename),
}
}
}
fn func1() -&gt; ChainResult&lt;(), Func1Error&gt; {
func2().map_err(|e| cherr!(e, Func1Error::Func2))?;
let filename = String::from(&quot;bar.txt&quot;);
do_some_io().map_err(|e| cherr!(e, Func1Error::IO(filename)))?;
Ok(())
}
fn main() -&gt; Result&lt;(), Box&lt;Error&gt;&gt; {
if let Err(e) = func1() {
match e.kind() {
Func1Error::Func2 =&gt; eprintln!(&quot;Main Error Report: func1 error calling func2&quot;),
Func1Error::IO(filename) =&gt; {
eprintln!(&quot;Main Error Report: func1 error reading '{}'&quot;, filename)
}
}
if let Some(e) = e.find_chain_cause::&lt;Func2Error&gt;() {
eprintln!(&quot;Error reported by Func2Error: {}&quot;, e)
}
eprintln!(&quot;\nDebug Error:\n{:?}&quot;, e);
}
Ok(())
}
# #[allow(dead_code)]
# mod chainerror {
# use std::error::Error;
# use std::fmt::{Debug, Display, Formatter, Result};
# use std::result::Result as StdResult;
#
# pub struct ChainError&lt;T&gt; {
# #[cfg(not(feature = &quot;no-fileline&quot;))]
# occurrence: Option&lt;(u32, &amp;'static str)&gt;,
# kind: T,
# error_cause: Option&lt;Box&lt;dyn Error + 'static&gt;&gt;,
# }
#
# pub type ChainResult&lt;O, E&gt; = StdResult&lt;O, ChainError&lt;E&gt;&gt;;
#
# impl&lt;T: 'static + Display + Debug&gt; ChainError&lt;T&gt; {
# #[cfg(not(feature = &quot;no-fileline&quot;))]
# pub fn new(
# kind: T,
# error_cause: Option&lt;Box&lt;dyn Error + 'static&gt;&gt;,
# occurrence: Option&lt;(u32, &amp;'static str)&gt;,
# ) -&gt; Self {
# Self {
# occurrence,
# kind,
# error_cause,
# }
# }
#
# #[cfg(feature = &quot;no-fileline&quot;)]
# pub fn new(
# kind: T,
# error_cause: Option&lt;Box&lt;dyn Error + 'static&gt;&gt;,
# _occurrence: Option&lt;(u32, &amp;'static str)&gt;,
# ) -&gt; Self {
# Self { kind, error_cause }
# }
#
# pub fn root_cause(&amp;self) -&gt; Option&lt;&amp;(dyn Error + 'static)&gt; {
# let mut cause = self as &amp;(dyn Error + 'static);
# while let Some(c) = cause.source() {
# cause = c;
# }
# Some(cause)
# }
#
# pub fn find_cause&lt;U: Error + 'static&gt;(&amp;self) -&gt; Option&lt;&amp;U&gt; {
# let mut cause = self as &amp;(dyn Error + 'static);
# loop {
# if cause.is::&lt;U&gt;() {
# return cause.downcast_ref::&lt;U&gt;();
# }
#
# match cause.source() {
# Some(c) =&gt; cause = c,
# None =&gt; return None,
# }
# }
# }
#
# pub fn find_chain_cause&lt;U: Error + 'static&gt;(&amp;self) -&gt; Option&lt;&amp;ChainError&lt;U&gt;&gt; {
# let mut cause = self as &amp;(dyn Error + 'static);
# loop {
# if cause.is::&lt;ChainError&lt;U&gt;&gt;() {
# return cause.downcast_ref::&lt;ChainError&lt;U&gt;&gt;();
# }
#
# match cause.source() {
# Some(c) =&gt; cause = c,
# None =&gt; return None,
# }
# }
# }
#
# pub fn kind&lt;'a&gt;(&amp;'a self) -&gt; &amp;'a T {
# &amp;self.kind
# }
# }
#
# pub trait ChainErrorDown {
# fn is_chain&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; bool;
# fn downcast_chain_ref&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; Option&lt;&amp;ChainError&lt;T&gt;&gt;;
# fn downcast_chain_mut&lt;T: 'static + Display + Debug&gt;(&amp;mut self) -&gt; Option&lt;&amp;mut ChainError&lt;T&gt;&gt;;
# }
#
# use std::any::TypeId;
#
# impl&lt;U: 'static + Display + Debug&gt; ChainErrorDown for ChainError&lt;U&gt; {
# fn is_chain&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; bool {
# TypeId::of::&lt;T&gt;() == TypeId::of::&lt;U&gt;()
# }
#
# fn downcast_chain_ref&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; Option&lt;&amp;ChainError&lt;T&gt;&gt; {
# if self.is_chain::&lt;T&gt;() {
# unsafe { Some(&amp;*(self as *const dyn Error as *const &amp;ChainError&lt;T&gt;)) }
# } else {
# None
# }
# }
#
# fn downcast_chain_mut&lt;T: 'static + Display + Debug&gt;(&amp;mut self) -&gt; Option&lt;&amp;mut ChainError&lt;T&gt;&gt; {
# if self.is_chain::&lt;T&gt;() {
# unsafe { Some(&amp;mut *(self as *mut dyn Error as *mut &amp;mut ChainError&lt;T&gt;)) }
# } else {
# None
# }
# }
# }
#
# impl ChainErrorDown for dyn Error + 'static {
# fn is_chain&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; bool {
# self.is::&lt;ChainError&lt;T&gt;&gt;()
# }
#
# fn downcast_chain_ref&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; Option&lt;&amp;ChainError&lt;T&gt;&gt; {
# self.downcast_ref::&lt;ChainError&lt;T&gt;&gt;()
# }
#
# fn downcast_chain_mut&lt;T: 'static + Display + Debug&gt;(&amp;mut self) -&gt; Option&lt;&amp;mut ChainError&lt;T&gt;&gt; {
# self.downcast_mut::&lt;ChainError&lt;T&gt;&gt;()
# }
# }
#
# impl ChainErrorDown for dyn Error + 'static + Send {
# fn is_chain&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; bool {
# self.is::&lt;ChainError&lt;T&gt;&gt;()
# }
#
# fn downcast_chain_ref&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; Option&lt;&amp;ChainError&lt;T&gt;&gt; {
# self.downcast_ref::&lt;ChainError&lt;T&gt;&gt;()
# }
#
# fn downcast_chain_mut&lt;T: 'static + Display + Debug&gt;(&amp;mut self) -&gt; Option&lt;&amp;mut ChainError&lt;T&gt;&gt; {
# self.downcast_mut::&lt;ChainError&lt;T&gt;&gt;()
# }
# }
#
# impl ChainErrorDown for dyn Error + 'static + Send + Sync {
# fn is_chain&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; bool {
# self.is::&lt;ChainError&lt;T&gt;&gt;()
# }
#
# fn downcast_chain_ref&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; Option&lt;&amp;ChainError&lt;T&gt;&gt; {
# self.downcast_ref::&lt;ChainError&lt;T&gt;&gt;()
# }
#
# fn downcast_chain_mut&lt;T: 'static + Display + Debug&gt;(&amp;mut self) -&gt; Option&lt;&amp;mut ChainError&lt;T&gt;&gt; {
# self.downcast_mut::&lt;ChainError&lt;T&gt;&gt;()
# }
# }
#
# impl&lt;T: 'static + Display + Debug&gt; Error for ChainError&lt;T&gt; {
# fn source(&amp;self) -&gt; Option&lt;&amp;(dyn Error + 'static)&gt; {
# if let Some(ref e) = self.error_cause {
# Some(e.as_ref())
# } else {
# None
# }
# }
# }
#
# impl&lt;T: 'static + Display + Debug&gt; Error for &amp;ChainError&lt;T&gt; {
# fn source(&amp;self) -&gt; Option&lt;&amp;(dyn Error + 'static)&gt; {
# if let Some(ref e) = self.error_cause {
# Some(e.as_ref())
# } else {
# None
# }
# }
# }
#
# impl&lt;T: 'static + Display + Debug&gt; Error for &amp;mut ChainError&lt;T&gt; {
# fn source(&amp;self) -&gt; Option&lt;&amp;(dyn Error + 'static)&gt; {
# if let Some(ref e) = self.error_cause {
# Some(e.as_ref())
# } else {
# None
# }
# }
# }
#
# impl&lt;T: 'static + Display + Debug&gt; Display for ChainError&lt;T&gt; {
# fn fmt(&amp;self, f: &amp;mut Formatter) -&gt; Result {
# write!(f, &quot;{}&quot;, self.kind)?;
#
# #[cfg(feature = &quot;display-cause&quot;)]
# {
# if let Some(e) = self.source() {
# writeln!(f, &quot;\nCaused by:&quot;)?;
# Display::fmt(&amp;e, f)?;
# }
# }
# Ok(())
# }
# }
#
# impl&lt;T: 'static + Display + Debug&gt; Debug for ChainError&lt;T&gt; {
# fn fmt(&amp;self, f: &amp;mut Formatter) -&gt; Result {
# #[cfg(not(feature = &quot;no-fileline&quot;))]
# {
# if let Some(o) = self.occurrence {
# write!(f, &quot;{}:{}: &quot;, o.1, o.0)?;
# }
# }
#
# Debug::fmt(&amp;self.kind, f)?;
#
# #[cfg(not(feature = &quot;no-debug-cause&quot;))]
# {
# if let Some(e) = self.source() {
# writeln!(f, &quot;\nCaused by:&quot;)?;
# Debug::fmt(&amp;e, f)?;
# }
# }
# Ok(())
# }
# }
#
# #[macro_export]
# macro_rules! cherr {
# ( $k:expr ) =&gt; {
# ChainError::&lt;_&gt;::new($k, None, Some((line!(), file!())))
# };
# ( $e:expr, $k:expr ) =&gt; {
# ChainError::&lt;_&gt;::new($k, Some(Box::from($e)), Some((line!(), file!())))
# };
# }
#
# #[macro_export]
# macro_rules! mstrerr {
# ( $t:ident, $v:expr $(, $more:expr)* ) =&gt; {
# |e| cherr!(e, $t (format!($v, $( $more , )* )))
# };
# ( $t:path, $v:expr $(, $more:expr)* ) =&gt; {
# |e| cherr!(e, $t (format!($v, $( $more , )* )))
# };
# ( $v:expr $(, $more:expr)* ) =&gt; {
# |e| cherr!(e, format!($v, $( $more , )* ))
# };
# }
#
# #[macro_export]
# macro_rules! derive_str_cherr {
# ($e:ident) =&gt; {
# struct $e(String);
# impl ::std::fmt::Display for $e {
# fn fmt(&amp;self, f: &amp;mut ::std::fmt::Formatter) -&gt; ::std::fmt::Result {
# write!(f, &quot;{}&quot;, self.0)
# }
# }
# impl ::std::fmt::Debug for $e {
# fn fmt(&amp;self, f: &amp;mut ::std::fmt::Formatter) -&gt; ::std::fmt::Result {
# write!(f, &quot;{}({})&quot;, stringify!($e), self.0)
# }
# }
# impl ::std::error::Error for $e {}
# };
# }
#
# #[macro_export]
# macro_rules! try_cherr_ref {
# ( $e:expr, $t:ident ) =&gt; {
# $e.downcast_ref::&lt;ChainError&lt;$t&gt;&gt;()
# };
# ( $e:expr, $t:path ) =&gt; {
# $e.downcast_ref::&lt;ChainError&lt;$t&gt;&gt;()
# };
# }
#
# #[macro_export]
# macro_rules! try_cherr_mut {
# ( $e:expr, $t:ident ) =&gt; {
# $e.downcast_mut::&lt;ChainError&lt;$t&gt;&gt;()
# };
# ( $e:expr, $t:path ) =&gt; {
# $e.downcast_mut::&lt;ChainError&lt;$t&gt;&gt;()
# };
# }
# }
</code></pre></pre>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="prev" href="tutorial9.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a rel="next" href="tutorial11.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
<div style="clear: both"></div>
</nav>
</div>
</div>
<nav class="nav-wide-wrapper" aria-label="Page navigation">
<a href="tutorial9.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a href="tutorial11.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
</nav>
</div>
<script src="ace.js" type="text/javascript" charset="utf-8"></script>
<script src="editor.js" type="text/javascript" charset="utf-8"></script>
<script src="mode-rust.js" type="text/javascript" charset="utf-8"></script>
<script src="theme-dawn.js" type="text/javascript" charset="utf-8"></script>
<script src="theme-tomorrow_night.js" type="text/javascript" charset="utf-8"></script>
<script src="elasticlunr.min.js" type="text/javascript" charset="utf-8"></script>
<script src="mark.min.js" type="text/javascript" charset="utf-8"></script>
<script src="searcher.js" type="text/javascript" charset="utf-8"></script>
<script src="clipboard.min.js" type="text/javascript" charset="utf-8"></script>
<script src="highlight.js" type="text/javascript" charset="utf-8"></script>
<script src="book.js" type="text/javascript" charset="utf-8"></script>
<!-- Custom JS scripts -->
</body>
</html>

543
tutorial11.html Normal file
View file

@ -0,0 +1,543 @@
<!DOCTYPE HTML>
<html lang="en" class="sidebar-visible no-js">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>Chapter 11 - chainerror</title>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#ffffff" />
<link rel="shortcut icon" href="favicon.png">
<link rel="stylesheet" href="css/variables.css">
<link rel="stylesheet" href="css/general.css">
<link rel="stylesheet" href="css/chrome.css">
<link rel="stylesheet" href="css/print.css" media="print">
<!-- Fonts -->
<link rel="stylesheet" href="FontAwesome/css/font-awesome.css">
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800" rel="stylesheet" type="text/css">
<link href="https://fonts.googleapis.com/css?family=Source+Code+Pro:500" rel="stylesheet" type="text/css">
<!-- Highlight.js Stylesheets -->
<link rel="stylesheet" href="highlight.css">
<link rel="stylesheet" href="tomorrow-night.css">
<link rel="stylesheet" href="ayu-highlight.css">
<!-- Custom theme stylesheets -->
</head>
<body class="light">
<!-- Provide site root to javascript -->
<script type="text/javascript">
var path_to_root = "";
var default_theme = "light";
</script>
<!-- Work around some values being stored in localStorage wrapped in quotes -->
<script type="text/javascript">
try {
var theme = localStorage.getItem('mdbook-theme');
var sidebar = localStorage.getItem('mdbook-sidebar');
if (theme.startsWith('"') && theme.endsWith('"')) {
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
}
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
}
} catch (e) { }
</script>
<!-- Set the theme before any content is loaded, prevents flash -->
<script type="text/javascript">
var theme;
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
if (theme === null || theme === undefined) { theme = default_theme; }
document.body.className = theme;
document.querySelector('html').className = theme + ' js';
</script>
<!-- Hide / unhide sidebar before it is displayed -->
<script type="text/javascript">
var html = document.querySelector('html');
var sidebar = 'hidden';
if (document.body.clientWidth >= 1080) {
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
sidebar = sidebar || 'visible';
}
html.classList.remove('sidebar-visible');
html.classList.add("sidebar-" + sidebar);
</script>
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
<ol class="chapter"><li><a href="tutorial1.html"><strong aria-hidden="true">1.</strong> Chapter 1</a></li><li><a href="tutorial2.html"><strong aria-hidden="true">2.</strong> Chapter 2</a></li><li><a href="tutorial3.html"><strong aria-hidden="true">3.</strong> Chapter 3</a></li><li><a href="tutorial4.html"><strong aria-hidden="true">4.</strong> Chapter 4</a></li><li><a href="tutorial5.html"><strong aria-hidden="true">5.</strong> Chapter 5</a></li><li><a href="tutorial6.html"><strong aria-hidden="true">6.</strong> Chapter 6</a></li><li><a href="tutorial7.html"><strong aria-hidden="true">7.</strong> Chapter 7</a></li><li><a href="tutorial8.html"><strong aria-hidden="true">8.</strong> Chapter 8</a></li><li><a href="tutorial9.html"><strong aria-hidden="true">9.</strong> Chapter 9</a></li><li><a href="tutorial10.html"><strong aria-hidden="true">10.</strong> Chapter 10</a></li><li><a href="tutorial11.html" class="active"><strong aria-hidden="true">11.</strong> Chapter 11</a></li></ol>
</nav>
<div id="page-wrapper" class="page-wrapper">
<div class="page">
<div id="menu-bar" class="menu-bar">
<div id="menu-bar-sticky-container">
<div class="left-buttons">
<button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
<i class="fa fa-bars"></i>
</button>
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
<i class="fa fa-paint-brush"></i>
</button>
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
<li role="none"><button role="menuitem" class="theme" id="light">Light (default)</button></li>
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
</ul>
<button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
<i class="fa fa-search"></i>
</button>
</div>
<h1 class="menu-title">chainerror</h1>
<div class="right-buttons">
<a href="print.html" title="Print this book" aria-label="Print this book">
<i id="print-button" class="fa fa-print"></i>
</a>
</div>
</div>
</div>
<div id="search-wrapper" class="hidden">
<form id="searchbar-outer" class="searchbar-outer">
<input type="search" name="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
</form>
<div id="searchresults-outer" class="searchresults-outer hidden">
<div id="searchresults-header" class="searchresults-header"></div>
<ul id="searchresults">
</ul>
</div>
</div>
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
<script type="text/javascript">
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
});
</script>
<div id="content" class="content">
<main>
<pre><pre class="playpen"><code class="language-rust">use crate::chainerror::*;
use std::error::Error;
use std::io;
use std::result::Result;
fn do_some_io() -&gt; Result&lt;(), Box&lt;Error&gt;&gt; {
Err(io::Error::from(io::ErrorKind::NotFound))?;
Ok(())
}
derive_str_cherr!(Func2Error);
fn func2() -&gt; Result&lt;(), Box&lt;Error&gt;&gt; {
let filename = &quot;foo.txt&quot;;
do_some_io().map_err(mstrerr!(Func2Error, &quot;Error reading '{}'&quot;, filename))?;
Ok(())
}
enum Func1Error {
Func2,
IO(String),
}
impl ::std::fmt::Display for Func1Error {
fn fmt(&amp;self, f: &amp;mut ::std::fmt::Formatter) -&gt; ::std::fmt::Result {
match self {
Func1Error::Func2 =&gt; write!(f, &quot;func1 error calling func2&quot;),
Func1Error::IO(filename) =&gt; write!(f, &quot;Error reading '{}'&quot;, filename),
}
}
}
impl ::std::fmt::Debug for Func1Error {
fn fmt(&amp;self, f: &amp;mut ::std::fmt::Formatter) -&gt; ::std::fmt::Result {
write!(f, &quot;{}&quot;, self)
}
}
fn func1() -&gt; ChainResult&lt;(), Func1Error&gt; {
func2().map_err(|e| cherr!(e, Func1Error::Func2))?;
let filename = String::from(&quot;bar.txt&quot;);
do_some_io().map_err(|e| cherr!(e, Func1Error::IO(filename)))?;
Ok(())
}
fn main() -&gt; Result&lt;(), Box&lt;Error&gt;&gt; {
if let Err(e) = func1() {
match e.kind() {
Func1Error::Func2 =&gt; eprintln!(&quot;Main Error Report: func1 error calling func2&quot;),
Func1Error::IO(filename) =&gt; {
eprintln!(&quot;Main Error Report: func1 error reading '{}'&quot;, filename)
}
}
if let Some(e) = e.find_chain_cause::&lt;Func2Error&gt;() {
eprintln!(&quot;Error reported by Func2Error: {}&quot;, e)
}
eprintln!(&quot;\nDebug Error:\n{:?}&quot;, e);
}
Ok(())
}
# #[allow(dead_code)]
# mod chainerror {
# use std::error::Error;
# use std::fmt::{Debug, Display, Formatter, Result};
# use std::result::Result as StdResult;
#
# pub struct ChainError&lt;T&gt; {
# #[cfg(not(feature = &quot;no-fileline&quot;))]
# occurrence: Option&lt;(u32, &amp;'static str)&gt;,
# kind: T,
# error_cause: Option&lt;Box&lt;dyn Error + 'static&gt;&gt;,
# }
#
# pub type ChainResult&lt;O, E&gt; = StdResult&lt;O, ChainError&lt;E&gt;&gt;;
#
# impl&lt;T: 'static + Display + Debug&gt; ChainError&lt;T&gt; {
# #[cfg(not(feature = &quot;no-fileline&quot;))]
# pub fn new(
# kind: T,
# error_cause: Option&lt;Box&lt;dyn Error + 'static&gt;&gt;,
# occurrence: Option&lt;(u32, &amp;'static str)&gt;,
# ) -&gt; Self {
# Self {
# occurrence,
# kind,
# error_cause,
# }
# }
#
# #[cfg(feature = &quot;no-fileline&quot;)]
# pub fn new(
# kind: T,
# error_cause: Option&lt;Box&lt;dyn Error + 'static&gt;&gt;,
# _occurrence: Option&lt;(u32, &amp;'static str)&gt;,
# ) -&gt; Self {
# Self { kind, error_cause }
# }
#
# pub fn root_cause(&amp;self) -&gt; Option&lt;&amp;(dyn Error + 'static)&gt; {
# let mut cause = self as &amp;(dyn Error + 'static);
# while let Some(c) = cause.source() {
# cause = c;
# }
# Some(cause)
# }
#
# pub fn find_cause&lt;U: Error + 'static&gt;(&amp;self) -&gt; Option&lt;&amp;U&gt; {
# let mut cause = self as &amp;(dyn Error + 'static);
# loop {
# if cause.is::&lt;U&gt;() {
# return cause.downcast_ref::&lt;U&gt;();
# }
#
# match cause.source() {
# Some(c) =&gt; cause = c,
# None =&gt; return None,
# }
# }
# }
#
# pub fn find_chain_cause&lt;U: Error + 'static&gt;(&amp;self) -&gt; Option&lt;&amp;ChainError&lt;U&gt;&gt; {
# let mut cause = self as &amp;(dyn Error + 'static);
# loop {
# if cause.is::&lt;ChainError&lt;U&gt;&gt;() {
# return cause.downcast_ref::&lt;ChainError&lt;U&gt;&gt;();
# }
#
# match cause.source() {
# Some(c) =&gt; cause = c,
# None =&gt; return None,
# }
# }
# }
#
# pub fn kind&lt;'a&gt;(&amp;'a self) -&gt; &amp;'a T {
# &amp;self.kind
# }
# }
#
# pub trait ChainErrorDown {
# fn is_chain&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; bool;
# fn downcast_chain_ref&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; Option&lt;&amp;ChainError&lt;T&gt;&gt;;
# fn downcast_chain_mut&lt;T: 'static + Display + Debug&gt;(&amp;mut self) -&gt; Option&lt;&amp;mut ChainError&lt;T&gt;&gt;;
# }
#
# use std::any::TypeId;
#
# impl&lt;U: 'static + Display + Debug&gt; ChainErrorDown for ChainError&lt;U&gt; {
# fn is_chain&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; bool {
# TypeId::of::&lt;T&gt;() == TypeId::of::&lt;U&gt;()
# }
#
# fn downcast_chain_ref&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; Option&lt;&amp;ChainError&lt;T&gt;&gt; {
# if self.is_chain::&lt;T&gt;() {
# unsafe { Some(&amp;*(self as *const dyn Error as *const &amp;ChainError&lt;T&gt;)) }
# } else {
# None
# }
# }
#
# fn downcast_chain_mut&lt;T: 'static + Display + Debug&gt;(&amp;mut self) -&gt; Option&lt;&amp;mut ChainError&lt;T&gt;&gt; {
# if self.is_chain::&lt;T&gt;() {
# unsafe { Some(&amp;mut *(self as *mut dyn Error as *mut &amp;mut ChainError&lt;T&gt;)) }
# } else {
# None
# }
# }
# }
#
# impl ChainErrorDown for dyn Error + 'static {
# fn is_chain&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; bool {
# self.is::&lt;ChainError&lt;T&gt;&gt;()
# }
#
# fn downcast_chain_ref&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; Option&lt;&amp;ChainError&lt;T&gt;&gt; {
# self.downcast_ref::&lt;ChainError&lt;T&gt;&gt;()
# }
#
# fn downcast_chain_mut&lt;T: 'static + Display + Debug&gt;(&amp;mut self) -&gt; Option&lt;&amp;mut ChainError&lt;T&gt;&gt; {
# self.downcast_mut::&lt;ChainError&lt;T&gt;&gt;()
# }
# }
#
# impl ChainErrorDown for dyn Error + 'static + Send {
# fn is_chain&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; bool {
# self.is::&lt;ChainError&lt;T&gt;&gt;()
# }
#
# fn downcast_chain_ref&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; Option&lt;&amp;ChainError&lt;T&gt;&gt; {
# self.downcast_ref::&lt;ChainError&lt;T&gt;&gt;()
# }
#
# fn downcast_chain_mut&lt;T: 'static + Display + Debug&gt;(&amp;mut self) -&gt; Option&lt;&amp;mut ChainError&lt;T&gt;&gt; {
# self.downcast_mut::&lt;ChainError&lt;T&gt;&gt;()
# }
# }
#
# impl ChainErrorDown for dyn Error + 'static + Send + Sync {
# fn is_chain&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; bool {
# self.is::&lt;ChainError&lt;T&gt;&gt;()
# }
#
# fn downcast_chain_ref&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; Option&lt;&amp;ChainError&lt;T&gt;&gt; {
# self.downcast_ref::&lt;ChainError&lt;T&gt;&gt;()
# }
#
# fn downcast_chain_mut&lt;T: 'static + Display + Debug&gt;(&amp;mut self) -&gt; Option&lt;&amp;mut ChainError&lt;T&gt;&gt; {
# self.downcast_mut::&lt;ChainError&lt;T&gt;&gt;()
# }
# }
#
# impl&lt;T: 'static + Display + Debug&gt; Error for ChainError&lt;T&gt; {
# fn source(&amp;self) -&gt; Option&lt;&amp;(dyn Error + 'static)&gt; {
# if let Some(ref e) = self.error_cause {
# Some(e.as_ref())
# } else {
# None
# }
# }
# }
#
# impl&lt;T: 'static + Display + Debug&gt; Error for &amp;ChainError&lt;T&gt; {
# fn source(&amp;self) -&gt; Option&lt;&amp;(dyn Error + 'static)&gt; {
# if let Some(ref e) = self.error_cause {
# Some(e.as_ref())
# } else {
# None
# }
# }
# }
#
# impl&lt;T: 'static + Display + Debug&gt; Error for &amp;mut ChainError&lt;T&gt; {
# fn source(&amp;self) -&gt; Option&lt;&amp;(dyn Error + 'static)&gt; {
# if let Some(ref e) = self.error_cause {
# Some(e.as_ref())
# } else {
# None
# }
# }
# }
#
# impl&lt;T: 'static + Display + Debug&gt; Display for ChainError&lt;T&gt; {
# fn fmt(&amp;self, f: &amp;mut Formatter) -&gt; Result {
# write!(f, &quot;{}&quot;, self.kind)?;
#
# #[cfg(feature = &quot;display-cause&quot;)]
# {
# if let Some(e) = self.source() {
# writeln!(f, &quot;\nCaused by:&quot;)?;
# Display::fmt(&amp;e, f)?;
# }
# }
# Ok(())
# }
# }
#
# impl&lt;T: 'static + Display + Debug&gt; Debug for ChainError&lt;T&gt; {
# fn fmt(&amp;self, f: &amp;mut Formatter) -&gt; Result {
# #[cfg(not(feature = &quot;no-fileline&quot;))]
# {
# if let Some(o) = self.occurrence {
# write!(f, &quot;{}:{}: &quot;, o.1, o.0)?;
# }
# }
#
# Debug::fmt(&amp;self.kind, f)?;
#
# #[cfg(not(feature = &quot;no-debug-cause&quot;))]
# {
# if let Some(e) = self.source() {
# writeln!(f, &quot;\nCaused by:&quot;)?;
# Debug::fmt(&amp;e, f)?;
# }
# }
# Ok(())
# }
# }
#
# #[macro_export]
# macro_rules! cherr {
# ( $k:expr ) =&gt; {
# ChainError::&lt;_&gt;::new($k, None, Some((line!(), file!())))
# };
# ( $e:expr, $k:expr ) =&gt; {
# ChainError::&lt;_&gt;::new($k, Some(Box::from($e)), Some((line!(), file!())))
# };
# }
#
# #[macro_export]
# macro_rules! mstrerr {
# ( $t:ident, $v:expr $(, $more:expr)* ) =&gt; {
# |e| cherr!(e, $t (format!($v, $( $more , )* )))
# };
# ( $t:path, $v:expr $(, $more:expr)* ) =&gt; {
# |e| cherr!(e, $t (format!($v, $( $more , )* )))
# };
# ( $v:expr $(, $more:expr)* ) =&gt; {
# |e| cherr!(e, format!($v, $( $more , )* ))
# };
# }
#
# #[macro_export]
# macro_rules! derive_str_cherr {
# ($e:ident) =&gt; {
# struct $e(String);
# impl ::std::fmt::Display for $e {
# fn fmt(&amp;self, f: &amp;mut ::std::fmt::Formatter) -&gt; ::std::fmt::Result {
# write!(f, &quot;{}&quot;, self.0)
# }
# }
# impl ::std::fmt::Debug for $e {
# fn fmt(&amp;self, f: &amp;mut ::std::fmt::Formatter) -&gt; ::std::fmt::Result {
# write!(f, &quot;{}({})&quot;, stringify!($e), self.0)
# }
# }
# impl ::std::error::Error for $e {}
# };
# }
#
# #[macro_export]
# macro_rules! try_cherr_ref {
# ( $e:expr, $t:ident ) =&gt; {
# $e.downcast_ref::&lt;ChainError&lt;$t&gt;&gt;()
# };
# ( $e:expr, $t:path ) =&gt; {
# $e.downcast_ref::&lt;ChainError&lt;$t&gt;&gt;()
# };
# }
#
# #[macro_export]
# macro_rules! try_cherr_mut {
# ( $e:expr, $t:ident ) =&gt; {
# $e.downcast_mut::&lt;ChainError&lt;$t&gt;&gt;()
# };
# ( $e:expr, $t:path ) =&gt; {
# $e.downcast_mut::&lt;ChainError&lt;$t&gt;&gt;()
# };
# }
# }
</code></pre></pre>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="prev" href="tutorial10.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<div style="clear: both"></div>
</nav>
</div>
</div>
<nav class="nav-wide-wrapper" aria-label="Page navigation">
<a href="tutorial10.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
</nav>
</div>
<script src="ace.js" type="text/javascript" charset="utf-8"></script>
<script src="editor.js" type="text/javascript" charset="utf-8"></script>
<script src="mode-rust.js" type="text/javascript" charset="utf-8"></script>
<script src="theme-dawn.js" type="text/javascript" charset="utf-8"></script>
<script src="theme-tomorrow_night.js" type="text/javascript" charset="utf-8"></script>
<script src="elasticlunr.min.js" type="text/javascript" charset="utf-8"></script>
<script src="mark.min.js" type="text/javascript" charset="utf-8"></script>
<script src="searcher.js" type="text/javascript" charset="utf-8"></script>
<script src="clipboard.min.js" type="text/javascript" charset="utf-8"></script>
<script src="highlight.js" type="text/javascript" charset="utf-8"></script>
<script src="book.js" type="text/javascript" charset="utf-8"></script>
<!-- Custom JS scripts -->
</body>
</html>

515
tutorial2.html Normal file
View file

@ -0,0 +1,515 @@
<!DOCTYPE HTML>
<html lang="en" class="sidebar-visible no-js">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>Chapter 2 - chainerror</title>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#ffffff" />
<link rel="shortcut icon" href="favicon.png">
<link rel="stylesheet" href="css/variables.css">
<link rel="stylesheet" href="css/general.css">
<link rel="stylesheet" href="css/chrome.css">
<link rel="stylesheet" href="css/print.css" media="print">
<!-- Fonts -->
<link rel="stylesheet" href="FontAwesome/css/font-awesome.css">
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800" rel="stylesheet" type="text/css">
<link href="https://fonts.googleapis.com/css?family=Source+Code+Pro:500" rel="stylesheet" type="text/css">
<!-- Highlight.js Stylesheets -->
<link rel="stylesheet" href="highlight.css">
<link rel="stylesheet" href="tomorrow-night.css">
<link rel="stylesheet" href="ayu-highlight.css">
<!-- Custom theme stylesheets -->
</head>
<body class="light">
<!-- Provide site root to javascript -->
<script type="text/javascript">
var path_to_root = "";
var default_theme = "light";
</script>
<!-- Work around some values being stored in localStorage wrapped in quotes -->
<script type="text/javascript">
try {
var theme = localStorage.getItem('mdbook-theme');
var sidebar = localStorage.getItem('mdbook-sidebar');
if (theme.startsWith('"') && theme.endsWith('"')) {
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
}
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
}
} catch (e) { }
</script>
<!-- Set the theme before any content is loaded, prevents flash -->
<script type="text/javascript">
var theme;
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
if (theme === null || theme === undefined) { theme = default_theme; }
document.body.className = theme;
document.querySelector('html').className = theme + ' js';
</script>
<!-- Hide / unhide sidebar before it is displayed -->
<script type="text/javascript">
var html = document.querySelector('html');
var sidebar = 'hidden';
if (document.body.clientWidth >= 1080) {
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
sidebar = sidebar || 'visible';
}
html.classList.remove('sidebar-visible');
html.classList.add("sidebar-" + sidebar);
</script>
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
<ol class="chapter"><li><a href="tutorial1.html"><strong aria-hidden="true">1.</strong> Chapter 1</a></li><li><a href="tutorial2.html" class="active"><strong aria-hidden="true">2.</strong> Chapter 2</a></li><li><a href="tutorial3.html"><strong aria-hidden="true">3.</strong> Chapter 3</a></li><li><a href="tutorial4.html"><strong aria-hidden="true">4.</strong> Chapter 4</a></li><li><a href="tutorial5.html"><strong aria-hidden="true">5.</strong> Chapter 5</a></li><li><a href="tutorial6.html"><strong aria-hidden="true">6.</strong> Chapter 6</a></li><li><a href="tutorial7.html"><strong aria-hidden="true">7.</strong> Chapter 7</a></li><li><a href="tutorial8.html"><strong aria-hidden="true">8.</strong> Chapter 8</a></li><li><a href="tutorial9.html"><strong aria-hidden="true">9.</strong> Chapter 9</a></li><li><a href="tutorial10.html"><strong aria-hidden="true">10.</strong> Chapter 10</a></li><li><a href="tutorial11.html"><strong aria-hidden="true">11.</strong> Chapter 11</a></li></ol>
</nav>
<div id="page-wrapper" class="page-wrapper">
<div class="page">
<div id="menu-bar" class="menu-bar">
<div id="menu-bar-sticky-container">
<div class="left-buttons">
<button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
<i class="fa fa-bars"></i>
</button>
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
<i class="fa fa-paint-brush"></i>
</button>
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
<li role="none"><button role="menuitem" class="theme" id="light">Light (default)</button></li>
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
</ul>
<button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
<i class="fa fa-search"></i>
</button>
</div>
<h1 class="menu-title">chainerror</h1>
<div class="right-buttons">
<a href="print.html" title="Print this book" aria-label="Print this book">
<i id="print-button" class="fa fa-print"></i>
</a>
</div>
</div>
</div>
<div id="search-wrapper" class="hidden">
<form id="searchbar-outer" class="searchbar-outer">
<input type="search" name="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
</form>
<div id="searchresults-outer" class="searchresults-outer hidden">
<div id="searchresults-header" class="searchresults-header"></div>
<ul id="searchresults">
</ul>
</div>
</div>
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
<script type="text/javascript">
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
});
</script>
<div id="content" class="content">
<main>
<pre><pre class="playpen"><code class="language-rust">use crate::chainerror::*;
use std::error::Error;
use std::result::Result;
fn do_some_io() -&gt; Result&lt;(), Box&lt;Error&gt;&gt; {
Err(&quot;do_some_io error&quot;)?;
Ok(())
}
fn func2() -&gt; Result&lt;(), Box&lt;Error&gt;&gt; {
if let Err(e) = do_some_io() {
Err(cherr!(e, &quot;func2 error&quot;))?;
}
Ok(())
}
fn func1() -&gt; Result&lt;(), Box&lt;Error&gt;&gt; {
if let Err(e) = func2() {
Err(cherr!(e, &quot;func1 error&quot;))?;
}
Ok(())
}
fn main() -&gt; Result&lt;(), Box&lt;Error&gt;&gt; {
func1()
}
# #[allow(dead_code)]
# mod chainerror {
# use std::error::Error;
# use std::fmt::{Debug, Display, Formatter, Result};
# use std::result::Result as StdResult;
#
# pub struct ChainError&lt;T&gt; {
# #[cfg(not(feature = &quot;no-fileline&quot;))]
# occurrence: Option&lt;(u32, &amp;'static str)&gt;,
# kind: T,
# error_cause: Option&lt;Box&lt;dyn Error + 'static&gt;&gt;,
# }
#
# pub type ChainResult&lt;O, E&gt; = StdResult&lt;O, ChainError&lt;E&gt;&gt;;
#
# impl&lt;T: 'static + Display + Debug&gt; ChainError&lt;T&gt; {
# #[cfg(not(feature = &quot;no-fileline&quot;))]
# pub fn new(
# kind: T,
# error_cause: Option&lt;Box&lt;dyn Error + 'static&gt;&gt;,
# occurrence: Option&lt;(u32, &amp;'static str)&gt;,
# ) -&gt; Self {
# Self {
# occurrence,
# kind,
# error_cause,
# }
# }
#
# #[cfg(feature = &quot;no-fileline&quot;)]
# pub fn new(
# kind: T,
# error_cause: Option&lt;Box&lt;dyn Error + 'static&gt;&gt;,
# _occurrence: Option&lt;(u32, &amp;'static str)&gt;,
# ) -&gt; Self {
# Self { kind, error_cause }
# }
#
# pub fn root_cause(&amp;self) -&gt; Option&lt;&amp;(dyn Error + 'static)&gt; {
# let mut cause = self as &amp;(dyn Error + 'static);
# while let Some(c) = cause.source() {
# cause = c;
# }
# Some(cause)
# }
#
# pub fn find_cause&lt;U: Error + 'static&gt;(&amp;self) -&gt; Option&lt;&amp;U&gt; {
# let mut cause = self as &amp;(dyn Error + 'static);
# loop {
# if cause.is::&lt;U&gt;() {
# return cause.downcast_ref::&lt;U&gt;();
# }
#
# match cause.source() {
# Some(c) =&gt; cause = c,
# None =&gt; return None,
# }
# }
# }
#
# pub fn find_chain_cause&lt;U: Error + 'static&gt;(&amp;self) -&gt; Option&lt;&amp;ChainError&lt;U&gt;&gt; {
# let mut cause = self as &amp;(dyn Error + 'static);
# loop {
# if cause.is::&lt;ChainError&lt;U&gt;&gt;() {
# return cause.downcast_ref::&lt;ChainError&lt;U&gt;&gt;();
# }
#
# match cause.source() {
# Some(c) =&gt; cause = c,
# None =&gt; return None,
# }
# }
# }
#
# pub fn kind&lt;'a&gt;(&amp;'a self) -&gt; &amp;'a T {
# &amp;self.kind
# }
# }
#
# pub trait ChainErrorDown {
# fn is_chain&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; bool;
# fn downcast_chain_ref&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; Option&lt;&amp;ChainError&lt;T&gt;&gt;;
# fn downcast_chain_mut&lt;T: 'static + Display + Debug&gt;(&amp;mut self) -&gt; Option&lt;&amp;mut ChainError&lt;T&gt;&gt;;
# }
#
# use std::any::TypeId;
#
# impl&lt;U: 'static + Display + Debug&gt; ChainErrorDown for ChainError&lt;U&gt; {
# fn is_chain&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; bool {
# TypeId::of::&lt;T&gt;() == TypeId::of::&lt;U&gt;()
# }
#
# fn downcast_chain_ref&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; Option&lt;&amp;ChainError&lt;T&gt;&gt; {
# if self.is_chain::&lt;T&gt;() {
# unsafe { Some(&amp;*(self as *const dyn Error as *const &amp;ChainError&lt;T&gt;)) }
# } else {
# None
# }
# }
#
# fn downcast_chain_mut&lt;T: 'static + Display + Debug&gt;(&amp;mut self) -&gt; Option&lt;&amp;mut ChainError&lt;T&gt;&gt; {
# if self.is_chain::&lt;T&gt;() {
# unsafe { Some(&amp;mut *(self as *mut dyn Error as *mut &amp;mut ChainError&lt;T&gt;)) }
# } else {
# None
# }
# }
# }
#
# impl ChainErrorDown for dyn Error + 'static {
# fn is_chain&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; bool {
# self.is::&lt;ChainError&lt;T&gt;&gt;()
# }
#
# fn downcast_chain_ref&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; Option&lt;&amp;ChainError&lt;T&gt;&gt; {
# self.downcast_ref::&lt;ChainError&lt;T&gt;&gt;()
# }
#
# fn downcast_chain_mut&lt;T: 'static + Display + Debug&gt;(&amp;mut self) -&gt; Option&lt;&amp;mut ChainError&lt;T&gt;&gt; {
# self.downcast_mut::&lt;ChainError&lt;T&gt;&gt;()
# }
# }
#
# impl ChainErrorDown for dyn Error + 'static + Send {
# fn is_chain&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; bool {
# self.is::&lt;ChainError&lt;T&gt;&gt;()
# }
#
# fn downcast_chain_ref&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; Option&lt;&amp;ChainError&lt;T&gt;&gt; {
# self.downcast_ref::&lt;ChainError&lt;T&gt;&gt;()
# }
#
# fn downcast_chain_mut&lt;T: 'static + Display + Debug&gt;(&amp;mut self) -&gt; Option&lt;&amp;mut ChainError&lt;T&gt;&gt; {
# self.downcast_mut::&lt;ChainError&lt;T&gt;&gt;()
# }
# }
#
# impl ChainErrorDown for dyn Error + 'static + Send + Sync {
# fn is_chain&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; bool {
# self.is::&lt;ChainError&lt;T&gt;&gt;()
# }
#
# fn downcast_chain_ref&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; Option&lt;&amp;ChainError&lt;T&gt;&gt; {
# self.downcast_ref::&lt;ChainError&lt;T&gt;&gt;()
# }
#
# fn downcast_chain_mut&lt;T: 'static + Display + Debug&gt;(&amp;mut self) -&gt; Option&lt;&amp;mut ChainError&lt;T&gt;&gt; {
# self.downcast_mut::&lt;ChainError&lt;T&gt;&gt;()
# }
# }
#
# impl&lt;T: 'static + Display + Debug&gt; Error for ChainError&lt;T&gt; {
# fn source(&amp;self) -&gt; Option&lt;&amp;(dyn Error + 'static)&gt; {
# if let Some(ref e) = self.error_cause {
# Some(e.as_ref())
# } else {
# None
# }
# }
# }
#
# impl&lt;T: 'static + Display + Debug&gt; Error for &amp;ChainError&lt;T&gt; {
# fn source(&amp;self) -&gt; Option&lt;&amp;(dyn Error + 'static)&gt; {
# if let Some(ref e) = self.error_cause {
# Some(e.as_ref())
# } else {
# None
# }
# }
# }
#
# impl&lt;T: 'static + Display + Debug&gt; Error for &amp;mut ChainError&lt;T&gt; {
# fn source(&amp;self) -&gt; Option&lt;&amp;(dyn Error + 'static)&gt; {
# if let Some(ref e) = self.error_cause {
# Some(e.as_ref())
# } else {
# None
# }
# }
# }
#
# impl&lt;T: 'static + Display + Debug&gt; Display for ChainError&lt;T&gt; {
# fn fmt(&amp;self, f: &amp;mut Formatter) -&gt; Result {
# write!(f, &quot;{}&quot;, self.kind)?;
#
# #[cfg(feature = &quot;display-cause&quot;)]
# {
# if let Some(e) = self.source() {
# writeln!(f, &quot;\nCaused by:&quot;)?;
# Display::fmt(&amp;e, f)?;
# }
# }
# Ok(())
# }
# }
#
# impl&lt;T: 'static + Display + Debug&gt; Debug for ChainError&lt;T&gt; {
# fn fmt(&amp;self, f: &amp;mut Formatter) -&gt; Result {
# #[cfg(not(feature = &quot;no-fileline&quot;))]
# {
# if let Some(o) = self.occurrence {
# write!(f, &quot;{}:{}: &quot;, o.1, o.0)?;
# }
# }
#
# Debug::fmt(&amp;self.kind, f)?;
#
# #[cfg(not(feature = &quot;no-debug-cause&quot;))]
# {
# if let Some(e) = self.source() {
# writeln!(f, &quot;\nCaused by:&quot;)?;
# Debug::fmt(&amp;e, f)?;
# }
# }
# Ok(())
# }
# }
#
# #[macro_export]
# macro_rules! cherr {
# ( $k:expr ) =&gt; {
# ChainError::&lt;_&gt;::new($k, None, Some((line!(), file!())))
# };
# ( $e:expr, $k:expr ) =&gt; {
# ChainError::&lt;_&gt;::new($k, Some(Box::from($e)), Some((line!(), file!())))
# };
# }
#
# #[macro_export]
# macro_rules! mstrerr {
# ( $t:ident, $v:expr $(, $more:expr)* ) =&gt; {
# |e| cherr!(e, $t (format!($v, $( $more , )* )))
# };
# ( $t:path, $v:expr $(, $more:expr)* ) =&gt; {
# |e| cherr!(e, $t (format!($v, $( $more , )* )))
# };
# ( $v:expr $(, $more:expr)* ) =&gt; {
# |e| cherr!(e, format!($v, $( $more , )* ))
# };
# }
#
# #[macro_export]
# macro_rules! derive_str_cherr {
# ($e:ident) =&gt; {
# struct $e(String);
# impl ::std::fmt::Display for $e {
# fn fmt(&amp;self, f: &amp;mut ::std::fmt::Formatter) -&gt; ::std::fmt::Result {
# write!(f, &quot;{}&quot;, self.0)
# }
# }
# impl ::std::fmt::Debug for $e {
# fn fmt(&amp;self, f: &amp;mut ::std::fmt::Formatter) -&gt; ::std::fmt::Result {
# write!(f, &quot;{}({})&quot;, stringify!($e), self.0)
# }
# }
# impl ::std::error::Error for $e {}
# };
# }
#
# #[macro_export]
# macro_rules! try_cherr_ref {
# ( $e:expr, $t:ident ) =&gt; {
# $e.downcast_ref::&lt;ChainError&lt;$t&gt;&gt;()
# };
# ( $e:expr, $t:path ) =&gt; {
# $e.downcast_ref::&lt;ChainError&lt;$t&gt;&gt;()
# };
# }
#
# #[macro_export]
# macro_rules! try_cherr_mut {
# ( $e:expr, $t:ident ) =&gt; {
# $e.downcast_mut::&lt;ChainError&lt;$t&gt;&gt;()
# };
# ( $e:expr, $t:path ) =&gt; {
# $e.downcast_mut::&lt;ChainError&lt;$t&gt;&gt;()
# };
# }
# }
</code></pre></pre>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="prev" href="tutorial1.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a rel="next" href="tutorial3.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
<div style="clear: both"></div>
</nav>
</div>
</div>
<nav class="nav-wide-wrapper" aria-label="Page navigation">
<a href="tutorial1.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a href="tutorial3.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
</nav>
</div>
<script src="ace.js" type="text/javascript" charset="utf-8"></script>
<script src="editor.js" type="text/javascript" charset="utf-8"></script>
<script src="mode-rust.js" type="text/javascript" charset="utf-8"></script>
<script src="theme-dawn.js" type="text/javascript" charset="utf-8"></script>
<script src="theme-tomorrow_night.js" type="text/javascript" charset="utf-8"></script>
<script src="elasticlunr.min.js" type="text/javascript" charset="utf-8"></script>
<script src="mark.min.js" type="text/javascript" charset="utf-8"></script>
<script src="searcher.js" type="text/javascript" charset="utf-8"></script>
<script src="clipboard.min.js" type="text/javascript" charset="utf-8"></script>
<script src="highlight.js" type="text/javascript" charset="utf-8"></script>
<script src="book.js" type="text/javascript" charset="utf-8"></script>
<!-- Custom JS scripts -->
</body>
</html>

514
tutorial3.html Normal file
View file

@ -0,0 +1,514 @@
<!DOCTYPE HTML>
<html lang="en" class="sidebar-visible no-js">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>Chapter 3 - chainerror</title>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#ffffff" />
<link rel="shortcut icon" href="favicon.png">
<link rel="stylesheet" href="css/variables.css">
<link rel="stylesheet" href="css/general.css">
<link rel="stylesheet" href="css/chrome.css">
<link rel="stylesheet" href="css/print.css" media="print">
<!-- Fonts -->
<link rel="stylesheet" href="FontAwesome/css/font-awesome.css">
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800" rel="stylesheet" type="text/css">
<link href="https://fonts.googleapis.com/css?family=Source+Code+Pro:500" rel="stylesheet" type="text/css">
<!-- Highlight.js Stylesheets -->
<link rel="stylesheet" href="highlight.css">
<link rel="stylesheet" href="tomorrow-night.css">
<link rel="stylesheet" href="ayu-highlight.css">
<!-- Custom theme stylesheets -->
</head>
<body class="light">
<!-- Provide site root to javascript -->
<script type="text/javascript">
var path_to_root = "";
var default_theme = "light";
</script>
<!-- Work around some values being stored in localStorage wrapped in quotes -->
<script type="text/javascript">
try {
var theme = localStorage.getItem('mdbook-theme');
var sidebar = localStorage.getItem('mdbook-sidebar');
if (theme.startsWith('"') && theme.endsWith('"')) {
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
}
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
}
} catch (e) { }
</script>
<!-- Set the theme before any content is loaded, prevents flash -->
<script type="text/javascript">
var theme;
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
if (theme === null || theme === undefined) { theme = default_theme; }
document.body.className = theme;
document.querySelector('html').className = theme + ' js';
</script>
<!-- Hide / unhide sidebar before it is displayed -->
<script type="text/javascript">
var html = document.querySelector('html');
var sidebar = 'hidden';
if (document.body.clientWidth >= 1080) {
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
sidebar = sidebar || 'visible';
}
html.classList.remove('sidebar-visible');
html.classList.add("sidebar-" + sidebar);
</script>
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
<ol class="chapter"><li><a href="tutorial1.html"><strong aria-hidden="true">1.</strong> Chapter 1</a></li><li><a href="tutorial2.html"><strong aria-hidden="true">2.</strong> Chapter 2</a></li><li><a href="tutorial3.html" class="active"><strong aria-hidden="true">3.</strong> Chapter 3</a></li><li><a href="tutorial4.html"><strong aria-hidden="true">4.</strong> Chapter 4</a></li><li><a href="tutorial5.html"><strong aria-hidden="true">5.</strong> Chapter 5</a></li><li><a href="tutorial6.html"><strong aria-hidden="true">6.</strong> Chapter 6</a></li><li><a href="tutorial7.html"><strong aria-hidden="true">7.</strong> Chapter 7</a></li><li><a href="tutorial8.html"><strong aria-hidden="true">8.</strong> Chapter 8</a></li><li><a href="tutorial9.html"><strong aria-hidden="true">9.</strong> Chapter 9</a></li><li><a href="tutorial10.html"><strong aria-hidden="true">10.</strong> Chapter 10</a></li><li><a href="tutorial11.html"><strong aria-hidden="true">11.</strong> Chapter 11</a></li></ol>
</nav>
<div id="page-wrapper" class="page-wrapper">
<div class="page">
<div id="menu-bar" class="menu-bar">
<div id="menu-bar-sticky-container">
<div class="left-buttons">
<button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
<i class="fa fa-bars"></i>
</button>
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
<i class="fa fa-paint-brush"></i>
</button>
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
<li role="none"><button role="menuitem" class="theme" id="light">Light (default)</button></li>
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
</ul>
<button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
<i class="fa fa-search"></i>
</button>
</div>
<h1 class="menu-title">chainerror</h1>
<div class="right-buttons">
<a href="print.html" title="Print this book" aria-label="Print this book">
<i id="print-button" class="fa fa-print"></i>
</a>
</div>
</div>
</div>
<div id="search-wrapper" class="hidden">
<form id="searchbar-outer" class="searchbar-outer">
<input type="search" name="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
</form>
<div id="searchresults-outer" class="searchresults-outer hidden">
<div id="searchresults-header" class="searchresults-header"></div>
<ul id="searchresults">
</ul>
</div>
</div>
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
<script type="text/javascript">
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
});
</script>
<div id="content" class="content">
<main>
<pre><pre class="playpen"><code class="language-rust">use crate::chainerror::*;
use std::error::Error;
use std::result::Result;
fn do_some_io() -&gt; Result&lt;(), Box&lt;Error&gt;&gt; {
Err(&quot;do_some_io error&quot;)?;
Ok(())
}
fn func2() -&gt; Result&lt;(), Box&lt;Error&gt;&gt; {
do_some_io().map_err(|e| cherr!(e, &quot;func2 error&quot;))?;
Ok(())
}
fn func1() -&gt; Result&lt;(), Box&lt;Error&gt;&gt; {
func2().map_err(|e| cherr!(e, &quot;func1 error&quot;))?;
Ok(())
}
fn main() -&gt; Result&lt;(), Box&lt;Error&gt;&gt; {
if let Err(e) = func1() {
eprintln!(&quot;{:?}&quot;, e);
}
Ok(())
}
# #[allow(dead_code)]
# mod chainerror {
# use std::error::Error;
# use std::fmt::{Debug, Display, Formatter, Result};
# use std::result::Result as StdResult;
#
# pub struct ChainError&lt;T&gt; {
# #[cfg(not(feature = &quot;no-fileline&quot;))]
# occurrence: Option&lt;(u32, &amp;'static str)&gt;,
# kind: T,
# error_cause: Option&lt;Box&lt;dyn Error + 'static&gt;&gt;,
# }
#
# pub type ChainResult&lt;O, E&gt; = StdResult&lt;O, ChainError&lt;E&gt;&gt;;
#
# impl&lt;T: 'static + Display + Debug&gt; ChainError&lt;T&gt; {
# #[cfg(not(feature = &quot;no-fileline&quot;))]
# pub fn new(
# kind: T,
# error_cause: Option&lt;Box&lt;dyn Error + 'static&gt;&gt;,
# occurrence: Option&lt;(u32, &amp;'static str)&gt;,
# ) -&gt; Self {
# Self {
# occurrence,
# kind,
# error_cause,
# }
# }
#
# #[cfg(feature = &quot;no-fileline&quot;)]
# pub fn new(
# kind: T,
# error_cause: Option&lt;Box&lt;dyn Error + 'static&gt;&gt;,
# _occurrence: Option&lt;(u32, &amp;'static str)&gt;,
# ) -&gt; Self {
# Self { kind, error_cause }
# }
#
# pub fn root_cause(&amp;self) -&gt; Option&lt;&amp;(dyn Error + 'static)&gt; {
# let mut cause = self as &amp;(dyn Error + 'static);
# while let Some(c) = cause.source() {
# cause = c;
# }
# Some(cause)
# }
#
# pub fn find_cause&lt;U: Error + 'static&gt;(&amp;self) -&gt; Option&lt;&amp;U&gt; {
# let mut cause = self as &amp;(dyn Error + 'static);
# loop {
# if cause.is::&lt;U&gt;() {
# return cause.downcast_ref::&lt;U&gt;();
# }
#
# match cause.source() {
# Some(c) =&gt; cause = c,
# None =&gt; return None,
# }
# }
# }
#
# pub fn find_chain_cause&lt;U: Error + 'static&gt;(&amp;self) -&gt; Option&lt;&amp;ChainError&lt;U&gt;&gt; {
# let mut cause = self as &amp;(dyn Error + 'static);
# loop {
# if cause.is::&lt;ChainError&lt;U&gt;&gt;() {
# return cause.downcast_ref::&lt;ChainError&lt;U&gt;&gt;();
# }
#
# match cause.source() {
# Some(c) =&gt; cause = c,
# None =&gt; return None,
# }
# }
# }
#
# pub fn kind&lt;'a&gt;(&amp;'a self) -&gt; &amp;'a T {
# &amp;self.kind
# }
# }
#
# pub trait ChainErrorDown {
# fn is_chain&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; bool;
# fn downcast_chain_ref&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; Option&lt;&amp;ChainError&lt;T&gt;&gt;;
# fn downcast_chain_mut&lt;T: 'static + Display + Debug&gt;(&amp;mut self) -&gt; Option&lt;&amp;mut ChainError&lt;T&gt;&gt;;
# }
#
# use std::any::TypeId;
#
# impl&lt;U: 'static + Display + Debug&gt; ChainErrorDown for ChainError&lt;U&gt; {
# fn is_chain&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; bool {
# TypeId::of::&lt;T&gt;() == TypeId::of::&lt;U&gt;()
# }
#
# fn downcast_chain_ref&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; Option&lt;&amp;ChainError&lt;T&gt;&gt; {
# if self.is_chain::&lt;T&gt;() {
# unsafe { Some(&amp;*(self as *const dyn Error as *const &amp;ChainError&lt;T&gt;)) }
# } else {
# None
# }
# }
#
# fn downcast_chain_mut&lt;T: 'static + Display + Debug&gt;(&amp;mut self) -&gt; Option&lt;&amp;mut ChainError&lt;T&gt;&gt; {
# if self.is_chain::&lt;T&gt;() {
# unsafe { Some(&amp;mut *(self as *mut dyn Error as *mut &amp;mut ChainError&lt;T&gt;)) }
# } else {
# None
# }
# }
# }
#
# impl ChainErrorDown for dyn Error + 'static {
# fn is_chain&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; bool {
# self.is::&lt;ChainError&lt;T&gt;&gt;()
# }
#
# fn downcast_chain_ref&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; Option&lt;&amp;ChainError&lt;T&gt;&gt; {
# self.downcast_ref::&lt;ChainError&lt;T&gt;&gt;()
# }
#
# fn downcast_chain_mut&lt;T: 'static + Display + Debug&gt;(&amp;mut self) -&gt; Option&lt;&amp;mut ChainError&lt;T&gt;&gt; {
# self.downcast_mut::&lt;ChainError&lt;T&gt;&gt;()
# }
# }
#
# impl ChainErrorDown for dyn Error + 'static + Send {
# fn is_chain&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; bool {
# self.is::&lt;ChainError&lt;T&gt;&gt;()
# }
#
# fn downcast_chain_ref&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; Option&lt;&amp;ChainError&lt;T&gt;&gt; {
# self.downcast_ref::&lt;ChainError&lt;T&gt;&gt;()
# }
#
# fn downcast_chain_mut&lt;T: 'static + Display + Debug&gt;(&amp;mut self) -&gt; Option&lt;&amp;mut ChainError&lt;T&gt;&gt; {
# self.downcast_mut::&lt;ChainError&lt;T&gt;&gt;()
# }
# }
#
# impl ChainErrorDown for dyn Error + 'static + Send + Sync {
# fn is_chain&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; bool {
# self.is::&lt;ChainError&lt;T&gt;&gt;()
# }
#
# fn downcast_chain_ref&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; Option&lt;&amp;ChainError&lt;T&gt;&gt; {
# self.downcast_ref::&lt;ChainError&lt;T&gt;&gt;()
# }
#
# fn downcast_chain_mut&lt;T: 'static + Display + Debug&gt;(&amp;mut self) -&gt; Option&lt;&amp;mut ChainError&lt;T&gt;&gt; {
# self.downcast_mut::&lt;ChainError&lt;T&gt;&gt;()
# }
# }
#
# impl&lt;T: 'static + Display + Debug&gt; Error for ChainError&lt;T&gt; {
# fn source(&amp;self) -&gt; Option&lt;&amp;(dyn Error + 'static)&gt; {
# if let Some(ref e) = self.error_cause {
# Some(e.as_ref())
# } else {
# None
# }
# }
# }
#
# impl&lt;T: 'static + Display + Debug&gt; Error for &amp;ChainError&lt;T&gt; {
# fn source(&amp;self) -&gt; Option&lt;&amp;(dyn Error + 'static)&gt; {
# if let Some(ref e) = self.error_cause {
# Some(e.as_ref())
# } else {
# None
# }
# }
# }
#
# impl&lt;T: 'static + Display + Debug&gt; Error for &amp;mut ChainError&lt;T&gt; {
# fn source(&amp;self) -&gt; Option&lt;&amp;(dyn Error + 'static)&gt; {
# if let Some(ref e) = self.error_cause {
# Some(e.as_ref())
# } else {
# None
# }
# }
# }
#
# impl&lt;T: 'static + Display + Debug&gt; Display for ChainError&lt;T&gt; {
# fn fmt(&amp;self, f: &amp;mut Formatter) -&gt; Result {
# write!(f, &quot;{}&quot;, self.kind)?;
#
# #[cfg(feature = &quot;display-cause&quot;)]
# {
# if let Some(e) = self.source() {
# writeln!(f, &quot;\nCaused by:&quot;)?;
# Display::fmt(&amp;e, f)?;
# }
# }
# Ok(())
# }
# }
#
# impl&lt;T: 'static + Display + Debug&gt; Debug for ChainError&lt;T&gt; {
# fn fmt(&amp;self, f: &amp;mut Formatter) -&gt; Result {
# #[cfg(not(feature = &quot;no-fileline&quot;))]
# {
# if let Some(o) = self.occurrence {
# write!(f, &quot;{}:{}: &quot;, o.1, o.0)?;
# }
# }
#
# Debug::fmt(&amp;self.kind, f)?;
#
# #[cfg(not(feature = &quot;no-debug-cause&quot;))]
# {
# if let Some(e) = self.source() {
# writeln!(f, &quot;\nCaused by:&quot;)?;
# Debug::fmt(&amp;e, f)?;
# }
# }
# Ok(())
# }
# }
#
# #[macro_export]
# macro_rules! cherr {
# ( $k:expr ) =&gt; {
# ChainError::&lt;_&gt;::new($k, None, Some((line!(), file!())))
# };
# ( $e:expr, $k:expr ) =&gt; {
# ChainError::&lt;_&gt;::new($k, Some(Box::from($e)), Some((line!(), file!())))
# };
# }
#
# #[macro_export]
# macro_rules! mstrerr {
# ( $t:ident, $v:expr $(, $more:expr)* ) =&gt; {
# |e| cherr!(e, $t (format!($v, $( $more , )* )))
# };
# ( $t:path, $v:expr $(, $more:expr)* ) =&gt; {
# |e| cherr!(e, $t (format!($v, $( $more , )* )))
# };
# ( $v:expr $(, $more:expr)* ) =&gt; {
# |e| cherr!(e, format!($v, $( $more , )* ))
# };
# }
#
# #[macro_export]
# macro_rules! derive_str_cherr {
# ($e:ident) =&gt; {
# struct $e(String);
# impl ::std::fmt::Display for $e {
# fn fmt(&amp;self, f: &amp;mut ::std::fmt::Formatter) -&gt; ::std::fmt::Result {
# write!(f, &quot;{}&quot;, self.0)
# }
# }
# impl ::std::fmt::Debug for $e {
# fn fmt(&amp;self, f: &amp;mut ::std::fmt::Formatter) -&gt; ::std::fmt::Result {
# write!(f, &quot;{}({})&quot;, stringify!($e), self.0)
# }
# }
# impl ::std::error::Error for $e {}
# };
# }
#
# #[macro_export]
# macro_rules! try_cherr_ref {
# ( $e:expr, $t:ident ) =&gt; {
# $e.downcast_ref::&lt;ChainError&lt;$t&gt;&gt;()
# };
# ( $e:expr, $t:path ) =&gt; {
# $e.downcast_ref::&lt;ChainError&lt;$t&gt;&gt;()
# };
# }
#
# #[macro_export]
# macro_rules! try_cherr_mut {
# ( $e:expr, $t:ident ) =&gt; {
# $e.downcast_mut::&lt;ChainError&lt;$t&gt;&gt;()
# };
# ( $e:expr, $t:path ) =&gt; {
# $e.downcast_mut::&lt;ChainError&lt;$t&gt;&gt;()
# };
# }
# }
</code></pre></pre>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="prev" href="tutorial2.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a rel="next" href="tutorial4.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
<div style="clear: both"></div>
</nav>
</div>
</div>
<nav class="nav-wide-wrapper" aria-label="Page navigation">
<a href="tutorial2.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a href="tutorial4.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
</nav>
</div>
<script src="ace.js" type="text/javascript" charset="utf-8"></script>
<script src="editor.js" type="text/javascript" charset="utf-8"></script>
<script src="mode-rust.js" type="text/javascript" charset="utf-8"></script>
<script src="theme-dawn.js" type="text/javascript" charset="utf-8"></script>
<script src="theme-tomorrow_night.js" type="text/javascript" charset="utf-8"></script>
<script src="elasticlunr.min.js" type="text/javascript" charset="utf-8"></script>
<script src="mark.min.js" type="text/javascript" charset="utf-8"></script>
<script src="searcher.js" type="text/javascript" charset="utf-8"></script>
<script src="clipboard.min.js" type="text/javascript" charset="utf-8"></script>
<script src="highlight.js" type="text/javascript" charset="utf-8"></script>
<script src="book.js" type="text/javascript" charset="utf-8"></script>
<!-- Custom JS scripts -->
</body>
</html>

514
tutorial4.html Normal file
View file

@ -0,0 +1,514 @@
<!DOCTYPE HTML>
<html lang="en" class="sidebar-visible no-js">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>Chapter 4 - chainerror</title>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#ffffff" />
<link rel="shortcut icon" href="favicon.png">
<link rel="stylesheet" href="css/variables.css">
<link rel="stylesheet" href="css/general.css">
<link rel="stylesheet" href="css/chrome.css">
<link rel="stylesheet" href="css/print.css" media="print">
<!-- Fonts -->
<link rel="stylesheet" href="FontAwesome/css/font-awesome.css">
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800" rel="stylesheet" type="text/css">
<link href="https://fonts.googleapis.com/css?family=Source+Code+Pro:500" rel="stylesheet" type="text/css">
<!-- Highlight.js Stylesheets -->
<link rel="stylesheet" href="highlight.css">
<link rel="stylesheet" href="tomorrow-night.css">
<link rel="stylesheet" href="ayu-highlight.css">
<!-- Custom theme stylesheets -->
</head>
<body class="light">
<!-- Provide site root to javascript -->
<script type="text/javascript">
var path_to_root = "";
var default_theme = "light";
</script>
<!-- Work around some values being stored in localStorage wrapped in quotes -->
<script type="text/javascript">
try {
var theme = localStorage.getItem('mdbook-theme');
var sidebar = localStorage.getItem('mdbook-sidebar');
if (theme.startsWith('"') && theme.endsWith('"')) {
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
}
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
}
} catch (e) { }
</script>
<!-- Set the theme before any content is loaded, prevents flash -->
<script type="text/javascript">
var theme;
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
if (theme === null || theme === undefined) { theme = default_theme; }
document.body.className = theme;
document.querySelector('html').className = theme + ' js';
</script>
<!-- Hide / unhide sidebar before it is displayed -->
<script type="text/javascript">
var html = document.querySelector('html');
var sidebar = 'hidden';
if (document.body.clientWidth >= 1080) {
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
sidebar = sidebar || 'visible';
}
html.classList.remove('sidebar-visible');
html.classList.add("sidebar-" + sidebar);
</script>
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
<ol class="chapter"><li><a href="tutorial1.html"><strong aria-hidden="true">1.</strong> Chapter 1</a></li><li><a href="tutorial2.html"><strong aria-hidden="true">2.</strong> Chapter 2</a></li><li><a href="tutorial3.html"><strong aria-hidden="true">3.</strong> Chapter 3</a></li><li><a href="tutorial4.html" class="active"><strong aria-hidden="true">4.</strong> Chapter 4</a></li><li><a href="tutorial5.html"><strong aria-hidden="true">5.</strong> Chapter 5</a></li><li><a href="tutorial6.html"><strong aria-hidden="true">6.</strong> Chapter 6</a></li><li><a href="tutorial7.html"><strong aria-hidden="true">7.</strong> Chapter 7</a></li><li><a href="tutorial8.html"><strong aria-hidden="true">8.</strong> Chapter 8</a></li><li><a href="tutorial9.html"><strong aria-hidden="true">9.</strong> Chapter 9</a></li><li><a href="tutorial10.html"><strong aria-hidden="true">10.</strong> Chapter 10</a></li><li><a href="tutorial11.html"><strong aria-hidden="true">11.</strong> Chapter 11</a></li></ol>
</nav>
<div id="page-wrapper" class="page-wrapper">
<div class="page">
<div id="menu-bar" class="menu-bar">
<div id="menu-bar-sticky-container">
<div class="left-buttons">
<button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
<i class="fa fa-bars"></i>
</button>
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
<i class="fa fa-paint-brush"></i>
</button>
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
<li role="none"><button role="menuitem" class="theme" id="light">Light (default)</button></li>
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
</ul>
<button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
<i class="fa fa-search"></i>
</button>
</div>
<h1 class="menu-title">chainerror</h1>
<div class="right-buttons">
<a href="print.html" title="Print this book" aria-label="Print this book">
<i id="print-button" class="fa fa-print"></i>
</a>
</div>
</div>
</div>
<div id="search-wrapper" class="hidden">
<form id="searchbar-outer" class="searchbar-outer">
<input type="search" name="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
</form>
<div id="searchresults-outer" class="searchresults-outer hidden">
<div id="searchresults-header" class="searchresults-header"></div>
<ul id="searchresults">
</ul>
</div>
</div>
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
<script type="text/javascript">
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
});
</script>
<div id="content" class="content">
<main>
<pre><pre class="playpen"><code class="language-rust">use crate::chainerror::*;
use std::error::Error;
use std::result::Result;
fn do_some_io() -&gt; Result&lt;(), Box&lt;Error&gt;&gt; {
Err(&quot;do_some_io error&quot;)?;
Ok(())
}
fn func2() -&gt; Result&lt;(), Box&lt;Error&gt;&gt; {
do_some_io().map_err(mstrerr!(&quot;func2 error&quot;))?;
Ok(())
}
fn func1() -&gt; Result&lt;(), Box&lt;Error&gt;&gt; {
func2().map_err(mstrerr!(&quot;func1 error&quot;))?;
Ok(())
}
fn main() -&gt; Result&lt;(), Box&lt;Error&gt;&gt; {
if let Err(e) = func1() {
eprintln!(&quot;{:?}&quot;, e);
}
Ok(())
}
# #[allow(dead_code)]
# mod chainerror {
# use std::error::Error;
# use std::fmt::{Debug, Display, Formatter, Result};
# use std::result::Result as StdResult;
#
# pub struct ChainError&lt;T&gt; {
# #[cfg(not(feature = &quot;no-fileline&quot;))]
# occurrence: Option&lt;(u32, &amp;'static str)&gt;,
# kind: T,
# error_cause: Option&lt;Box&lt;dyn Error + 'static&gt;&gt;,
# }
#
# pub type ChainResult&lt;O, E&gt; = StdResult&lt;O, ChainError&lt;E&gt;&gt;;
#
# impl&lt;T: 'static + Display + Debug&gt; ChainError&lt;T&gt; {
# #[cfg(not(feature = &quot;no-fileline&quot;))]
# pub fn new(
# kind: T,
# error_cause: Option&lt;Box&lt;dyn Error + 'static&gt;&gt;,
# occurrence: Option&lt;(u32, &amp;'static str)&gt;,
# ) -&gt; Self {
# Self {
# occurrence,
# kind,
# error_cause,
# }
# }
#
# #[cfg(feature = &quot;no-fileline&quot;)]
# pub fn new(
# kind: T,
# error_cause: Option&lt;Box&lt;dyn Error + 'static&gt;&gt;,
# _occurrence: Option&lt;(u32, &amp;'static str)&gt;,
# ) -&gt; Self {
# Self { kind, error_cause }
# }
#
# pub fn root_cause(&amp;self) -&gt; Option&lt;&amp;(dyn Error + 'static)&gt; {
# let mut cause = self as &amp;(dyn Error + 'static);
# while let Some(c) = cause.source() {
# cause = c;
# }
# Some(cause)
# }
#
# pub fn find_cause&lt;U: Error + 'static&gt;(&amp;self) -&gt; Option&lt;&amp;U&gt; {
# let mut cause = self as &amp;(dyn Error + 'static);
# loop {
# if cause.is::&lt;U&gt;() {
# return cause.downcast_ref::&lt;U&gt;();
# }
#
# match cause.source() {
# Some(c) =&gt; cause = c,
# None =&gt; return None,
# }
# }
# }
#
# pub fn find_chain_cause&lt;U: Error + 'static&gt;(&amp;self) -&gt; Option&lt;&amp;ChainError&lt;U&gt;&gt; {
# let mut cause = self as &amp;(dyn Error + 'static);
# loop {
# if cause.is::&lt;ChainError&lt;U&gt;&gt;() {
# return cause.downcast_ref::&lt;ChainError&lt;U&gt;&gt;();
# }
#
# match cause.source() {
# Some(c) =&gt; cause = c,
# None =&gt; return None,
# }
# }
# }
#
# pub fn kind&lt;'a&gt;(&amp;'a self) -&gt; &amp;'a T {
# &amp;self.kind
# }
# }
#
# pub trait ChainErrorDown {
# fn is_chain&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; bool;
# fn downcast_chain_ref&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; Option&lt;&amp;ChainError&lt;T&gt;&gt;;
# fn downcast_chain_mut&lt;T: 'static + Display + Debug&gt;(&amp;mut self) -&gt; Option&lt;&amp;mut ChainError&lt;T&gt;&gt;;
# }
#
# use std::any::TypeId;
#
# impl&lt;U: 'static + Display + Debug&gt; ChainErrorDown for ChainError&lt;U&gt; {
# fn is_chain&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; bool {
# TypeId::of::&lt;T&gt;() == TypeId::of::&lt;U&gt;()
# }
#
# fn downcast_chain_ref&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; Option&lt;&amp;ChainError&lt;T&gt;&gt; {
# if self.is_chain::&lt;T&gt;() {
# unsafe { Some(&amp;*(self as *const dyn Error as *const &amp;ChainError&lt;T&gt;)) }
# } else {
# None
# }
# }
#
# fn downcast_chain_mut&lt;T: 'static + Display + Debug&gt;(&amp;mut self) -&gt; Option&lt;&amp;mut ChainError&lt;T&gt;&gt; {
# if self.is_chain::&lt;T&gt;() {
# unsafe { Some(&amp;mut *(self as *mut dyn Error as *mut &amp;mut ChainError&lt;T&gt;)) }
# } else {
# None
# }
# }
# }
#
# impl ChainErrorDown for dyn Error + 'static {
# fn is_chain&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; bool {
# self.is::&lt;ChainError&lt;T&gt;&gt;()
# }
#
# fn downcast_chain_ref&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; Option&lt;&amp;ChainError&lt;T&gt;&gt; {
# self.downcast_ref::&lt;ChainError&lt;T&gt;&gt;()
# }
#
# fn downcast_chain_mut&lt;T: 'static + Display + Debug&gt;(&amp;mut self) -&gt; Option&lt;&amp;mut ChainError&lt;T&gt;&gt; {
# self.downcast_mut::&lt;ChainError&lt;T&gt;&gt;()
# }
# }
#
# impl ChainErrorDown for dyn Error + 'static + Send {
# fn is_chain&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; bool {
# self.is::&lt;ChainError&lt;T&gt;&gt;()
# }
#
# fn downcast_chain_ref&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; Option&lt;&amp;ChainError&lt;T&gt;&gt; {
# self.downcast_ref::&lt;ChainError&lt;T&gt;&gt;()
# }
#
# fn downcast_chain_mut&lt;T: 'static + Display + Debug&gt;(&amp;mut self) -&gt; Option&lt;&amp;mut ChainError&lt;T&gt;&gt; {
# self.downcast_mut::&lt;ChainError&lt;T&gt;&gt;()
# }
# }
#
# impl ChainErrorDown for dyn Error + 'static + Send + Sync {
# fn is_chain&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; bool {
# self.is::&lt;ChainError&lt;T&gt;&gt;()
# }
#
# fn downcast_chain_ref&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; Option&lt;&amp;ChainError&lt;T&gt;&gt; {
# self.downcast_ref::&lt;ChainError&lt;T&gt;&gt;()
# }
#
# fn downcast_chain_mut&lt;T: 'static + Display + Debug&gt;(&amp;mut self) -&gt; Option&lt;&amp;mut ChainError&lt;T&gt;&gt; {
# self.downcast_mut::&lt;ChainError&lt;T&gt;&gt;()
# }
# }
#
# impl&lt;T: 'static + Display + Debug&gt; Error for ChainError&lt;T&gt; {
# fn source(&amp;self) -&gt; Option&lt;&amp;(dyn Error + 'static)&gt; {
# if let Some(ref e) = self.error_cause {
# Some(e.as_ref())
# } else {
# None
# }
# }
# }
#
# impl&lt;T: 'static + Display + Debug&gt; Error for &amp;ChainError&lt;T&gt; {
# fn source(&amp;self) -&gt; Option&lt;&amp;(dyn Error + 'static)&gt; {
# if let Some(ref e) = self.error_cause {
# Some(e.as_ref())
# } else {
# None
# }
# }
# }
#
# impl&lt;T: 'static + Display + Debug&gt; Error for &amp;mut ChainError&lt;T&gt; {
# fn source(&amp;self) -&gt; Option&lt;&amp;(dyn Error + 'static)&gt; {
# if let Some(ref e) = self.error_cause {
# Some(e.as_ref())
# } else {
# None
# }
# }
# }
#
# impl&lt;T: 'static + Display + Debug&gt; Display for ChainError&lt;T&gt; {
# fn fmt(&amp;self, f: &amp;mut Formatter) -&gt; Result {
# write!(f, &quot;{}&quot;, self.kind)?;
#
# #[cfg(feature = &quot;display-cause&quot;)]
# {
# if let Some(e) = self.source() {
# writeln!(f, &quot;\nCaused by:&quot;)?;
# Display::fmt(&amp;e, f)?;
# }
# }
# Ok(())
# }
# }
#
# impl&lt;T: 'static + Display + Debug&gt; Debug for ChainError&lt;T&gt; {
# fn fmt(&amp;self, f: &amp;mut Formatter) -&gt; Result {
# #[cfg(not(feature = &quot;no-fileline&quot;))]
# {
# if let Some(o) = self.occurrence {
# write!(f, &quot;{}:{}: &quot;, o.1, o.0)?;
# }
# }
#
# Debug::fmt(&amp;self.kind, f)?;
#
# #[cfg(not(feature = &quot;no-debug-cause&quot;))]
# {
# if let Some(e) = self.source() {
# writeln!(f, &quot;\nCaused by:&quot;)?;
# Debug::fmt(&amp;e, f)?;
# }
# }
# Ok(())
# }
# }
#
# #[macro_export]
# macro_rules! cherr {
# ( $k:expr ) =&gt; {
# ChainError::&lt;_&gt;::new($k, None, Some((line!(), file!())))
# };
# ( $e:expr, $k:expr ) =&gt; {
# ChainError::&lt;_&gt;::new($k, Some(Box::from($e)), Some((line!(), file!())))
# };
# }
#
# #[macro_export]
# macro_rules! mstrerr {
# ( $t:ident, $v:expr $(, $more:expr)* ) =&gt; {
# |e| cherr!(e, $t (format!($v, $( $more , )* )))
# };
# ( $t:path, $v:expr $(, $more:expr)* ) =&gt; {
# |e| cherr!(e, $t (format!($v, $( $more , )* )))
# };
# ( $v:expr $(, $more:expr)* ) =&gt; {
# |e| cherr!(e, format!($v, $( $more , )* ))
# };
# }
#
# #[macro_export]
# macro_rules! derive_str_cherr {
# ($e:ident) =&gt; {
# struct $e(String);
# impl ::std::fmt::Display for $e {
# fn fmt(&amp;self, f: &amp;mut ::std::fmt::Formatter) -&gt; ::std::fmt::Result {
# write!(f, &quot;{}&quot;, self.0)
# }
# }
# impl ::std::fmt::Debug for $e {
# fn fmt(&amp;self, f: &amp;mut ::std::fmt::Formatter) -&gt; ::std::fmt::Result {
# write!(f, &quot;{}({})&quot;, stringify!($e), self.0)
# }
# }
# impl ::std::error::Error for $e {}
# };
# }
#
# #[macro_export]
# macro_rules! try_cherr_ref {
# ( $e:expr, $t:ident ) =&gt; {
# $e.downcast_ref::&lt;ChainError&lt;$t&gt;&gt;()
# };
# ( $e:expr, $t:path ) =&gt; {
# $e.downcast_ref::&lt;ChainError&lt;$t&gt;&gt;()
# };
# }
#
# #[macro_export]
# macro_rules! try_cherr_mut {
# ( $e:expr, $t:ident ) =&gt; {
# $e.downcast_mut::&lt;ChainError&lt;$t&gt;&gt;()
# };
# ( $e:expr, $t:path ) =&gt; {
# $e.downcast_mut::&lt;ChainError&lt;$t&gt;&gt;()
# };
# }
# }
</code></pre></pre>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="prev" href="tutorial3.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a rel="next" href="tutorial5.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
<div style="clear: both"></div>
</nav>
</div>
</div>
<nav class="nav-wide-wrapper" aria-label="Page navigation">
<a href="tutorial3.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a href="tutorial5.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
</nav>
</div>
<script src="ace.js" type="text/javascript" charset="utf-8"></script>
<script src="editor.js" type="text/javascript" charset="utf-8"></script>
<script src="mode-rust.js" type="text/javascript" charset="utf-8"></script>
<script src="theme-dawn.js" type="text/javascript" charset="utf-8"></script>
<script src="theme-tomorrow_night.js" type="text/javascript" charset="utf-8"></script>
<script src="elasticlunr.min.js" type="text/javascript" charset="utf-8"></script>
<script src="mark.min.js" type="text/javascript" charset="utf-8"></script>
<script src="searcher.js" type="text/javascript" charset="utf-8"></script>
<script src="clipboard.min.js" type="text/javascript" charset="utf-8"></script>
<script src="highlight.js" type="text/javascript" charset="utf-8"></script>
<script src="book.js" type="text/javascript" charset="utf-8"></script>
<!-- Custom JS scripts -->
</body>
</html>

521
tutorial5.html Normal file
View file

@ -0,0 +1,521 @@
<!DOCTYPE HTML>
<html lang="en" class="sidebar-visible no-js">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>Chapter 5 - chainerror</title>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#ffffff" />
<link rel="shortcut icon" href="favicon.png">
<link rel="stylesheet" href="css/variables.css">
<link rel="stylesheet" href="css/general.css">
<link rel="stylesheet" href="css/chrome.css">
<link rel="stylesheet" href="css/print.css" media="print">
<!-- Fonts -->
<link rel="stylesheet" href="FontAwesome/css/font-awesome.css">
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800" rel="stylesheet" type="text/css">
<link href="https://fonts.googleapis.com/css?family=Source+Code+Pro:500" rel="stylesheet" type="text/css">
<!-- Highlight.js Stylesheets -->
<link rel="stylesheet" href="highlight.css">
<link rel="stylesheet" href="tomorrow-night.css">
<link rel="stylesheet" href="ayu-highlight.css">
<!-- Custom theme stylesheets -->
</head>
<body class="light">
<!-- Provide site root to javascript -->
<script type="text/javascript">
var path_to_root = "";
var default_theme = "light";
</script>
<!-- Work around some values being stored in localStorage wrapped in quotes -->
<script type="text/javascript">
try {
var theme = localStorage.getItem('mdbook-theme');
var sidebar = localStorage.getItem('mdbook-sidebar');
if (theme.startsWith('"') && theme.endsWith('"')) {
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
}
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
}
} catch (e) { }
</script>
<!-- Set the theme before any content is loaded, prevents flash -->
<script type="text/javascript">
var theme;
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
if (theme === null || theme === undefined) { theme = default_theme; }
document.body.className = theme;
document.querySelector('html').className = theme + ' js';
</script>
<!-- Hide / unhide sidebar before it is displayed -->
<script type="text/javascript">
var html = document.querySelector('html');
var sidebar = 'hidden';
if (document.body.clientWidth >= 1080) {
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
sidebar = sidebar || 'visible';
}
html.classList.remove('sidebar-visible');
html.classList.add("sidebar-" + sidebar);
</script>
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
<ol class="chapter"><li><a href="tutorial1.html"><strong aria-hidden="true">1.</strong> Chapter 1</a></li><li><a href="tutorial2.html"><strong aria-hidden="true">2.</strong> Chapter 2</a></li><li><a href="tutorial3.html"><strong aria-hidden="true">3.</strong> Chapter 3</a></li><li><a href="tutorial4.html"><strong aria-hidden="true">4.</strong> Chapter 4</a></li><li><a href="tutorial5.html" class="active"><strong aria-hidden="true">5.</strong> Chapter 5</a></li><li><a href="tutorial6.html"><strong aria-hidden="true">6.</strong> Chapter 6</a></li><li><a href="tutorial7.html"><strong aria-hidden="true">7.</strong> Chapter 7</a></li><li><a href="tutorial8.html"><strong aria-hidden="true">8.</strong> Chapter 8</a></li><li><a href="tutorial9.html"><strong aria-hidden="true">9.</strong> Chapter 9</a></li><li><a href="tutorial10.html"><strong aria-hidden="true">10.</strong> Chapter 10</a></li><li><a href="tutorial11.html"><strong aria-hidden="true">11.</strong> Chapter 11</a></li></ol>
</nav>
<div id="page-wrapper" class="page-wrapper">
<div class="page">
<div id="menu-bar" class="menu-bar">
<div id="menu-bar-sticky-container">
<div class="left-buttons">
<button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
<i class="fa fa-bars"></i>
</button>
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
<i class="fa fa-paint-brush"></i>
</button>
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
<li role="none"><button role="menuitem" class="theme" id="light">Light (default)</button></li>
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
</ul>
<button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
<i class="fa fa-search"></i>
</button>
</div>
<h1 class="menu-title">chainerror</h1>
<div class="right-buttons">
<a href="print.html" title="Print this book" aria-label="Print this book">
<i id="print-button" class="fa fa-print"></i>
</a>
</div>
</div>
</div>
<div id="search-wrapper" class="hidden">
<form id="searchbar-outer" class="searchbar-outer">
<input type="search" name="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
</form>
<div id="searchresults-outer" class="searchresults-outer hidden">
<div id="searchresults-header" class="searchresults-header"></div>
<ul id="searchresults">
</ul>
</div>
</div>
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
<script type="text/javascript">
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
});
</script>
<div id="content" class="content">
<main>
<pre><pre class="playpen"><code class="language-rust">use crate::chainerror::*;
use std::error::Error;
use std::io;
use std::result::Result;
fn do_some_io() -&gt; Result&lt;(), Box&lt;Error&gt;&gt; {
Err(io::Error::from(io::ErrorKind::NotFound))?;
Ok(())
}
fn func2() -&gt; Result&lt;(), Box&lt;Error&gt;&gt; {
let filename = &quot;foo.txt&quot;;
do_some_io().map_err(mstrerr!(&quot;Error reading '{}'&quot;, filename))?;
Ok(())
}
fn func1() -&gt; Result&lt;(), Box&lt;Error&gt;&gt; {
if let Err(e) = func2() {
if let Some(s) = e.source() {
eprintln!(&quot;func2 failed because of '{}'&quot;, s);
Err(e).map_err(mstrerr!(&quot;func1 error&quot;))?;
}
}
Ok(())
}
fn main() -&gt; Result&lt;(), Box&lt;Error&gt;&gt; {
if let Err(e) = func1() {
eprintln!(&quot;{}&quot;, e);
}
Ok(())
}
# #[allow(dead_code)]
# mod chainerror {
# use std::error::Error;
# use std::fmt::{Debug, Display, Formatter, Result};
# use std::result::Result as StdResult;
#
# pub struct ChainError&lt;T&gt; {
# #[cfg(not(feature = &quot;no-fileline&quot;))]
# occurrence: Option&lt;(u32, &amp;'static str)&gt;,
# kind: T,
# error_cause: Option&lt;Box&lt;dyn Error + 'static&gt;&gt;,
# }
#
# pub type ChainResult&lt;O, E&gt; = StdResult&lt;O, ChainError&lt;E&gt;&gt;;
#
# impl&lt;T: 'static + Display + Debug&gt; ChainError&lt;T&gt; {
# #[cfg(not(feature = &quot;no-fileline&quot;))]
# pub fn new(
# kind: T,
# error_cause: Option&lt;Box&lt;dyn Error + 'static&gt;&gt;,
# occurrence: Option&lt;(u32, &amp;'static str)&gt;,
# ) -&gt; Self {
# Self {
# occurrence,
# kind,
# error_cause,
# }
# }
#
# #[cfg(feature = &quot;no-fileline&quot;)]
# pub fn new(
# kind: T,
# error_cause: Option&lt;Box&lt;dyn Error + 'static&gt;&gt;,
# _occurrence: Option&lt;(u32, &amp;'static str)&gt;,
# ) -&gt; Self {
# Self { kind, error_cause }
# }
#
# pub fn root_cause(&amp;self) -&gt; Option&lt;&amp;(dyn Error + 'static)&gt; {
# let mut cause = self as &amp;(dyn Error + 'static);
# while let Some(c) = cause.source() {
# cause = c;
# }
# Some(cause)
# }
#
# pub fn find_cause&lt;U: Error + 'static&gt;(&amp;self) -&gt; Option&lt;&amp;U&gt; {
# let mut cause = self as &amp;(dyn Error + 'static);
# loop {
# if cause.is::&lt;U&gt;() {
# return cause.downcast_ref::&lt;U&gt;();
# }
#
# match cause.source() {
# Some(c) =&gt; cause = c,
# None =&gt; return None,
# }
# }
# }
#
# pub fn find_chain_cause&lt;U: Error + 'static&gt;(&amp;self) -&gt; Option&lt;&amp;ChainError&lt;U&gt;&gt; {
# let mut cause = self as &amp;(dyn Error + 'static);
# loop {
# if cause.is::&lt;ChainError&lt;U&gt;&gt;() {
# return cause.downcast_ref::&lt;ChainError&lt;U&gt;&gt;();
# }
#
# match cause.source() {
# Some(c) =&gt; cause = c,
# None =&gt; return None,
# }
# }
# }
#
# pub fn kind&lt;'a&gt;(&amp;'a self) -&gt; &amp;'a T {
# &amp;self.kind
# }
# }
#
# pub trait ChainErrorDown {
# fn is_chain&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; bool;
# fn downcast_chain_ref&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; Option&lt;&amp;ChainError&lt;T&gt;&gt;;
# fn downcast_chain_mut&lt;T: 'static + Display + Debug&gt;(&amp;mut self) -&gt; Option&lt;&amp;mut ChainError&lt;T&gt;&gt;;
# }
#
# use std::any::TypeId;
#
# impl&lt;U: 'static + Display + Debug&gt; ChainErrorDown for ChainError&lt;U&gt; {
# fn is_chain&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; bool {
# TypeId::of::&lt;T&gt;() == TypeId::of::&lt;U&gt;()
# }
#
# fn downcast_chain_ref&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; Option&lt;&amp;ChainError&lt;T&gt;&gt; {
# if self.is_chain::&lt;T&gt;() {
# unsafe { Some(&amp;*(self as *const dyn Error as *const &amp;ChainError&lt;T&gt;)) }
# } else {
# None
# }
# }
#
# fn downcast_chain_mut&lt;T: 'static + Display + Debug&gt;(&amp;mut self) -&gt; Option&lt;&amp;mut ChainError&lt;T&gt;&gt; {
# if self.is_chain::&lt;T&gt;() {
# unsafe { Some(&amp;mut *(self as *mut dyn Error as *mut &amp;mut ChainError&lt;T&gt;)) }
# } else {
# None
# }
# }
# }
#
# impl ChainErrorDown for dyn Error + 'static {
# fn is_chain&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; bool {
# self.is::&lt;ChainError&lt;T&gt;&gt;()
# }
#
# fn downcast_chain_ref&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; Option&lt;&amp;ChainError&lt;T&gt;&gt; {
# self.downcast_ref::&lt;ChainError&lt;T&gt;&gt;()
# }
#
# fn downcast_chain_mut&lt;T: 'static + Display + Debug&gt;(&amp;mut self) -&gt; Option&lt;&amp;mut ChainError&lt;T&gt;&gt; {
# self.downcast_mut::&lt;ChainError&lt;T&gt;&gt;()
# }
# }
#
# impl ChainErrorDown for dyn Error + 'static + Send {
# fn is_chain&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; bool {
# self.is::&lt;ChainError&lt;T&gt;&gt;()
# }
#
# fn downcast_chain_ref&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; Option&lt;&amp;ChainError&lt;T&gt;&gt; {
# self.downcast_ref::&lt;ChainError&lt;T&gt;&gt;()
# }
#
# fn downcast_chain_mut&lt;T: 'static + Display + Debug&gt;(&amp;mut self) -&gt; Option&lt;&amp;mut ChainError&lt;T&gt;&gt; {
# self.downcast_mut::&lt;ChainError&lt;T&gt;&gt;()
# }
# }
#
# impl ChainErrorDown for dyn Error + 'static + Send + Sync {
# fn is_chain&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; bool {
# self.is::&lt;ChainError&lt;T&gt;&gt;()
# }
#
# fn downcast_chain_ref&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; Option&lt;&amp;ChainError&lt;T&gt;&gt; {
# self.downcast_ref::&lt;ChainError&lt;T&gt;&gt;()
# }
#
# fn downcast_chain_mut&lt;T: 'static + Display + Debug&gt;(&amp;mut self) -&gt; Option&lt;&amp;mut ChainError&lt;T&gt;&gt; {
# self.downcast_mut::&lt;ChainError&lt;T&gt;&gt;()
# }
# }
#
# impl&lt;T: 'static + Display + Debug&gt; Error for ChainError&lt;T&gt; {
# fn source(&amp;self) -&gt; Option&lt;&amp;(dyn Error + 'static)&gt; {
# if let Some(ref e) = self.error_cause {
# Some(e.as_ref())
# } else {
# None
# }
# }
# }
#
# impl&lt;T: 'static + Display + Debug&gt; Error for &amp;ChainError&lt;T&gt; {
# fn source(&amp;self) -&gt; Option&lt;&amp;(dyn Error + 'static)&gt; {
# if let Some(ref e) = self.error_cause {
# Some(e.as_ref())
# } else {
# None
# }
# }
# }
#
# impl&lt;T: 'static + Display + Debug&gt; Error for &amp;mut ChainError&lt;T&gt; {
# fn source(&amp;self) -&gt; Option&lt;&amp;(dyn Error + 'static)&gt; {
# if let Some(ref e) = self.error_cause {
# Some(e.as_ref())
# } else {
# None
# }
# }
# }
#
# impl&lt;T: 'static + Display + Debug&gt; Display for ChainError&lt;T&gt; {
# fn fmt(&amp;self, f: &amp;mut Formatter) -&gt; Result {
# write!(f, &quot;{}&quot;, self.kind)?;
#
# #[cfg(feature = &quot;display-cause&quot;)]
# {
# if let Some(e) = self.source() {
# writeln!(f, &quot;\nCaused by:&quot;)?;
# Display::fmt(&amp;e, f)?;
# }
# }
# Ok(())
# }
# }
#
# impl&lt;T: 'static + Display + Debug&gt; Debug for ChainError&lt;T&gt; {
# fn fmt(&amp;self, f: &amp;mut Formatter) -&gt; Result {
# #[cfg(not(feature = &quot;no-fileline&quot;))]
# {
# if let Some(o) = self.occurrence {
# write!(f, &quot;{}:{}: &quot;, o.1, o.0)?;
# }
# }
#
# Debug::fmt(&amp;self.kind, f)?;
#
# #[cfg(not(feature = &quot;no-debug-cause&quot;))]
# {
# if let Some(e) = self.source() {
# writeln!(f, &quot;\nCaused by:&quot;)?;
# Debug::fmt(&amp;e, f)?;
# }
# }
# Ok(())
# }
# }
#
# #[macro_export]
# macro_rules! cherr {
# ( $k:expr ) =&gt; {
# ChainError::&lt;_&gt;::new($k, None, Some((line!(), file!())))
# };
# ( $e:expr, $k:expr ) =&gt; {
# ChainError::&lt;_&gt;::new($k, Some(Box::from($e)), Some((line!(), file!())))
# };
# }
#
# #[macro_export]
# macro_rules! mstrerr {
# ( $t:ident, $v:expr $(, $more:expr)* ) =&gt; {
# |e| cherr!(e, $t (format!($v, $( $more , )* )))
# };
# ( $t:path, $v:expr $(, $more:expr)* ) =&gt; {
# |e| cherr!(e, $t (format!($v, $( $more , )* )))
# };
# ( $v:expr $(, $more:expr)* ) =&gt; {
# |e| cherr!(e, format!($v, $( $more , )* ))
# };
# }
#
# #[macro_export]
# macro_rules! derive_str_cherr {
# ($e:ident) =&gt; {
# struct $e(String);
# impl ::std::fmt::Display for $e {
# fn fmt(&amp;self, f: &amp;mut ::std::fmt::Formatter) -&gt; ::std::fmt::Result {
# write!(f, &quot;{}&quot;, self.0)
# }
# }
# impl ::std::fmt::Debug for $e {
# fn fmt(&amp;self, f: &amp;mut ::std::fmt::Formatter) -&gt; ::std::fmt::Result {
# write!(f, &quot;{}({})&quot;, stringify!($e), self.0)
# }
# }
# impl ::std::error::Error for $e {}
# };
# }
#
# #[macro_export]
# macro_rules! try_cherr_ref {
# ( $e:expr, $t:ident ) =&gt; {
# $e.downcast_ref::&lt;ChainError&lt;$t&gt;&gt;()
# };
# ( $e:expr, $t:path ) =&gt; {
# $e.downcast_ref::&lt;ChainError&lt;$t&gt;&gt;()
# };
# }
#
# #[macro_export]
# macro_rules! try_cherr_mut {
# ( $e:expr, $t:ident ) =&gt; {
# $e.downcast_mut::&lt;ChainError&lt;$t&gt;&gt;()
# };
# ( $e:expr, $t:path ) =&gt; {
# $e.downcast_mut::&lt;ChainError&lt;$t&gt;&gt;()
# };
# }
# }
</code></pre></pre>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="prev" href="tutorial4.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a rel="next" href="tutorial6.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
<div style="clear: both"></div>
</nav>
</div>
</div>
<nav class="nav-wide-wrapper" aria-label="Page navigation">
<a href="tutorial4.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a href="tutorial6.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
</nav>
</div>
<script src="ace.js" type="text/javascript" charset="utf-8"></script>
<script src="editor.js" type="text/javascript" charset="utf-8"></script>
<script src="mode-rust.js" type="text/javascript" charset="utf-8"></script>
<script src="theme-dawn.js" type="text/javascript" charset="utf-8"></script>
<script src="theme-tomorrow_night.js" type="text/javascript" charset="utf-8"></script>
<script src="elasticlunr.min.js" type="text/javascript" charset="utf-8"></script>
<script src="mark.min.js" type="text/javascript" charset="utf-8"></script>
<script src="searcher.js" type="text/javascript" charset="utf-8"></script>
<script src="clipboard.min.js" type="text/javascript" charset="utf-8"></script>
<script src="highlight.js" type="text/javascript" charset="utf-8"></script>
<script src="book.js" type="text/javascript" charset="utf-8"></script>
<!-- Custom JS scripts -->
</body>
</html>

529
tutorial6.html Normal file
View file

@ -0,0 +1,529 @@
<!DOCTYPE HTML>
<html lang="en" class="sidebar-visible no-js">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>Chapter 6 - chainerror</title>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#ffffff" />
<link rel="shortcut icon" href="favicon.png">
<link rel="stylesheet" href="css/variables.css">
<link rel="stylesheet" href="css/general.css">
<link rel="stylesheet" href="css/chrome.css">
<link rel="stylesheet" href="css/print.css" media="print">
<!-- Fonts -->
<link rel="stylesheet" href="FontAwesome/css/font-awesome.css">
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800" rel="stylesheet" type="text/css">
<link href="https://fonts.googleapis.com/css?family=Source+Code+Pro:500" rel="stylesheet" type="text/css">
<!-- Highlight.js Stylesheets -->
<link rel="stylesheet" href="highlight.css">
<link rel="stylesheet" href="tomorrow-night.css">
<link rel="stylesheet" href="ayu-highlight.css">
<!-- Custom theme stylesheets -->
</head>
<body class="light">
<!-- Provide site root to javascript -->
<script type="text/javascript">
var path_to_root = "";
var default_theme = "light";
</script>
<!-- Work around some values being stored in localStorage wrapped in quotes -->
<script type="text/javascript">
try {
var theme = localStorage.getItem('mdbook-theme');
var sidebar = localStorage.getItem('mdbook-sidebar');
if (theme.startsWith('"') && theme.endsWith('"')) {
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
}
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
}
} catch (e) { }
</script>
<!-- Set the theme before any content is loaded, prevents flash -->
<script type="text/javascript">
var theme;
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
if (theme === null || theme === undefined) { theme = default_theme; }
document.body.className = theme;
document.querySelector('html').className = theme + ' js';
</script>
<!-- Hide / unhide sidebar before it is displayed -->
<script type="text/javascript">
var html = document.querySelector('html');
var sidebar = 'hidden';
if (document.body.clientWidth >= 1080) {
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
sidebar = sidebar || 'visible';
}
html.classList.remove('sidebar-visible');
html.classList.add("sidebar-" + sidebar);
</script>
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
<ol class="chapter"><li><a href="tutorial1.html"><strong aria-hidden="true">1.</strong> Chapter 1</a></li><li><a href="tutorial2.html"><strong aria-hidden="true">2.</strong> Chapter 2</a></li><li><a href="tutorial3.html"><strong aria-hidden="true">3.</strong> Chapter 3</a></li><li><a href="tutorial4.html"><strong aria-hidden="true">4.</strong> Chapter 4</a></li><li><a href="tutorial5.html"><strong aria-hidden="true">5.</strong> Chapter 5</a></li><li><a href="tutorial6.html" class="active"><strong aria-hidden="true">6.</strong> Chapter 6</a></li><li><a href="tutorial7.html"><strong aria-hidden="true">7.</strong> Chapter 7</a></li><li><a href="tutorial8.html"><strong aria-hidden="true">8.</strong> Chapter 8</a></li><li><a href="tutorial9.html"><strong aria-hidden="true">9.</strong> Chapter 9</a></li><li><a href="tutorial10.html"><strong aria-hidden="true">10.</strong> Chapter 10</a></li><li><a href="tutorial11.html"><strong aria-hidden="true">11.</strong> Chapter 11</a></li></ol>
</nav>
<div id="page-wrapper" class="page-wrapper">
<div class="page">
<div id="menu-bar" class="menu-bar">
<div id="menu-bar-sticky-container">
<div class="left-buttons">
<button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
<i class="fa fa-bars"></i>
</button>
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
<i class="fa fa-paint-brush"></i>
</button>
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
<li role="none"><button role="menuitem" class="theme" id="light">Light (default)</button></li>
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
</ul>
<button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
<i class="fa fa-search"></i>
</button>
</div>
<h1 class="menu-title">chainerror</h1>
<div class="right-buttons">
<a href="print.html" title="Print this book" aria-label="Print this book">
<i id="print-button" class="fa fa-print"></i>
</a>
</div>
</div>
</div>
<div id="search-wrapper" class="hidden">
<form id="searchbar-outer" class="searchbar-outer">
<input type="search" name="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
</form>
<div id="searchresults-outer" class="searchresults-outer hidden">
<div id="searchresults-header" class="searchresults-header"></div>
<ul id="searchresults">
</ul>
</div>
</div>
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
<script type="text/javascript">
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
});
</script>
<div id="content" class="content">
<main>
<pre><pre class="playpen"><code class="language-rust">use crate::chainerror::*;
use std::error::Error;
use std::io;
use std::result::Result;
fn do_some_io() -&gt; Result&lt;(), Box&lt;Error&gt;&gt; {
Err(io::Error::from(io::ErrorKind::NotFound))?;
Ok(())
}
fn func2() -&gt; Result&lt;(), Box&lt;Error&gt;&gt; {
let filename = &quot;foo.txt&quot;;
do_some_io().map_err(mstrerr!(&quot;Error reading '{}'&quot;, filename))?;
Ok(())
}
fn func1() -&gt; Result&lt;(), Box&lt;Error&gt;&gt; {
func2().map_err(mstrerr!(&quot;func1 error&quot;))?;
Ok(())
}
fn main() -&gt; Result&lt;(), Box&lt;Error&gt;&gt; {
if let Err(e) = func1() {
eprintln!(&quot;Error: {}&quot;, e);
let mut s = e.as_ref();
while let Some(c) = s.source() {
if let Some(ioerror) = c.downcast_ref::&lt;io::Error&gt;() {
eprintln!(&quot;caused by: std::io::Error: {}&quot;, ioerror);
match ioerror.kind() {
io::ErrorKind::NotFound =&gt; eprintln!(&quot;of kind: std::io::ErrorKind::NotFound&quot;),
_ =&gt; {}
}
} else {
eprintln!(&quot;caused by: {}&quot;, c);
}
s = c;
}
}
Ok(())
}
# #[allow(dead_code)]
# mod chainerror {
# use std::error::Error;
# use std::fmt::{Debug, Display, Formatter, Result};
# use std::result::Result as StdResult;
#
# pub struct ChainError&lt;T&gt; {
# #[cfg(not(feature = &quot;no-fileline&quot;))]
# occurrence: Option&lt;(u32, &amp;'static str)&gt;,
# kind: T,
# error_cause: Option&lt;Box&lt;dyn Error + 'static&gt;&gt;,
# }
#
# pub type ChainResult&lt;O, E&gt; = StdResult&lt;O, ChainError&lt;E&gt;&gt;;
#
# impl&lt;T: 'static + Display + Debug&gt; ChainError&lt;T&gt; {
# #[cfg(not(feature = &quot;no-fileline&quot;))]
# pub fn new(
# kind: T,
# error_cause: Option&lt;Box&lt;dyn Error + 'static&gt;&gt;,
# occurrence: Option&lt;(u32, &amp;'static str)&gt;,
# ) -&gt; Self {
# Self {
# occurrence,
# kind,
# error_cause,
# }
# }
#
# #[cfg(feature = &quot;no-fileline&quot;)]
# pub fn new(
# kind: T,
# error_cause: Option&lt;Box&lt;dyn Error + 'static&gt;&gt;,
# _occurrence: Option&lt;(u32, &amp;'static str)&gt;,
# ) -&gt; Self {
# Self { kind, error_cause }
# }
#
# pub fn root_cause(&amp;self) -&gt; Option&lt;&amp;(dyn Error + 'static)&gt; {
# let mut cause = self as &amp;(dyn Error + 'static);
# while let Some(c) = cause.source() {
# cause = c;
# }
# Some(cause)
# }
#
# pub fn find_cause&lt;U: Error + 'static&gt;(&amp;self) -&gt; Option&lt;&amp;U&gt; {
# let mut cause = self as &amp;(dyn Error + 'static);
# loop {
# if cause.is::&lt;U&gt;() {
# return cause.downcast_ref::&lt;U&gt;();
# }
#
# match cause.source() {
# Some(c) =&gt; cause = c,
# None =&gt; return None,
# }
# }
# }
#
# pub fn find_chain_cause&lt;U: Error + 'static&gt;(&amp;self) -&gt; Option&lt;&amp;ChainError&lt;U&gt;&gt; {
# let mut cause = self as &amp;(dyn Error + 'static);
# loop {
# if cause.is::&lt;ChainError&lt;U&gt;&gt;() {
# return cause.downcast_ref::&lt;ChainError&lt;U&gt;&gt;();
# }
#
# match cause.source() {
# Some(c) =&gt; cause = c,
# None =&gt; return None,
# }
# }
# }
#
# pub fn kind&lt;'a&gt;(&amp;'a self) -&gt; &amp;'a T {
# &amp;self.kind
# }
# }
#
# pub trait ChainErrorDown {
# fn is_chain&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; bool;
# fn downcast_chain_ref&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; Option&lt;&amp;ChainError&lt;T&gt;&gt;;
# fn downcast_chain_mut&lt;T: 'static + Display + Debug&gt;(&amp;mut self) -&gt; Option&lt;&amp;mut ChainError&lt;T&gt;&gt;;
# }
#
# use std::any::TypeId;
#
# impl&lt;U: 'static + Display + Debug&gt; ChainErrorDown for ChainError&lt;U&gt; {
# fn is_chain&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; bool {
# TypeId::of::&lt;T&gt;() == TypeId::of::&lt;U&gt;()
# }
#
# fn downcast_chain_ref&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; Option&lt;&amp;ChainError&lt;T&gt;&gt; {
# if self.is_chain::&lt;T&gt;() {
# unsafe { Some(&amp;*(self as *const dyn Error as *const &amp;ChainError&lt;T&gt;)) }
# } else {
# None
# }
# }
#
# fn downcast_chain_mut&lt;T: 'static + Display + Debug&gt;(&amp;mut self) -&gt; Option&lt;&amp;mut ChainError&lt;T&gt;&gt; {
# if self.is_chain::&lt;T&gt;() {
# unsafe { Some(&amp;mut *(self as *mut dyn Error as *mut &amp;mut ChainError&lt;T&gt;)) }
# } else {
# None
# }
# }
# }
#
# impl ChainErrorDown for dyn Error + 'static {
# fn is_chain&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; bool {
# self.is::&lt;ChainError&lt;T&gt;&gt;()
# }
#
# fn downcast_chain_ref&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; Option&lt;&amp;ChainError&lt;T&gt;&gt; {
# self.downcast_ref::&lt;ChainError&lt;T&gt;&gt;()
# }
#
# fn downcast_chain_mut&lt;T: 'static + Display + Debug&gt;(&amp;mut self) -&gt; Option&lt;&amp;mut ChainError&lt;T&gt;&gt; {
# self.downcast_mut::&lt;ChainError&lt;T&gt;&gt;()
# }
# }
#
# impl ChainErrorDown for dyn Error + 'static + Send {
# fn is_chain&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; bool {
# self.is::&lt;ChainError&lt;T&gt;&gt;()
# }
#
# fn downcast_chain_ref&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; Option&lt;&amp;ChainError&lt;T&gt;&gt; {
# self.downcast_ref::&lt;ChainError&lt;T&gt;&gt;()
# }
#
# fn downcast_chain_mut&lt;T: 'static + Display + Debug&gt;(&amp;mut self) -&gt; Option&lt;&amp;mut ChainError&lt;T&gt;&gt; {
# self.downcast_mut::&lt;ChainError&lt;T&gt;&gt;()
# }
# }
#
# impl ChainErrorDown for dyn Error + 'static + Send + Sync {
# fn is_chain&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; bool {
# self.is::&lt;ChainError&lt;T&gt;&gt;()
# }
#
# fn downcast_chain_ref&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; Option&lt;&amp;ChainError&lt;T&gt;&gt; {
# self.downcast_ref::&lt;ChainError&lt;T&gt;&gt;()
# }
#
# fn downcast_chain_mut&lt;T: 'static + Display + Debug&gt;(&amp;mut self) -&gt; Option&lt;&amp;mut ChainError&lt;T&gt;&gt; {
# self.downcast_mut::&lt;ChainError&lt;T&gt;&gt;()
# }
# }
#
# impl&lt;T: 'static + Display + Debug&gt; Error for ChainError&lt;T&gt; {
# fn source(&amp;self) -&gt; Option&lt;&amp;(dyn Error + 'static)&gt; {
# if let Some(ref e) = self.error_cause {
# Some(e.as_ref())
# } else {
# None
# }
# }
# }
#
# impl&lt;T: 'static + Display + Debug&gt; Error for &amp;ChainError&lt;T&gt; {
# fn source(&amp;self) -&gt; Option&lt;&amp;(dyn Error + 'static)&gt; {
# if let Some(ref e) = self.error_cause {
# Some(e.as_ref())
# } else {
# None
# }
# }
# }
#
# impl&lt;T: 'static + Display + Debug&gt; Error for &amp;mut ChainError&lt;T&gt; {
# fn source(&amp;self) -&gt; Option&lt;&amp;(dyn Error + 'static)&gt; {
# if let Some(ref e) = self.error_cause {
# Some(e.as_ref())
# } else {
# None
# }
# }
# }
#
# impl&lt;T: 'static + Display + Debug&gt; Display for ChainError&lt;T&gt; {
# fn fmt(&amp;self, f: &amp;mut Formatter) -&gt; Result {
# write!(f, &quot;{}&quot;, self.kind)?;
#
# #[cfg(feature = &quot;display-cause&quot;)]
# {
# if let Some(e) = self.source() {
# writeln!(f, &quot;\nCaused by:&quot;)?;
# Display::fmt(&amp;e, f)?;
# }
# }
# Ok(())
# }
# }
#
# impl&lt;T: 'static + Display + Debug&gt; Debug for ChainError&lt;T&gt; {
# fn fmt(&amp;self, f: &amp;mut Formatter) -&gt; Result {
# #[cfg(not(feature = &quot;no-fileline&quot;))]
# {
# if let Some(o) = self.occurrence {
# write!(f, &quot;{}:{}: &quot;, o.1, o.0)?;
# }
# }
#
# Debug::fmt(&amp;self.kind, f)?;
#
# #[cfg(not(feature = &quot;no-debug-cause&quot;))]
# {
# if let Some(e) = self.source() {
# writeln!(f, &quot;\nCaused by:&quot;)?;
# Debug::fmt(&amp;e, f)?;
# }
# }
# Ok(())
# }
# }
#
# #[macro_export]
# macro_rules! cherr {
# ( $k:expr ) =&gt; {
# ChainError::&lt;_&gt;::new($k, None, Some((line!(), file!())))
# };
# ( $e:expr, $k:expr ) =&gt; {
# ChainError::&lt;_&gt;::new($k, Some(Box::from($e)), Some((line!(), file!())))
# };
# }
#
# #[macro_export]
# macro_rules! mstrerr {
# ( $t:ident, $v:expr $(, $more:expr)* ) =&gt; {
# |e| cherr!(e, $t (format!($v, $( $more , )* )))
# };
# ( $t:path, $v:expr $(, $more:expr)* ) =&gt; {
# |e| cherr!(e, $t (format!($v, $( $more , )* )))
# };
# ( $v:expr $(, $more:expr)* ) =&gt; {
# |e| cherr!(e, format!($v, $( $more , )* ))
# };
# }
#
# #[macro_export]
# macro_rules! derive_str_cherr {
# ($e:ident) =&gt; {
# struct $e(String);
# impl ::std::fmt::Display for $e {
# fn fmt(&amp;self, f: &amp;mut ::std::fmt::Formatter) -&gt; ::std::fmt::Result {
# write!(f, &quot;{}&quot;, self.0)
# }
# }
# impl ::std::fmt::Debug for $e {
# fn fmt(&amp;self, f: &amp;mut ::std::fmt::Formatter) -&gt; ::std::fmt::Result {
# write!(f, &quot;{}({})&quot;, stringify!($e), self.0)
# }
# }
# impl ::std::error::Error for $e {}
# };
# }
#
# #[macro_export]
# macro_rules! try_cherr_ref {
# ( $e:expr, $t:ident ) =&gt; {
# $e.downcast_ref::&lt;ChainError&lt;$t&gt;&gt;()
# };
# ( $e:expr, $t:path ) =&gt; {
# $e.downcast_ref::&lt;ChainError&lt;$t&gt;&gt;()
# };
# }
#
# #[macro_export]
# macro_rules! try_cherr_mut {
# ( $e:expr, $t:ident ) =&gt; {
# $e.downcast_mut::&lt;ChainError&lt;$t&gt;&gt;()
# };
# ( $e:expr, $t:path ) =&gt; {
# $e.downcast_mut::&lt;ChainError&lt;$t&gt;&gt;()
# };
# }
# }
</code></pre></pre>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="prev" href="tutorial5.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a rel="next" href="tutorial7.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
<div style="clear: both"></div>
</nav>
</div>
</div>
<nav class="nav-wide-wrapper" aria-label="Page navigation">
<a href="tutorial5.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a href="tutorial7.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
</nav>
</div>
<script src="ace.js" type="text/javascript" charset="utf-8"></script>
<script src="editor.js" type="text/javascript" charset="utf-8"></script>
<script src="mode-rust.js" type="text/javascript" charset="utf-8"></script>
<script src="theme-dawn.js" type="text/javascript" charset="utf-8"></script>
<script src="theme-tomorrow_night.js" type="text/javascript" charset="utf-8"></script>
<script src="elasticlunr.min.js" type="text/javascript" charset="utf-8"></script>
<script src="mark.min.js" type="text/javascript" charset="utf-8"></script>
<script src="searcher.js" type="text/javascript" charset="utf-8"></script>
<script src="clipboard.min.js" type="text/javascript" charset="utf-8"></script>
<script src="highlight.js" type="text/javascript" charset="utf-8"></script>
<script src="book.js" type="text/javascript" charset="utf-8"></script>
<!-- Custom JS scripts -->
</body>
</html>

530
tutorial7.html Normal file
View file

@ -0,0 +1,530 @@
<!DOCTYPE HTML>
<html lang="en" class="sidebar-visible no-js">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>Chapter 7 - chainerror</title>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#ffffff" />
<link rel="shortcut icon" href="favicon.png">
<link rel="stylesheet" href="css/variables.css">
<link rel="stylesheet" href="css/general.css">
<link rel="stylesheet" href="css/chrome.css">
<link rel="stylesheet" href="css/print.css" media="print">
<!-- Fonts -->
<link rel="stylesheet" href="FontAwesome/css/font-awesome.css">
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800" rel="stylesheet" type="text/css">
<link href="https://fonts.googleapis.com/css?family=Source+Code+Pro:500" rel="stylesheet" type="text/css">
<!-- Highlight.js Stylesheets -->
<link rel="stylesheet" href="highlight.css">
<link rel="stylesheet" href="tomorrow-night.css">
<link rel="stylesheet" href="ayu-highlight.css">
<!-- Custom theme stylesheets -->
</head>
<body class="light">
<!-- Provide site root to javascript -->
<script type="text/javascript">
var path_to_root = "";
var default_theme = "light";
</script>
<!-- Work around some values being stored in localStorage wrapped in quotes -->
<script type="text/javascript">
try {
var theme = localStorage.getItem('mdbook-theme');
var sidebar = localStorage.getItem('mdbook-sidebar');
if (theme.startsWith('"') && theme.endsWith('"')) {
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
}
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
}
} catch (e) { }
</script>
<!-- Set the theme before any content is loaded, prevents flash -->
<script type="text/javascript">
var theme;
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
if (theme === null || theme === undefined) { theme = default_theme; }
document.body.className = theme;
document.querySelector('html').className = theme + ' js';
</script>
<!-- Hide / unhide sidebar before it is displayed -->
<script type="text/javascript">
var html = document.querySelector('html');
var sidebar = 'hidden';
if (document.body.clientWidth >= 1080) {
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
sidebar = sidebar || 'visible';
}
html.classList.remove('sidebar-visible');
html.classList.add("sidebar-" + sidebar);
</script>
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
<ol class="chapter"><li><a href="tutorial1.html"><strong aria-hidden="true">1.</strong> Chapter 1</a></li><li><a href="tutorial2.html"><strong aria-hidden="true">2.</strong> Chapter 2</a></li><li><a href="tutorial3.html"><strong aria-hidden="true">3.</strong> Chapter 3</a></li><li><a href="tutorial4.html"><strong aria-hidden="true">4.</strong> Chapter 4</a></li><li><a href="tutorial5.html"><strong aria-hidden="true">5.</strong> Chapter 5</a></li><li><a href="tutorial6.html"><strong aria-hidden="true">6.</strong> Chapter 6</a></li><li><a href="tutorial7.html" class="active"><strong aria-hidden="true">7.</strong> Chapter 7</a></li><li><a href="tutorial8.html"><strong aria-hidden="true">8.</strong> Chapter 8</a></li><li><a href="tutorial9.html"><strong aria-hidden="true">9.</strong> Chapter 9</a></li><li><a href="tutorial10.html"><strong aria-hidden="true">10.</strong> Chapter 10</a></li><li><a href="tutorial11.html"><strong aria-hidden="true">11.</strong> Chapter 11</a></li></ol>
</nav>
<div id="page-wrapper" class="page-wrapper">
<div class="page">
<div id="menu-bar" class="menu-bar">
<div id="menu-bar-sticky-container">
<div class="left-buttons">
<button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
<i class="fa fa-bars"></i>
</button>
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
<i class="fa fa-paint-brush"></i>
</button>
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
<li role="none"><button role="menuitem" class="theme" id="light">Light (default)</button></li>
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
</ul>
<button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
<i class="fa fa-search"></i>
</button>
</div>
<h1 class="menu-title">chainerror</h1>
<div class="right-buttons">
<a href="print.html" title="Print this book" aria-label="Print this book">
<i id="print-button" class="fa fa-print"></i>
</a>
</div>
</div>
</div>
<div id="search-wrapper" class="hidden">
<form id="searchbar-outer" class="searchbar-outer">
<input type="search" name="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
</form>
<div id="searchresults-outer" class="searchresults-outer hidden">
<div id="searchresults-header" class="searchresults-header"></div>
<ul id="searchresults">
</ul>
</div>
</div>
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
<script type="text/javascript">
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
});
</script>
<div id="content" class="content">
<main>
<pre><pre class="playpen"><code class="language-rust">use crate::chainerror::*;
use std::error::Error;
use std::io;
use std::result::Result;
fn do_some_io() -&gt; Result&lt;(), Box&lt;Error&gt;&gt; {
Err(io::Error::from(io::ErrorKind::NotFound))?;
Ok(())
}
fn func2() -&gt; Result&lt;(), Box&lt;Error&gt;&gt; {
let filename = &quot;foo.txt&quot;;
do_some_io().map_err(mstrerr!(&quot;Error reading '{}'&quot;, filename))?;
Ok(())
}
fn func1() -&gt; Result&lt;(), Box&lt;Error&gt;&gt; {
func2().map_err(mstrerr!(&quot;func1 error&quot;))?;
Ok(())
}
fn main() -&gt; Result&lt;(), Box&lt;Error&gt;&gt; {
if let Err(e) = func1() {
eprintln!(&quot;Error: {}&quot;, e);
if let Some(s) = e.downcast_chain_ref::&lt;String&gt;() {
if let Some(ioerror) = s.find_cause::&lt;io::Error&gt;() {
eprintln!(&quot;caused by: std::io::Error: {}&quot;, ioerror);
match ioerror.kind() {
io::ErrorKind::NotFound =&gt; eprintln!(&quot;of kind: std::io::ErrorKind::NotFound&quot;),
_ =&gt; {}
}
}
if let Some(e) = s.root_cause() {
let ioerror = e.downcast_ref::&lt;io::Error&gt;().unwrap();
eprintln!(&quot;The root cause was: std::io::Error: {:#?}&quot;, ioerror);
}
}
}
Ok(())
}
# #[allow(dead_code)]
# mod chainerror {
# use std::error::Error;
# use std::fmt::{Debug, Display, Formatter, Result};
# use std::result::Result as StdResult;
#
# pub struct ChainError&lt;T&gt; {
# #[cfg(not(feature = &quot;no-fileline&quot;))]
# occurrence: Option&lt;(u32, &amp;'static str)&gt;,
# kind: T,
# error_cause: Option&lt;Box&lt;dyn Error + 'static&gt;&gt;,
# }
#
# pub type ChainResult&lt;O, E&gt; = StdResult&lt;O, ChainError&lt;E&gt;&gt;;
#
# impl&lt;T: 'static + Display + Debug&gt; ChainError&lt;T&gt; {
# #[cfg(not(feature = &quot;no-fileline&quot;))]
# pub fn new(
# kind: T,
# error_cause: Option&lt;Box&lt;dyn Error + 'static&gt;&gt;,
# occurrence: Option&lt;(u32, &amp;'static str)&gt;,
# ) -&gt; Self {
# Self {
# occurrence,
# kind,
# error_cause,
# }
# }
#
# #[cfg(feature = &quot;no-fileline&quot;)]
# pub fn new(
# kind: T,
# error_cause: Option&lt;Box&lt;dyn Error + 'static&gt;&gt;,
# _occurrence: Option&lt;(u32, &amp;'static str)&gt;,
# ) -&gt; Self {
# Self { kind, error_cause }
# }
#
# pub fn root_cause(&amp;self) -&gt; Option&lt;&amp;(dyn Error + 'static)&gt; {
# let mut cause = self as &amp;(dyn Error + 'static);
# while let Some(c) = cause.source() {
# cause = c;
# }
# Some(cause)
# }
#
# pub fn find_cause&lt;U: Error + 'static&gt;(&amp;self) -&gt; Option&lt;&amp;U&gt; {
# let mut cause = self as &amp;(dyn Error + 'static);
# loop {
# if cause.is::&lt;U&gt;() {
# return cause.downcast_ref::&lt;U&gt;();
# }
#
# match cause.source() {
# Some(c) =&gt; cause = c,
# None =&gt; return None,
# }
# }
# }
#
# pub fn find_chain_cause&lt;U: Error + 'static&gt;(&amp;self) -&gt; Option&lt;&amp;ChainError&lt;U&gt;&gt; {
# let mut cause = self as &amp;(dyn Error + 'static);
# loop {
# if cause.is::&lt;ChainError&lt;U&gt;&gt;() {
# return cause.downcast_ref::&lt;ChainError&lt;U&gt;&gt;();
# }
#
# match cause.source() {
# Some(c) =&gt; cause = c,
# None =&gt; return None,
# }
# }
# }
#
# pub fn kind&lt;'a&gt;(&amp;'a self) -&gt; &amp;'a T {
# &amp;self.kind
# }
# }
#
# pub trait ChainErrorDown {
# fn is_chain&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; bool;
# fn downcast_chain_ref&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; Option&lt;&amp;ChainError&lt;T&gt;&gt;;
# fn downcast_chain_mut&lt;T: 'static + Display + Debug&gt;(&amp;mut self) -&gt; Option&lt;&amp;mut ChainError&lt;T&gt;&gt;;
# }
#
# use std::any::TypeId;
#
# impl&lt;U: 'static + Display + Debug&gt; ChainErrorDown for ChainError&lt;U&gt; {
# fn is_chain&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; bool {
# TypeId::of::&lt;T&gt;() == TypeId::of::&lt;U&gt;()
# }
#
# fn downcast_chain_ref&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; Option&lt;&amp;ChainError&lt;T&gt;&gt; {
# if self.is_chain::&lt;T&gt;() {
# unsafe { Some(&amp;*(self as *const dyn Error as *const &amp;ChainError&lt;T&gt;)) }
# } else {
# None
# }
# }
#
# fn downcast_chain_mut&lt;T: 'static + Display + Debug&gt;(&amp;mut self) -&gt; Option&lt;&amp;mut ChainError&lt;T&gt;&gt; {
# if self.is_chain::&lt;T&gt;() {
# unsafe { Some(&amp;mut *(self as *mut dyn Error as *mut &amp;mut ChainError&lt;T&gt;)) }
# } else {
# None
# }
# }
# }
#
# impl ChainErrorDown for dyn Error + 'static {
# fn is_chain&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; bool {
# self.is::&lt;ChainError&lt;T&gt;&gt;()
# }
#
# fn downcast_chain_ref&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; Option&lt;&amp;ChainError&lt;T&gt;&gt; {
# self.downcast_ref::&lt;ChainError&lt;T&gt;&gt;()
# }
#
# fn downcast_chain_mut&lt;T: 'static + Display + Debug&gt;(&amp;mut self) -&gt; Option&lt;&amp;mut ChainError&lt;T&gt;&gt; {
# self.downcast_mut::&lt;ChainError&lt;T&gt;&gt;()
# }
# }
#
# impl ChainErrorDown for dyn Error + 'static + Send {
# fn is_chain&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; bool {
# self.is::&lt;ChainError&lt;T&gt;&gt;()
# }
#
# fn downcast_chain_ref&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; Option&lt;&amp;ChainError&lt;T&gt;&gt; {
# self.downcast_ref::&lt;ChainError&lt;T&gt;&gt;()
# }
#
# fn downcast_chain_mut&lt;T: 'static + Display + Debug&gt;(&amp;mut self) -&gt; Option&lt;&amp;mut ChainError&lt;T&gt;&gt; {
# self.downcast_mut::&lt;ChainError&lt;T&gt;&gt;()
# }
# }
#
# impl ChainErrorDown for dyn Error + 'static + Send + Sync {
# fn is_chain&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; bool {
# self.is::&lt;ChainError&lt;T&gt;&gt;()
# }
#
# fn downcast_chain_ref&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; Option&lt;&amp;ChainError&lt;T&gt;&gt; {
# self.downcast_ref::&lt;ChainError&lt;T&gt;&gt;()
# }
#
# fn downcast_chain_mut&lt;T: 'static + Display + Debug&gt;(&amp;mut self) -&gt; Option&lt;&amp;mut ChainError&lt;T&gt;&gt; {
# self.downcast_mut::&lt;ChainError&lt;T&gt;&gt;()
# }
# }
#
# impl&lt;T: 'static + Display + Debug&gt; Error for ChainError&lt;T&gt; {
# fn source(&amp;self) -&gt; Option&lt;&amp;(dyn Error + 'static)&gt; {
# if let Some(ref e) = self.error_cause {
# Some(e.as_ref())
# } else {
# None
# }
# }
# }
#
# impl&lt;T: 'static + Display + Debug&gt; Error for &amp;ChainError&lt;T&gt; {
# fn source(&amp;self) -&gt; Option&lt;&amp;(dyn Error + 'static)&gt; {
# if let Some(ref e) = self.error_cause {
# Some(e.as_ref())
# } else {
# None
# }
# }
# }
#
# impl&lt;T: 'static + Display + Debug&gt; Error for &amp;mut ChainError&lt;T&gt; {
# fn source(&amp;self) -&gt; Option&lt;&amp;(dyn Error + 'static)&gt; {
# if let Some(ref e) = self.error_cause {
# Some(e.as_ref())
# } else {
# None
# }
# }
# }
#
# impl&lt;T: 'static + Display + Debug&gt; Display for ChainError&lt;T&gt; {
# fn fmt(&amp;self, f: &amp;mut Formatter) -&gt; Result {
# write!(f, &quot;{}&quot;, self.kind)?;
#
# #[cfg(feature = &quot;display-cause&quot;)]
# {
# if let Some(e) = self.source() {
# writeln!(f, &quot;\nCaused by:&quot;)?;
# Display::fmt(&amp;e, f)?;
# }
# }
# Ok(())
# }
# }
#
# impl&lt;T: 'static + Display + Debug&gt; Debug for ChainError&lt;T&gt; {
# fn fmt(&amp;self, f: &amp;mut Formatter) -&gt; Result {
# #[cfg(not(feature = &quot;no-fileline&quot;))]
# {
# if let Some(o) = self.occurrence {
# write!(f, &quot;{}:{}: &quot;, o.1, o.0)?;
# }
# }
#
# Debug::fmt(&amp;self.kind, f)?;
#
# #[cfg(not(feature = &quot;no-debug-cause&quot;))]
# {
# if let Some(e) = self.source() {
# writeln!(f, &quot;\nCaused by:&quot;)?;
# Debug::fmt(&amp;e, f)?;
# }
# }
# Ok(())
# }
# }
#
# #[macro_export]
# macro_rules! cherr {
# ( $k:expr ) =&gt; {
# ChainError::&lt;_&gt;::new($k, None, Some((line!(), file!())))
# };
# ( $e:expr, $k:expr ) =&gt; {
# ChainError::&lt;_&gt;::new($k, Some(Box::from($e)), Some((line!(), file!())))
# };
# }
#
# #[macro_export]
# macro_rules! mstrerr {
# ( $t:ident, $v:expr $(, $more:expr)* ) =&gt; {
# |e| cherr!(e, $t (format!($v, $( $more , )* )))
# };
# ( $t:path, $v:expr $(, $more:expr)* ) =&gt; {
# |e| cherr!(e, $t (format!($v, $( $more , )* )))
# };
# ( $v:expr $(, $more:expr)* ) =&gt; {
# |e| cherr!(e, format!($v, $( $more , )* ))
# };
# }
#
# #[macro_export]
# macro_rules! derive_str_cherr {
# ($e:ident) =&gt; {
# struct $e(String);
# impl ::std::fmt::Display for $e {
# fn fmt(&amp;self, f: &amp;mut ::std::fmt::Formatter) -&gt; ::std::fmt::Result {
# write!(f, &quot;{}&quot;, self.0)
# }
# }
# impl ::std::fmt::Debug for $e {
# fn fmt(&amp;self, f: &amp;mut ::std::fmt::Formatter) -&gt; ::std::fmt::Result {
# write!(f, &quot;{}({})&quot;, stringify!($e), self.0)
# }
# }
# impl ::std::error::Error for $e {}
# };
# }
#
# #[macro_export]
# macro_rules! try_cherr_ref {
# ( $e:expr, $t:ident ) =&gt; {
# $e.downcast_ref::&lt;ChainError&lt;$t&gt;&gt;()
# };
# ( $e:expr, $t:path ) =&gt; {
# $e.downcast_ref::&lt;ChainError&lt;$t&gt;&gt;()
# };
# }
#
# #[macro_export]
# macro_rules! try_cherr_mut {
# ( $e:expr, $t:ident ) =&gt; {
# $e.downcast_mut::&lt;ChainError&lt;$t&gt;&gt;()
# };
# ( $e:expr, $t:path ) =&gt; {
# $e.downcast_mut::&lt;ChainError&lt;$t&gt;&gt;()
# };
# }
# }
</code></pre></pre>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="prev" href="tutorial6.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a rel="next" href="tutorial8.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
<div style="clear: both"></div>
</nav>
</div>
</div>
<nav class="nav-wide-wrapper" aria-label="Page navigation">
<a href="tutorial6.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a href="tutorial8.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
</nav>
</div>
<script src="ace.js" type="text/javascript" charset="utf-8"></script>
<script src="editor.js" type="text/javascript" charset="utf-8"></script>
<script src="mode-rust.js" type="text/javascript" charset="utf-8"></script>
<script src="theme-dawn.js" type="text/javascript" charset="utf-8"></script>
<script src="theme-tomorrow_night.js" type="text/javascript" charset="utf-8"></script>
<script src="elasticlunr.min.js" type="text/javascript" charset="utf-8"></script>
<script src="mark.min.js" type="text/javascript" charset="utf-8"></script>
<script src="searcher.js" type="text/javascript" charset="utf-8"></script>
<script src="clipboard.min.js" type="text/javascript" charset="utf-8"></script>
<script src="highlight.js" type="text/javascript" charset="utf-8"></script>
<script src="book.js" type="text/javascript" charset="utf-8"></script>
<!-- Custom JS scripts -->
</body>
</html>

530
tutorial8.html Normal file
View file

@ -0,0 +1,530 @@
<!DOCTYPE HTML>
<html lang="en" class="sidebar-visible no-js">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>Chapter 8 - chainerror</title>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#ffffff" />
<link rel="shortcut icon" href="favicon.png">
<link rel="stylesheet" href="css/variables.css">
<link rel="stylesheet" href="css/general.css">
<link rel="stylesheet" href="css/chrome.css">
<link rel="stylesheet" href="css/print.css" media="print">
<!-- Fonts -->
<link rel="stylesheet" href="FontAwesome/css/font-awesome.css">
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800" rel="stylesheet" type="text/css">
<link href="https://fonts.googleapis.com/css?family=Source+Code+Pro:500" rel="stylesheet" type="text/css">
<!-- Highlight.js Stylesheets -->
<link rel="stylesheet" href="highlight.css">
<link rel="stylesheet" href="tomorrow-night.css">
<link rel="stylesheet" href="ayu-highlight.css">
<!-- Custom theme stylesheets -->
</head>
<body class="light">
<!-- Provide site root to javascript -->
<script type="text/javascript">
var path_to_root = "";
var default_theme = "light";
</script>
<!-- Work around some values being stored in localStorage wrapped in quotes -->
<script type="text/javascript">
try {
var theme = localStorage.getItem('mdbook-theme');
var sidebar = localStorage.getItem('mdbook-sidebar');
if (theme.startsWith('"') && theme.endsWith('"')) {
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
}
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
}
} catch (e) { }
</script>
<!-- Set the theme before any content is loaded, prevents flash -->
<script type="text/javascript">
var theme;
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
if (theme === null || theme === undefined) { theme = default_theme; }
document.body.className = theme;
document.querySelector('html').className = theme + ' js';
</script>
<!-- Hide / unhide sidebar before it is displayed -->
<script type="text/javascript">
var html = document.querySelector('html');
var sidebar = 'hidden';
if (document.body.clientWidth >= 1080) {
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
sidebar = sidebar || 'visible';
}
html.classList.remove('sidebar-visible');
html.classList.add("sidebar-" + sidebar);
</script>
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
<ol class="chapter"><li><a href="tutorial1.html"><strong aria-hidden="true">1.</strong> Chapter 1</a></li><li><a href="tutorial2.html"><strong aria-hidden="true">2.</strong> Chapter 2</a></li><li><a href="tutorial3.html"><strong aria-hidden="true">3.</strong> Chapter 3</a></li><li><a href="tutorial4.html"><strong aria-hidden="true">4.</strong> Chapter 4</a></li><li><a href="tutorial5.html"><strong aria-hidden="true">5.</strong> Chapter 5</a></li><li><a href="tutorial6.html"><strong aria-hidden="true">6.</strong> Chapter 6</a></li><li><a href="tutorial7.html"><strong aria-hidden="true">7.</strong> Chapter 7</a></li><li><a href="tutorial8.html" class="active"><strong aria-hidden="true">8.</strong> Chapter 8</a></li><li><a href="tutorial9.html"><strong aria-hidden="true">9.</strong> Chapter 9</a></li><li><a href="tutorial10.html"><strong aria-hidden="true">10.</strong> Chapter 10</a></li><li><a href="tutorial11.html"><strong aria-hidden="true">11.</strong> Chapter 11</a></li></ol>
</nav>
<div id="page-wrapper" class="page-wrapper">
<div class="page">
<div id="menu-bar" class="menu-bar">
<div id="menu-bar-sticky-container">
<div class="left-buttons">
<button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
<i class="fa fa-bars"></i>
</button>
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
<i class="fa fa-paint-brush"></i>
</button>
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
<li role="none"><button role="menuitem" class="theme" id="light">Light (default)</button></li>
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
</ul>
<button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
<i class="fa fa-search"></i>
</button>
</div>
<h1 class="menu-title">chainerror</h1>
<div class="right-buttons">
<a href="print.html" title="Print this book" aria-label="Print this book">
<i id="print-button" class="fa fa-print"></i>
</a>
</div>
</div>
</div>
<div id="search-wrapper" class="hidden">
<form id="searchbar-outer" class="searchbar-outer">
<input type="search" name="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
</form>
<div id="searchresults-outer" class="searchresults-outer hidden">
<div id="searchresults-header" class="searchresults-header"></div>
<ul id="searchresults">
</ul>
</div>
</div>
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
<script type="text/javascript">
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
});
</script>
<div id="content" class="content">
<main>
<pre><pre class="playpen"><code class="language-rust">use crate::chainerror::*;
use std::error::Error;
use std::io;
use std::result::Result;
fn do_some_io() -&gt; Result&lt;(), Box&lt;Error&gt;&gt; {
Err(io::Error::from(io::ErrorKind::NotFound))?;
Ok(())
}
derive_str_cherr!(Func2Error);
fn func2() -&gt; Result&lt;(), Box&lt;Error&gt;&gt; {
let filename = &quot;foo.txt&quot;;
do_some_io().map_err(mstrerr!(Func2Error, &quot;Error reading '{}'&quot;, filename))?;
Ok(())
}
derive_str_cherr!(Func1Error);
fn func1() -&gt; Result&lt;(), Box&lt;Error&gt;&gt; {
func2().map_err(mstrerr!(Func1Error, &quot;func1 error&quot;))?;
Ok(())
}
fn main() -&gt; Result&lt;(), Box&lt;Error&gt;&gt; {
if let Err(e) = func1() {
if let Some(f1err) = e.downcast_chain_ref::&lt;Func1Error&gt;() {
eprintln!(&quot;Func1Error: {}&quot;, f1err);
if let Some(f2err) = f1err.find_cause::&lt;ChainError&lt;Func2Error&gt;&gt;() {
eprintln!(&quot;Func2Error: {}&quot;, f2err);
}
if let Some(f2err) = f1err.find_chain_cause::&lt;Func2Error&gt;() {
eprintln!(&quot;Debug Func2Error:\n{:?}&quot;, f2err);
}
}
}
Ok(())
}
# #[allow(dead_code)]
# mod chainerror {
# use std::error::Error;
# use std::fmt::{Debug, Display, Formatter, Result};
# use std::result::Result as StdResult;
#
# pub struct ChainError&lt;T&gt; {
# #[cfg(not(feature = &quot;no-fileline&quot;))]
# occurrence: Option&lt;(u32, &amp;'static str)&gt;,
# kind: T,
# error_cause: Option&lt;Box&lt;dyn Error + 'static&gt;&gt;,
# }
#
# pub type ChainResult&lt;O, E&gt; = StdResult&lt;O, ChainError&lt;E&gt;&gt;;
#
# impl&lt;T: 'static + Display + Debug&gt; ChainError&lt;T&gt; {
# #[cfg(not(feature = &quot;no-fileline&quot;))]
# pub fn new(
# kind: T,
# error_cause: Option&lt;Box&lt;dyn Error + 'static&gt;&gt;,
# occurrence: Option&lt;(u32, &amp;'static str)&gt;,
# ) -&gt; Self {
# Self {
# occurrence,
# kind,
# error_cause,
# }
# }
#
# #[cfg(feature = &quot;no-fileline&quot;)]
# pub fn new(
# kind: T,
# error_cause: Option&lt;Box&lt;dyn Error + 'static&gt;&gt;,
# _occurrence: Option&lt;(u32, &amp;'static str)&gt;,
# ) -&gt; Self {
# Self { kind, error_cause }
# }
#
# pub fn root_cause(&amp;self) -&gt; Option&lt;&amp;(dyn Error + 'static)&gt; {
# let mut cause = self as &amp;(dyn Error + 'static);
# while let Some(c) = cause.source() {
# cause = c;
# }
# Some(cause)
# }
#
# pub fn find_cause&lt;U: Error + 'static&gt;(&amp;self) -&gt; Option&lt;&amp;U&gt; {
# let mut cause = self as &amp;(dyn Error + 'static);
# loop {
# if cause.is::&lt;U&gt;() {
# return cause.downcast_ref::&lt;U&gt;();
# }
#
# match cause.source() {
# Some(c) =&gt; cause = c,
# None =&gt; return None,
# }
# }
# }
#
# pub fn find_chain_cause&lt;U: Error + 'static&gt;(&amp;self) -&gt; Option&lt;&amp;ChainError&lt;U&gt;&gt; {
# let mut cause = self as &amp;(dyn Error + 'static);
# loop {
# if cause.is::&lt;ChainError&lt;U&gt;&gt;() {
# return cause.downcast_ref::&lt;ChainError&lt;U&gt;&gt;();
# }
#
# match cause.source() {
# Some(c) =&gt; cause = c,
# None =&gt; return None,
# }
# }
# }
#
# pub fn kind&lt;'a&gt;(&amp;'a self) -&gt; &amp;'a T {
# &amp;self.kind
# }
# }
#
# pub trait ChainErrorDown {
# fn is_chain&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; bool;
# fn downcast_chain_ref&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; Option&lt;&amp;ChainError&lt;T&gt;&gt;;
# fn downcast_chain_mut&lt;T: 'static + Display + Debug&gt;(&amp;mut self) -&gt; Option&lt;&amp;mut ChainError&lt;T&gt;&gt;;
# }
#
# use std::any::TypeId;
#
# impl&lt;U: 'static + Display + Debug&gt; ChainErrorDown for ChainError&lt;U&gt; {
# fn is_chain&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; bool {
# TypeId::of::&lt;T&gt;() == TypeId::of::&lt;U&gt;()
# }
#
# fn downcast_chain_ref&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; Option&lt;&amp;ChainError&lt;T&gt;&gt; {
# if self.is_chain::&lt;T&gt;() {
# unsafe { Some(&amp;*(self as *const dyn Error as *const &amp;ChainError&lt;T&gt;)) }
# } else {
# None
# }
# }
#
# fn downcast_chain_mut&lt;T: 'static + Display + Debug&gt;(&amp;mut self) -&gt; Option&lt;&amp;mut ChainError&lt;T&gt;&gt; {
# if self.is_chain::&lt;T&gt;() {
# unsafe { Some(&amp;mut *(self as *mut dyn Error as *mut &amp;mut ChainError&lt;T&gt;)) }
# } else {
# None
# }
# }
# }
#
# impl ChainErrorDown for dyn Error + 'static {
# fn is_chain&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; bool {
# self.is::&lt;ChainError&lt;T&gt;&gt;()
# }
#
# fn downcast_chain_ref&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; Option&lt;&amp;ChainError&lt;T&gt;&gt; {
# self.downcast_ref::&lt;ChainError&lt;T&gt;&gt;()
# }
#
# fn downcast_chain_mut&lt;T: 'static + Display + Debug&gt;(&amp;mut self) -&gt; Option&lt;&amp;mut ChainError&lt;T&gt;&gt; {
# self.downcast_mut::&lt;ChainError&lt;T&gt;&gt;()
# }
# }
#
# impl ChainErrorDown for dyn Error + 'static + Send {
# fn is_chain&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; bool {
# self.is::&lt;ChainError&lt;T&gt;&gt;()
# }
#
# fn downcast_chain_ref&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; Option&lt;&amp;ChainError&lt;T&gt;&gt; {
# self.downcast_ref::&lt;ChainError&lt;T&gt;&gt;()
# }
#
# fn downcast_chain_mut&lt;T: 'static + Display + Debug&gt;(&amp;mut self) -&gt; Option&lt;&amp;mut ChainError&lt;T&gt;&gt; {
# self.downcast_mut::&lt;ChainError&lt;T&gt;&gt;()
# }
# }
#
# impl ChainErrorDown for dyn Error + 'static + Send + Sync {
# fn is_chain&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; bool {
# self.is::&lt;ChainError&lt;T&gt;&gt;()
# }
#
# fn downcast_chain_ref&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; Option&lt;&amp;ChainError&lt;T&gt;&gt; {
# self.downcast_ref::&lt;ChainError&lt;T&gt;&gt;()
# }
#
# fn downcast_chain_mut&lt;T: 'static + Display + Debug&gt;(&amp;mut self) -&gt; Option&lt;&amp;mut ChainError&lt;T&gt;&gt; {
# self.downcast_mut::&lt;ChainError&lt;T&gt;&gt;()
# }
# }
#
# impl&lt;T: 'static + Display + Debug&gt; Error for ChainError&lt;T&gt; {
# fn source(&amp;self) -&gt; Option&lt;&amp;(dyn Error + 'static)&gt; {
# if let Some(ref e) = self.error_cause {
# Some(e.as_ref())
# } else {
# None
# }
# }
# }
#
# impl&lt;T: 'static + Display + Debug&gt; Error for &amp;ChainError&lt;T&gt; {
# fn source(&amp;self) -&gt; Option&lt;&amp;(dyn Error + 'static)&gt; {
# if let Some(ref e) = self.error_cause {
# Some(e.as_ref())
# } else {
# None
# }
# }
# }
#
# impl&lt;T: 'static + Display + Debug&gt; Error for &amp;mut ChainError&lt;T&gt; {
# fn source(&amp;self) -&gt; Option&lt;&amp;(dyn Error + 'static)&gt; {
# if let Some(ref e) = self.error_cause {
# Some(e.as_ref())
# } else {
# None
# }
# }
# }
#
# impl&lt;T: 'static + Display + Debug&gt; Display for ChainError&lt;T&gt; {
# fn fmt(&amp;self, f: &amp;mut Formatter) -&gt; Result {
# write!(f, &quot;{}&quot;, self.kind)?;
#
# #[cfg(feature = &quot;display-cause&quot;)]
# {
# if let Some(e) = self.source() {
# writeln!(f, &quot;\nCaused by:&quot;)?;
# Display::fmt(&amp;e, f)?;
# }
# }
# Ok(())
# }
# }
#
# impl&lt;T: 'static + Display + Debug&gt; Debug for ChainError&lt;T&gt; {
# fn fmt(&amp;self, f: &amp;mut Formatter) -&gt; Result {
# #[cfg(not(feature = &quot;no-fileline&quot;))]
# {
# if let Some(o) = self.occurrence {
# write!(f, &quot;{}:{}: &quot;, o.1, o.0)?;
# }
# }
#
# Debug::fmt(&amp;self.kind, f)?;
#
# #[cfg(not(feature = &quot;no-debug-cause&quot;))]
# {
# if let Some(e) = self.source() {
# writeln!(f, &quot;\nCaused by:&quot;)?;
# Debug::fmt(&amp;e, f)?;
# }
# }
# Ok(())
# }
# }
#
# #[macro_export]
# macro_rules! cherr {
# ( $k:expr ) =&gt; {
# ChainError::&lt;_&gt;::new($k, None, Some((line!(), file!())))
# };
# ( $e:expr, $k:expr ) =&gt; {
# ChainError::&lt;_&gt;::new($k, Some(Box::from($e)), Some((line!(), file!())))
# };
# }
#
# #[macro_export]
# macro_rules! mstrerr {
# ( $t:ident, $v:expr $(, $more:expr)* ) =&gt; {
# |e| cherr!(e, $t (format!($v, $( $more , )* )))
# };
# ( $t:path, $v:expr $(, $more:expr)* ) =&gt; {
# |e| cherr!(e, $t (format!($v, $( $more , )* )))
# };
# ( $v:expr $(, $more:expr)* ) =&gt; {
# |e| cherr!(e, format!($v, $( $more , )* ))
# };
# }
#
# #[macro_export]
# macro_rules! derive_str_cherr {
# ($e:ident) =&gt; {
# struct $e(String);
# impl ::std::fmt::Display for $e {
# fn fmt(&amp;self, f: &amp;mut ::std::fmt::Formatter) -&gt; ::std::fmt::Result {
# write!(f, &quot;{}&quot;, self.0)
# }
# }
# impl ::std::fmt::Debug for $e {
# fn fmt(&amp;self, f: &amp;mut ::std::fmt::Formatter) -&gt; ::std::fmt::Result {
# write!(f, &quot;{}({})&quot;, stringify!($e), self.0)
# }
# }
# impl ::std::error::Error for $e {}
# };
# }
#
# #[macro_export]
# macro_rules! try_cherr_ref {
# ( $e:expr, $t:ident ) =&gt; {
# $e.downcast_ref::&lt;ChainError&lt;$t&gt;&gt;()
# };
# ( $e:expr, $t:path ) =&gt; {
# $e.downcast_ref::&lt;ChainError&lt;$t&gt;&gt;()
# };
# }
#
# #[macro_export]
# macro_rules! try_cherr_mut {
# ( $e:expr, $t:ident ) =&gt; {
# $e.downcast_mut::&lt;ChainError&lt;$t&gt;&gt;()
# };
# ( $e:expr, $t:path ) =&gt; {
# $e.downcast_mut::&lt;ChainError&lt;$t&gt;&gt;()
# };
# }
# }
</code></pre></pre>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="prev" href="tutorial7.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a rel="next" href="tutorial9.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
<div style="clear: both"></div>
</nav>
</div>
</div>
<nav class="nav-wide-wrapper" aria-label="Page navigation">
<a href="tutorial7.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a href="tutorial9.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
</nav>
</div>
<script src="ace.js" type="text/javascript" charset="utf-8"></script>
<script src="editor.js" type="text/javascript" charset="utf-8"></script>
<script src="mode-rust.js" type="text/javascript" charset="utf-8"></script>
<script src="theme-dawn.js" type="text/javascript" charset="utf-8"></script>
<script src="theme-tomorrow_night.js" type="text/javascript" charset="utf-8"></script>
<script src="elasticlunr.min.js" type="text/javascript" charset="utf-8"></script>
<script src="mark.min.js" type="text/javascript" charset="utf-8"></script>
<script src="searcher.js" type="text/javascript" charset="utf-8"></script>
<script src="clipboard.min.js" type="text/javascript" charset="utf-8"></script>
<script src="highlight.js" type="text/javascript" charset="utf-8"></script>
<script src="book.js" type="text/javascript" charset="utf-8"></script>
<!-- Custom JS scripts -->
</body>
</html>

529
tutorial9.html Normal file
View file

@ -0,0 +1,529 @@
<!DOCTYPE HTML>
<html lang="en" class="sidebar-visible no-js">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>Chapter 9 - chainerror</title>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#ffffff" />
<link rel="shortcut icon" href="favicon.png">
<link rel="stylesheet" href="css/variables.css">
<link rel="stylesheet" href="css/general.css">
<link rel="stylesheet" href="css/chrome.css">
<link rel="stylesheet" href="css/print.css" media="print">
<!-- Fonts -->
<link rel="stylesheet" href="FontAwesome/css/font-awesome.css">
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800" rel="stylesheet" type="text/css">
<link href="https://fonts.googleapis.com/css?family=Source+Code+Pro:500" rel="stylesheet" type="text/css">
<!-- Highlight.js Stylesheets -->
<link rel="stylesheet" href="highlight.css">
<link rel="stylesheet" href="tomorrow-night.css">
<link rel="stylesheet" href="ayu-highlight.css">
<!-- Custom theme stylesheets -->
</head>
<body class="light">
<!-- Provide site root to javascript -->
<script type="text/javascript">
var path_to_root = "";
var default_theme = "light";
</script>
<!-- Work around some values being stored in localStorage wrapped in quotes -->
<script type="text/javascript">
try {
var theme = localStorage.getItem('mdbook-theme');
var sidebar = localStorage.getItem('mdbook-sidebar');
if (theme.startsWith('"') && theme.endsWith('"')) {
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
}
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
}
} catch (e) { }
</script>
<!-- Set the theme before any content is loaded, prevents flash -->
<script type="text/javascript">
var theme;
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
if (theme === null || theme === undefined) { theme = default_theme; }
document.body.className = theme;
document.querySelector('html').className = theme + ' js';
</script>
<!-- Hide / unhide sidebar before it is displayed -->
<script type="text/javascript">
var html = document.querySelector('html');
var sidebar = 'hidden';
if (document.body.clientWidth >= 1080) {
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
sidebar = sidebar || 'visible';
}
html.classList.remove('sidebar-visible');
html.classList.add("sidebar-" + sidebar);
</script>
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
<ol class="chapter"><li><a href="tutorial1.html"><strong aria-hidden="true">1.</strong> Chapter 1</a></li><li><a href="tutorial2.html"><strong aria-hidden="true">2.</strong> Chapter 2</a></li><li><a href="tutorial3.html"><strong aria-hidden="true">3.</strong> Chapter 3</a></li><li><a href="tutorial4.html"><strong aria-hidden="true">4.</strong> Chapter 4</a></li><li><a href="tutorial5.html"><strong aria-hidden="true">5.</strong> Chapter 5</a></li><li><a href="tutorial6.html"><strong aria-hidden="true">6.</strong> Chapter 6</a></li><li><a href="tutorial7.html"><strong aria-hidden="true">7.</strong> Chapter 7</a></li><li><a href="tutorial8.html"><strong aria-hidden="true">8.</strong> Chapter 8</a></li><li><a href="tutorial9.html" class="active"><strong aria-hidden="true">9.</strong> Chapter 9</a></li><li><a href="tutorial10.html"><strong aria-hidden="true">10.</strong> Chapter 10</a></li><li><a href="tutorial11.html"><strong aria-hidden="true">11.</strong> Chapter 11</a></li></ol>
</nav>
<div id="page-wrapper" class="page-wrapper">
<div class="page">
<div id="menu-bar" class="menu-bar">
<div id="menu-bar-sticky-container">
<div class="left-buttons">
<button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
<i class="fa fa-bars"></i>
</button>
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
<i class="fa fa-paint-brush"></i>
</button>
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
<li role="none"><button role="menuitem" class="theme" id="light">Light (default)</button></li>
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
</ul>
<button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
<i class="fa fa-search"></i>
</button>
</div>
<h1 class="menu-title">chainerror</h1>
<div class="right-buttons">
<a href="print.html" title="Print this book" aria-label="Print this book">
<i id="print-button" class="fa fa-print"></i>
</a>
</div>
</div>
</div>
<div id="search-wrapper" class="hidden">
<form id="searchbar-outer" class="searchbar-outer">
<input type="search" name="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
</form>
<div id="searchresults-outer" class="searchresults-outer hidden">
<div id="searchresults-header" class="searchresults-header"></div>
<ul id="searchresults">
</ul>
</div>
</div>
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
<script type="text/javascript">
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
});
</script>
<div id="content" class="content">
<main>
<pre><pre class="playpen"><code class="language-rust">use crate::chainerror::*;
use std::error::Error;
use std::io;
use std::result::Result;
fn do_some_io() -&gt; Result&lt;(), Box&lt;Error&gt;&gt; {
Err(io::Error::from(io::ErrorKind::NotFound))?;
Ok(())
}
derive_str_cherr!(Func2Error);
fn func2() -&gt; Result&lt;(), Box&lt;Error&gt;&gt; {
let filename = &quot;foo.txt&quot;;
do_some_io().map_err(mstrerr!(Func2Error, &quot;Error reading '{}'&quot;, filename))?;
Ok(())
}
derive_str_cherr!(Func1ErrorFunc2);
derive_str_cherr!(Func1ErrorIO);
fn func1() -&gt; Result&lt;(), Box&lt;Error&gt;&gt; {
func2().map_err(mstrerr!(Func1ErrorFunc2, &quot;func1 error calling func2&quot;))?;
let filename = &quot;bar.txt&quot;;
do_some_io().map_err(mstrerr!(Func1ErrorIO, &quot;Error reading '{}'&quot;, filename))?;
Ok(())
}
fn main() -&gt; Result&lt;(), Box&lt;Error&gt;&gt; {
if let Err(e) = func1() {
if let Some(s) = e.downcast_ref::&lt;ChainError&lt;Func1ErrorIO&gt;&gt;() {
eprintln!(&quot;Func1ErrorIO:\n{:?}&quot;, s);
}
if let Some(s) = try_cherr_ref!(e, Func1ErrorFunc2) {
eprintln!(&quot;Func1ErrorFunc2:\n{:?}&quot;, s);
}
}
Ok(())
}
# #[allow(dead_code)]
# mod chainerror {
# use std::error::Error;
# use std::fmt::{Debug, Display, Formatter, Result};
# use std::result::Result as StdResult;
#
# pub struct ChainError&lt;T&gt; {
# #[cfg(not(feature = &quot;no-fileline&quot;))]
# occurrence: Option&lt;(u32, &amp;'static str)&gt;,
# kind: T,
# error_cause: Option&lt;Box&lt;dyn Error + 'static&gt;&gt;,
# }
#
# pub type ChainResult&lt;O, E&gt; = StdResult&lt;O, ChainError&lt;E&gt;&gt;;
#
# impl&lt;T: 'static + Display + Debug&gt; ChainError&lt;T&gt; {
# #[cfg(not(feature = &quot;no-fileline&quot;))]
# pub fn new(
# kind: T,
# error_cause: Option&lt;Box&lt;dyn Error + 'static&gt;&gt;,
# occurrence: Option&lt;(u32, &amp;'static str)&gt;,
# ) -&gt; Self {
# Self {
# occurrence,
# kind,
# error_cause,
# }
# }
#
# #[cfg(feature = &quot;no-fileline&quot;)]
# pub fn new(
# kind: T,
# error_cause: Option&lt;Box&lt;dyn Error + 'static&gt;&gt;,
# _occurrence: Option&lt;(u32, &amp;'static str)&gt;,
# ) -&gt; Self {
# Self { kind, error_cause }
# }
#
# pub fn root_cause(&amp;self) -&gt; Option&lt;&amp;(dyn Error + 'static)&gt; {
# let mut cause = self as &amp;(dyn Error + 'static);
# while let Some(c) = cause.source() {
# cause = c;
# }
# Some(cause)
# }
#
# pub fn find_cause&lt;U: Error + 'static&gt;(&amp;self) -&gt; Option&lt;&amp;U&gt; {
# let mut cause = self as &amp;(dyn Error + 'static);
# loop {
# if cause.is::&lt;U&gt;() {
# return cause.downcast_ref::&lt;U&gt;();
# }
#
# match cause.source() {
# Some(c) =&gt; cause = c,
# None =&gt; return None,
# }
# }
# }
#
# pub fn find_chain_cause&lt;U: Error + 'static&gt;(&amp;self) -&gt; Option&lt;&amp;ChainError&lt;U&gt;&gt; {
# let mut cause = self as &amp;(dyn Error + 'static);
# loop {
# if cause.is::&lt;ChainError&lt;U&gt;&gt;() {
# return cause.downcast_ref::&lt;ChainError&lt;U&gt;&gt;();
# }
#
# match cause.source() {
# Some(c) =&gt; cause = c,
# None =&gt; return None,
# }
# }
# }
#
# pub fn kind&lt;'a&gt;(&amp;'a self) -&gt; &amp;'a T {
# &amp;self.kind
# }
# }
#
# pub trait ChainErrorDown {
# fn is_chain&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; bool;
# fn downcast_chain_ref&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; Option&lt;&amp;ChainError&lt;T&gt;&gt;;
# fn downcast_chain_mut&lt;T: 'static + Display + Debug&gt;(&amp;mut self) -&gt; Option&lt;&amp;mut ChainError&lt;T&gt;&gt;;
# }
#
# use std::any::TypeId;
#
# impl&lt;U: 'static + Display + Debug&gt; ChainErrorDown for ChainError&lt;U&gt; {
# fn is_chain&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; bool {
# TypeId::of::&lt;T&gt;() == TypeId::of::&lt;U&gt;()
# }
#
# fn downcast_chain_ref&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; Option&lt;&amp;ChainError&lt;T&gt;&gt; {
# if self.is_chain::&lt;T&gt;() {
# unsafe { Some(&amp;*(self as *const dyn Error as *const &amp;ChainError&lt;T&gt;)) }
# } else {
# None
# }
# }
#
# fn downcast_chain_mut&lt;T: 'static + Display + Debug&gt;(&amp;mut self) -&gt; Option&lt;&amp;mut ChainError&lt;T&gt;&gt; {
# if self.is_chain::&lt;T&gt;() {
# unsafe { Some(&amp;mut *(self as *mut dyn Error as *mut &amp;mut ChainError&lt;T&gt;)) }
# } else {
# None
# }
# }
# }
#
# impl ChainErrorDown for dyn Error + 'static {
# fn is_chain&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; bool {
# self.is::&lt;ChainError&lt;T&gt;&gt;()
# }
#
# fn downcast_chain_ref&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; Option&lt;&amp;ChainError&lt;T&gt;&gt; {
# self.downcast_ref::&lt;ChainError&lt;T&gt;&gt;()
# }
#
# fn downcast_chain_mut&lt;T: 'static + Display + Debug&gt;(&amp;mut self) -&gt; Option&lt;&amp;mut ChainError&lt;T&gt;&gt; {
# self.downcast_mut::&lt;ChainError&lt;T&gt;&gt;()
# }
# }
#
# impl ChainErrorDown for dyn Error + 'static + Send {
# fn is_chain&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; bool {
# self.is::&lt;ChainError&lt;T&gt;&gt;()
# }
#
# fn downcast_chain_ref&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; Option&lt;&amp;ChainError&lt;T&gt;&gt; {
# self.downcast_ref::&lt;ChainError&lt;T&gt;&gt;()
# }
#
# fn downcast_chain_mut&lt;T: 'static + Display + Debug&gt;(&amp;mut self) -&gt; Option&lt;&amp;mut ChainError&lt;T&gt;&gt; {
# self.downcast_mut::&lt;ChainError&lt;T&gt;&gt;()
# }
# }
#
# impl ChainErrorDown for dyn Error + 'static + Send + Sync {
# fn is_chain&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; bool {
# self.is::&lt;ChainError&lt;T&gt;&gt;()
# }
#
# fn downcast_chain_ref&lt;T: 'static + Display + Debug&gt;(&amp;self) -&gt; Option&lt;&amp;ChainError&lt;T&gt;&gt; {
# self.downcast_ref::&lt;ChainError&lt;T&gt;&gt;()
# }
#
# fn downcast_chain_mut&lt;T: 'static + Display + Debug&gt;(&amp;mut self) -&gt; Option&lt;&amp;mut ChainError&lt;T&gt;&gt; {
# self.downcast_mut::&lt;ChainError&lt;T&gt;&gt;()
# }
# }
#
# impl&lt;T: 'static + Display + Debug&gt; Error for ChainError&lt;T&gt; {
# fn source(&amp;self) -&gt; Option&lt;&amp;(dyn Error + 'static)&gt; {
# if let Some(ref e) = self.error_cause {
# Some(e.as_ref())
# } else {
# None
# }
# }
# }
#
# impl&lt;T: 'static + Display + Debug&gt; Error for &amp;ChainError&lt;T&gt; {
# fn source(&amp;self) -&gt; Option&lt;&amp;(dyn Error + 'static)&gt; {
# if let Some(ref e) = self.error_cause {
# Some(e.as_ref())
# } else {
# None
# }
# }
# }
#
# impl&lt;T: 'static + Display + Debug&gt; Error for &amp;mut ChainError&lt;T&gt; {
# fn source(&amp;self) -&gt; Option&lt;&amp;(dyn Error + 'static)&gt; {
# if let Some(ref e) = self.error_cause {
# Some(e.as_ref())
# } else {
# None
# }
# }
# }
#
# impl&lt;T: 'static + Display + Debug&gt; Display for ChainError&lt;T&gt; {
# fn fmt(&amp;self, f: &amp;mut Formatter) -&gt; Result {
# write!(f, &quot;{}&quot;, self.kind)?;
#
# #[cfg(feature = &quot;display-cause&quot;)]
# {
# if let Some(e) = self.source() {
# writeln!(f, &quot;\nCaused by:&quot;)?;
# Display::fmt(&amp;e, f)?;
# }
# }
# Ok(())
# }
# }
#
# impl&lt;T: 'static + Display + Debug&gt; Debug for ChainError&lt;T&gt; {
# fn fmt(&amp;self, f: &amp;mut Formatter) -&gt; Result {
# #[cfg(not(feature = &quot;no-fileline&quot;))]
# {
# if let Some(o) = self.occurrence {
# write!(f, &quot;{}:{}: &quot;, o.1, o.0)?;
# }
# }
#
# Debug::fmt(&amp;self.kind, f)?;
#
# #[cfg(not(feature = &quot;no-debug-cause&quot;))]
# {
# if let Some(e) = self.source() {
# writeln!(f, &quot;\nCaused by:&quot;)?;
# Debug::fmt(&amp;e, f)?;
# }
# }
# Ok(())
# }
# }
#
# #[macro_export]
# macro_rules! cherr {
# ( $k:expr ) =&gt; {
# ChainError::&lt;_&gt;::new($k, None, Some((line!(), file!())))
# };
# ( $e:expr, $k:expr ) =&gt; {
# ChainError::&lt;_&gt;::new($k, Some(Box::from($e)), Some((line!(), file!())))
# };
# }
#
# #[macro_export]
# macro_rules! mstrerr {
# ( $t:ident, $v:expr $(, $more:expr)* ) =&gt; {
# |e| cherr!(e, $t (format!($v, $( $more , )* )))
# };
# ( $t:path, $v:expr $(, $more:expr)* ) =&gt; {
# |e| cherr!(e, $t (format!($v, $( $more , )* )))
# };
# ( $v:expr $(, $more:expr)* ) =&gt; {
# |e| cherr!(e, format!($v, $( $more , )* ))
# };
# }
#
# #[macro_export]
# macro_rules! derive_str_cherr {
# ($e:ident) =&gt; {
# struct $e(String);
# impl ::std::fmt::Display for $e {
# fn fmt(&amp;self, f: &amp;mut ::std::fmt::Formatter) -&gt; ::std::fmt::Result {
# write!(f, &quot;{}&quot;, self.0)
# }
# }
# impl ::std::fmt::Debug for $e {
# fn fmt(&amp;self, f: &amp;mut ::std::fmt::Formatter) -&gt; ::std::fmt::Result {
# write!(f, &quot;{}({})&quot;, stringify!($e), self.0)
# }
# }
# impl ::std::error::Error for $e {}
# };
# }
#
# #[macro_export]
# macro_rules! try_cherr_ref {
# ( $e:expr, $t:ident ) =&gt; {
# $e.downcast_ref::&lt;ChainError&lt;$t&gt;&gt;()
# };
# ( $e:expr, $t:path ) =&gt; {
# $e.downcast_ref::&lt;ChainError&lt;$t&gt;&gt;()
# };
# }
#
# #[macro_export]
# macro_rules! try_cherr_mut {
# ( $e:expr, $t:ident ) =&gt; {
# $e.downcast_mut::&lt;ChainError&lt;$t&gt;&gt;()
# };
# ( $e:expr, $t:path ) =&gt; {
# $e.downcast_mut::&lt;ChainError&lt;$t&gt;&gt;()
# };
# }
# }
</code></pre></pre>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="prev" href="tutorial8.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a rel="next" href="tutorial10.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
<div style="clear: both"></div>
</nav>
</div>
</div>
<nav class="nav-wide-wrapper" aria-label="Page navigation">
<a href="tutorial8.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a href="tutorial10.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
</nav>
</div>
<script src="ace.js" type="text/javascript" charset="utf-8"></script>
<script src="editor.js" type="text/javascript" charset="utf-8"></script>
<script src="mode-rust.js" type="text/javascript" charset="utf-8"></script>
<script src="theme-dawn.js" type="text/javascript" charset="utf-8"></script>
<script src="theme-tomorrow_night.js" type="text/javascript" charset="utf-8"></script>
<script src="elasticlunr.min.js" type="text/javascript" charset="utf-8"></script>
<script src="mark.min.js" type="text/javascript" charset="utf-8"></script>
<script src="searcher.js" type="text/javascript" charset="utf-8"></script>
<script src="clipboard.min.js" type="text/javascript" charset="utf-8"></script>
<script src="highlight.js" type="text/javascript" charset="utf-8"></script>
<script src="book.js" type="text/javascript" charset="utf-8"></script>
<!-- Custom JS scripts -->
</body>
</html>