rust-cookbook/print.html

6513 lines
487 KiB
HTML

<!DOCTYPE HTML>
<html lang="en" class="sidebar-visible no-js light">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>Rust Cookbook</title>
<meta name="robots" content="noindex" />
<!-- Custom HTML head -->
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<meta name="description" content="Collection of useful Rust code examples">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#ffffff" />
<link rel="icon" href="favicon.svg">
<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 rel="stylesheet" href="fonts/fonts.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 -->
<link rel="stylesheet" href="theme/custom.css">
</head>
<body>
<!-- Provide site root to javascript -->
<script type="text/javascript">
var path_to_root = "";
var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "navy" : "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; }
var html = document.querySelector('html');
html.classList.remove('no-js')
html.classList.remove('light')
html.classList.add(theme);
html.classList.add('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">
<div class="sidebar-scrollbox">
<ol class="chapter"><li class="chapter-item expanded affix "><a href="intro.html">Table of Contents</a></li><li class="chapter-item expanded affix "><a href="about.html">About</a></li><li class="chapter-item expanded "><a href="algorithms.html"><strong aria-hidden="true">1.</strong> Algorithms</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="algorithms/randomness.html"><strong aria-hidden="true">1.1.</strong> Generate Random Values</a></li><li class="chapter-item expanded "><a href="algorithms/sorting.html"><strong aria-hidden="true">1.2.</strong> Sort a Vector</a></li></ol></li><li class="chapter-item expanded "><a href="cli.html"><strong aria-hidden="true">2.</strong> Command Line</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="cli/arguments.html"><strong aria-hidden="true">2.1.</strong> Argument Parsing</a></li><li class="chapter-item expanded "><a href="cli/ansi_terminal.html"><strong aria-hidden="true">2.2.</strong> ANSI Terminal</a></li></ol></li><li class="chapter-item expanded "><a href="compression.html"><strong aria-hidden="true">3.</strong> Compression</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="compression/tar.html"><strong aria-hidden="true">3.1.</strong> Working with Tarballs</a></li></ol></li><li class="chapter-item expanded "><a href="concurrency.html"><strong aria-hidden="true">4.</strong> Concurrency</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="concurrency/threads.html"><strong aria-hidden="true">4.1.</strong> Explicit Threads</a></li><li class="chapter-item expanded "><a href="concurrency/parallel.html"><strong aria-hidden="true">4.2.</strong> Data Parallelism</a></li></ol></li><li class="chapter-item expanded "><a href="cryptography.html"><strong aria-hidden="true">5.</strong> Cryptography</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="cryptography/hashing.html"><strong aria-hidden="true">5.1.</strong> Hashing</a></li><li class="chapter-item expanded "><a href="cryptography/encryption.html"><strong aria-hidden="true">5.2.</strong> Encryption</a></li></ol></li><li class="chapter-item expanded "><a href="data_structures.html"><strong aria-hidden="true">6.</strong> Data Structures</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="data_structures/bitfield.html"><strong aria-hidden="true">6.1.</strong> Bitfield</a></li></ol></li><li class="chapter-item expanded "><a href="database.html"><strong aria-hidden="true">7.</strong> Database</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="database/sqlite.html"><strong aria-hidden="true">7.1.</strong> SQLite</a></li><li class="chapter-item expanded "><a href="database/postgres.html"><strong aria-hidden="true">7.2.</strong> Postgres</a></li></ol></li><li class="chapter-item expanded "><a href="datetime.html"><strong aria-hidden="true">8.</strong> Date and Time</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="datetime/duration.html"><strong aria-hidden="true">8.1.</strong> Duration and Calculation</a></li><li class="chapter-item expanded "><a href="datetime/parse.html"><strong aria-hidden="true">8.2.</strong> Parsing and Displaying</a></li></ol></li><li class="chapter-item expanded "><a href="development_tools.html"><strong aria-hidden="true">9.</strong> Development Tools</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="development_tools/debugging.html"><strong aria-hidden="true">9.1.</strong> Debugging</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="development_tools/debugging/log.html"><strong aria-hidden="true">9.1.1.</strong> Log Messages</a></li><li class="chapter-item expanded "><a href="development_tools/debugging/config_log.html"><strong aria-hidden="true">9.1.2.</strong> Configure Logging</a></li></ol></li><li class="chapter-item expanded "><a href="development_tools/versioning.html"><strong aria-hidden="true">9.2.</strong> Versioning</a></li><li class="chapter-item expanded "><a href="development_tools/build_tools.html"><strong aria-hidden="true">9.3.</strong> Build Time Tooling</a></li></ol></li><li class="chapter-item expanded "><a href="encoding.html"><strong aria-hidden="true">10.</strong> Encoding</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="encoding/strings.html"><strong aria-hidden="true">10.1.</strong> Character Sets</a></li><li class="chapter-item expanded "><a href="encoding/csv.html"><strong aria-hidden="true">10.2.</strong> CSV processing</a></li><li class="chapter-item expanded "><a href="encoding/complex.html"><strong aria-hidden="true">10.3.</strong> Structured Data</a></li></ol></li><li class="chapter-item expanded "><a href="errors.html"><strong aria-hidden="true">11.</strong> Error Handling</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="errors/handle.html"><strong aria-hidden="true">11.1.</strong> Handle Error Variants</a></li></ol></li><li class="chapter-item expanded "><a href="file.html"><strong aria-hidden="true">12.</strong> File System</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="file/read-write.html"><strong aria-hidden="true">12.1.</strong> Read &amp; Write</a></li><li class="chapter-item expanded "><a href="file/dir.html"><strong aria-hidden="true">12.2.</strong> Directory Traversal</a></li></ol></li><li class="chapter-item expanded "><a href="hardware.html"><strong aria-hidden="true">13.</strong> Hardware Support</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="hardware/processor.html"><strong aria-hidden="true">13.1.</strong> Processor</a></li></ol></li><li class="chapter-item expanded "><a href="mem.html"><strong aria-hidden="true">14.</strong> Memory Management</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="mem/global_static.html"><strong aria-hidden="true">14.1.</strong> Global Static</a></li></ol></li><li class="chapter-item expanded "><a href="net.html"><strong aria-hidden="true">15.</strong> Network</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="net/server.html"><strong aria-hidden="true">15.1.</strong> Server</a></li></ol></li><li class="chapter-item expanded "><a href="os.html"><strong aria-hidden="true">16.</strong> Operating System</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="os/external.html"><strong aria-hidden="true">16.1.</strong> External Command</a></li></ol></li><li class="chapter-item expanded "><a href="science.html"><strong aria-hidden="true">17.</strong> Science</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="science/mathematics.html"><strong aria-hidden="true">17.1.</strong> Mathematics</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="science/mathematics/linear_algebra.html"><strong aria-hidden="true">17.1.1.</strong> Linear Algebra</a></li><li class="chapter-item expanded "><a href="science/mathematics/trigonometry.html"><strong aria-hidden="true">17.1.2.</strong> Trigonometry</a></li><li class="chapter-item expanded "><a href="science/mathematics/complex_numbers.html"><strong aria-hidden="true">17.1.3.</strong> Complex Numbers</a></li><li class="chapter-item expanded "><a href="science/mathematics/statistics.html"><strong aria-hidden="true">17.1.4.</strong> Statistics</a></li><li class="chapter-item expanded "><a href="science/mathematics/miscellaneous.html"><strong aria-hidden="true">17.1.5.</strong> Miscellaneous</a></li></ol></li></ol></li><li class="chapter-item expanded "><a href="text.html"><strong aria-hidden="true">18.</strong> Text Processing</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="text/regex.html"><strong aria-hidden="true">18.1.</strong> Regular Expressions</a></li><li class="chapter-item expanded "><a href="text/string_parsing.html"><strong aria-hidden="true">18.2.</strong> String Parsing</a></li></ol></li><li class="chapter-item expanded "><a href="web.html"><strong aria-hidden="true">19.</strong> Web Programming</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="web/scraping.html"><strong aria-hidden="true">19.1.</strong> Extracting Links</a></li><li class="chapter-item expanded "><a href="web/url.html"><strong aria-hidden="true">19.2.</strong> URL</a></li><li class="chapter-item expanded "><a href="web/mime.html"><strong aria-hidden="true">19.3.</strong> Media Types</a></li><li class="chapter-item expanded "><a href="web/clients.html"><strong aria-hidden="true">19.4.</strong> Clients</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="web/clients/requests.html"><strong aria-hidden="true">19.4.1.</strong> Making Requests</a></li><li class="chapter-item expanded "><a href="web/clients/apis.html"><strong aria-hidden="true">19.4.2.</strong> Calling a Web API</a></li><li class="chapter-item expanded "><a href="web/clients/download.html"><strong aria-hidden="true">19.4.3.</strong> Downloads</a></li><li class="chapter-item expanded "><a href="web/clients/authentication.html"><strong aria-hidden="true">19.4.4.</strong> Web Authentication</a></li></ol></li></ol></li></ol>
</div>
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
</nav>
<div id="page-wrapper" class="page-wrapper">
<div class="page">
<div id="menu-bar-hover-placeholder"></div>
<div id="menu-bar" class="menu-bar sticky bordered">
<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">Rust Cookbook</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 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>
<h1><a class="header" href="#cookin-with-rust" id="cookin-with-rust">Cookin' with Rust</a></h1>
<p>This <em>Rust Cookbook</em> is a collection of
simple examples that demonstrate good practices to accomplish common
programming tasks, using the crates of the Rust ecosystem.</p>
<p><a href="about.html">Read more about <em>Rust Cookbook</em></a>, including tips for
how to read the book, how to use the examples, and notes on conventions.</p>
<h2><a class="header" href="#contributing" id="contributing">Contributing</a></h2>
<p>This project is intended to be easy for new Rust programmers to
contribute to, and an easy way to get involved with the Rust
community. It needs and welcomes help. For details see
<a href="https://github.com/rust-lang-nursery/rust-cookbook/blob/master/CONTRIBUTING.md">CONTRIBUTING.md</a>.</p>
<h1><a class="header" href="#algorithms" id="algorithms">Algorithms</a></h1>
<table><thead><tr><th>Recipe</th><th>Crates</th><th>Categories</th></tr></thead><tbody>
<tr><td><a href="algorithms/randomness.html#generate-random-numbers">Generate random numbers</a></td><td><a href="https://docs.rs/rand/"><img src="https://badge-cache.kominick.com/crates/v/rand.svg?label=rand" alt="rand-badge" /></a></td><td><a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></td></tr>
<tr><td><a href="algorithms/randomness.html#generate-random-numbers-within-a-range">Generate random numbers within a range</a></td><td><a href="https://docs.rs/rand/"><img src="https://badge-cache.kominick.com/crates/v/rand.svg?label=rand" alt="rand-badge" /></a></td><td><a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></td></tr>
<tr><td><a href="algorithms/randomness.html#generate-random-numbers-with-given-distribution">Generate random numbers with given distribution</a></td><td><a href="https://docs.rs/rand/"><img src="https://badge-cache.kominick.com/crates/v/rand.svg?label=rand" alt="rand-badge" /></a> <a href="https://docs.rs/rand_distr/"><img src="https://badge-cache.kominick.com/crates/v/rand.svg?label=rand_distr" alt="rand_distr-badge" /></a></td><td><a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></td></tr>
<tr><td><a href="algorithms/randomness.html#generate-random-values-of-a-custom-type">Generate random values of a custom type</a></td><td><a href="https://docs.rs/rand/"><img src="https://badge-cache.kominick.com/crates/v/rand.svg?label=rand" alt="rand-badge" /></a></td><td><a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></td></tr>
<tr><td><a href="algorithms/randomness.html#create-random-passwords-from-a-set-of-alphanumeric-characters">Create random passwords from a set of alphanumeric characters</a></td><td><a href="https://docs.rs/rand/"><img src="https://badge-cache.kominick.com/crates/v/rand.svg?label=rand" alt="rand-badge" /></a></td><td><a href="https://crates.io/categories/os"><img src="https://badge-cache.kominick.com/badge/OS--x.svg?style=social" alt="cat-os-badge" /></a></td></tr>
<tr><td><a href="algorithms/randomness.html#create-random-passwords-from-a-set-of-user-defined-characters">Create random passwords from a set of user-defined characters</a></td><td><a href="https://docs.rs/rand/"><img src="https://badge-cache.kominick.com/crates/v/rand.svg?label=rand" alt="rand-badge" /></a></td><td><a href="https://crates.io/categories/os"><img src="https://badge-cache.kominick.com/badge/OS--x.svg?style=social" alt="cat-os-badge" /></a></td></tr>
<tr><td><a href="algorithms/sorting.html#sort-a-vector-of-integers">Sort a Vector of Integers</a></td><td><a href="https://doc.rust-lang.org/std"><img src="https://badge-cache.kominick.com/badge/std-1.29.1-blue.svg" alt="std-badge" /></a></td><td><a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></td></tr>
<tr><td><a href="algorithms/sorting.html#sort-a-vector-of-floats">Sort a Vector of Floats</a></td><td><a href="https://doc.rust-lang.org/std"><img src="https://badge-cache.kominick.com/badge/std-1.29.1-blue.svg" alt="std-badge" /></a></td><td><a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></td></tr>
<tr><td><a href="algorithms/sorting.html#sort-a-vector-of-structs">Sort a Vector of Structs</a></td><td><a href="https://doc.rust-lang.org/std"><img src="https://badge-cache.kominick.com/badge/std-1.29.1-blue.svg" alt="std-badge" /></a></td><td><a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></td></tr>
</tbody></table>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#command-line" id="command-line">Command Line</a></h1>
<table><thead><tr><th>Recipe</th><th>Crates</th><th>Categories</th></tr></thead><tbody>
<tr><td><a href="cli/arguments.html#parse-command-line-arguments">Parse command line arguments</a></td><td><a href="https://docs.rs/clap/"><img src="https://badge-cache.kominick.com/crates/v/clap.svg?label=clap" alt="clap-badge" /></a></td><td><a href="https://crates.io/categories/command-line-interface"><img src="https://badge-cache.kominick.com/badge/command_line--x.svg?style=social" alt="cat-command-line-badge" /></a></td></tr>
<tr><td><a href="cli/ansi_terminal.html#ansi-terminal">ANSI Terminal</a></td><td><a href="https://docs.rs/ansi_term/"><img src="https://badge-cache.kominick.com/crates/v/base64.svg?label=ansi_term" alt="ansi_term-badge" /></a></td><td><a href="https://crates.io/categories/command-line-interface"><img src="https://badge-cache.kominick.com/badge/command_line--x.svg?style=social" alt="cat-command-line-badge" /></a></td></tr>
</tbody></table>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#compression" id="compression">Compression</a></h1>
<table><thead><tr><th>Recipe</th><th>Crates</th><th>Categories</th></tr></thead><tbody>
<tr><td><a href="compression/tar.html#decompress-a-tarball">Decompress a tarball</a></td><td><a href="https://docs.rs/flate2/"><img src="https://badge-cache.kominick.com/crates/v/flate2.svg?label=flate2" alt="flate2-badge" /></a> <a href="https://docs.rs/tar/"><img src="https://badge-cache.kominick.com/crates/v/tar.svg?label=tar" alt="tar-badge" /></a></td><td><a href="https://crates.io/categories/compression"><img src="https://badge-cache.kominick.com/badge/compression--x.svg?style=social" alt="cat-compression-badge" /></a></td></tr>
<tr><td><a href="compression/tar.html#compress-a-directory-into-tarball">Compress a directory into a tarball</a></td><td><a href="https://docs.rs/flate2/"><img src="https://badge-cache.kominick.com/crates/v/flate2.svg?label=flate2" alt="flate2-badge" /></a> <a href="https://docs.rs/tar/"><img src="https://badge-cache.kominick.com/crates/v/tar.svg?label=tar" alt="tar-badge" /></a></td><td><a href="https://crates.io/categories/compression"><img src="https://badge-cache.kominick.com/badge/compression--x.svg?style=social" alt="cat-compression-badge" /></a></td></tr>
<tr><td><a href="compression/tar.html#decompress-a-tarball-while-removing-a-prefix-from-the-paths">Decompress a tarball while removing a prefix from the paths</a></td><td><a href="https://docs.rs/flate2/"><img src="https://badge-cache.kominick.com/crates/v/flate2.svg?label=flate2" alt="flate2-badge" /></a> <a href="https://docs.rs/tar/"><img src="https://badge-cache.kominick.com/crates/v/tar.svg?label=tar" alt="tar-badge" /></a></td><td><a href="https://crates.io/categories/compression"><img src="https://badge-cache.kominick.com/badge/compression--x.svg?style=social" alt="cat-compression-badge" /></a></td></tr>
</tbody></table>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#concurrency" id="concurrency">Concurrency</a></h1>
<table><thead><tr><th>Recipe</th><th>Crates</th><th>Categories</th></tr></thead><tbody>
<tr><td><a href="concurrency/threads.html#spawn-a-short-lived-thread">Spawn a short-lived thread</a></td><td><a href="https://docs.rs/crossbeam/"><img src="https://badge-cache.kominick.com/crates/v/crossbeam.svg?label=crossbeam" alt="crossbeam-badge" /></a></td><td><a href="https://crates.io/categories/concurrency"><img src="https://badge-cache.kominick.com/badge/concurrency--x.svg?style=social" alt="cat-concurrency-badge" /></a></td></tr>
<tr><td><a href="concurrency/threads.html#create-a-parallel-pipeline">Create a parallel data pipeline</a></td><td><a href="https://docs.rs/crossbeam/"><img src="https://badge-cache.kominick.com/crates/v/crossbeam.svg?label=crossbeam" alt="crossbeam-badge" /></a></td><td><a href="https://crates.io/categories/concurrency"><img src="https://badge-cache.kominick.com/badge/concurrency--x.svg?style=social" alt="cat-concurrency-badge" /></a></td></tr>
<tr><td><a href="concurrency/threads.html#pass-data-between-two-threads">Pass data between two threads</a></td><td><a href="https://docs.rs/crossbeam/"><img src="https://badge-cache.kominick.com/crates/v/crossbeam.svg?label=crossbeam" alt="crossbeam-badge" /></a></td><td><a href="https://crates.io/categories/concurrency"><img src="https://badge-cache.kominick.com/badge/concurrency--x.svg?style=social" alt="cat-concurrency-badge" /></a></td></tr>
<tr><td><a href="concurrency/threads.html#maintain-global-mutable-state">Maintain global mutable state</a></td><td><a href="https://docs.rs/lazy_static/"><img src="https://badge-cache.kominick.com/crates/v/lazy_static.svg?label=lazy_static" alt="lazy_static-badge" /></a></td><td><a href="https://crates.io/categories/rust-patterns"><img src="https://badge-cache.kominick.com/badge/rust_patterns--x.svg?style=social" alt="cat-rust-patterns-badge" /></a></td></tr>
<tr><td><a href="concurrency/threads.html#calculate-sha256-sum-of-iso-files-concurrently">Calculate SHA1 sum of *.iso files concurrently</a></td><td><a href="https://docs.rs/threadpool/"><img src="https://badge-cache.kominick.com/crates/v/threadpool.svg?label=threadpool" alt="threadpool-badge" /></a> <a href="https://docs.rs/walkdir/"><img src="https://badge-cache.kominick.com/crates/v/walkdir.svg?label=walkdir" alt="walkdir-badge" /></a> <a href="https://docs.rs/num_cpus/"><img src="https://badge-cache.kominick.com/crates/v/num_cpus.svg?label=num_cpus" alt="num_cpus-badge" /></a> <a href="https://briansmith.org/rustdoc/ring/"><img src="https://badge-cache.kominick.com/crates/v/ring.svg?label=ring" alt="ring-badge" /></a></td><td><a href="https://crates.io/categories/concurrency"><img src="https://badge-cache.kominick.com/badge/concurrency--x.svg?style=social" alt="cat-concurrency-badge" /></a><a href="https://crates.io/categories/filesystem"><img src="https://badge-cache.kominick.com/badge/filesystem--x.svg?style=social" alt="cat-filesystem-badge" /></a></td></tr>
<tr><td><a href="concurrency/threads.html#draw-fractal-dispatching-work-to-a-thread-pool">Draw fractal dispatching work to a thread pool</a></td><td><a href="https://docs.rs/threadpool/"><img src="https://badge-cache.kominick.com/crates/v/threadpool.svg?label=threadpool" alt="threadpool-badge" /></a> <a href="https://docs.rs/num/"><img src="https://badge-cache.kominick.com/crates/v/num.svg?label=num" alt="num-badge" /></a> <a href="https://docs.rs/num_cpus/"><img src="https://badge-cache.kominick.com/crates/v/num_cpus.svg?label=num_cpus" alt="num_cpus-badge" /></a> <a href="https://docs.rs/image/"><img src="https://badge-cache.kominick.com/crates/v/image.svg?label=image" alt="image-badge" /></a></td><td><a href="https://crates.io/categories/concurrency"><img src="https://badge-cache.kominick.com/badge/concurrency--x.svg?style=social" alt="cat-concurrency-badge" /></a><a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a><a href="https://crates.io/categories/rendering"><img src="https://badge-cache.kominick.com/badge/rendering--x.svg?style=social" alt="cat-rendering-badge" /></a></td></tr>
<tr><td><a href="concurrency/parallel.html#mutate-the-elements-of-an-array-in-parallel">Mutate the elements of an array in parallel</a></td><td><a href="https://docs.rs/rayon/"><img src="https://badge-cache.kominick.com/crates/v/rayon.svg?label=rayon" alt="rayon-badge" /></a></td><td><a href="https://crates.io/categories/concurrency"><img src="https://badge-cache.kominick.com/badge/concurrency--x.svg?style=social" alt="cat-concurrency-badge" /></a></td></tr>
<tr><td><a href="concurrency/parallel.html#test-in-parallel-if-any-or-all-elements-of-a-collection-match-a-given-predicate">Test in parallel if any or all elements of a collection match a given predicate</a></td><td><a href="https://docs.rs/rayon/"><img src="https://badge-cache.kominick.com/crates/v/rayon.svg?label=rayon" alt="rayon-badge" /></a></td><td><a href="https://crates.io/categories/concurrency"><img src="https://badge-cache.kominick.com/badge/concurrency--x.svg?style=social" alt="cat-concurrency-badge" /></a></td></tr>
<tr><td><a href="concurrency/parallel.html#search-items-using-given-predicate-in-parallel">Search items using given predicate in parallel</a></td><td><a href="https://docs.rs/rayon/"><img src="https://badge-cache.kominick.com/crates/v/rayon.svg?label=rayon" alt="rayon-badge" /></a></td><td><a href="https://crates.io/categories/concurrency"><img src="https://badge-cache.kominick.com/badge/concurrency--x.svg?style=social" alt="cat-concurrency-badge" /></a></td></tr>
<tr><td><a href="concurrency/parallel.html#sort-a-vector-in-parallel">Sort a vector in parallel</a></td><td><a href="https://docs.rs/rayon/"><img src="https://badge-cache.kominick.com/crates/v/rayon.svg?label=rayon" alt="rayon-badge" /></a> <a href="https://docs.rs/rand/"><img src="https://badge-cache.kominick.com/crates/v/rand.svg?label=rand" alt="rand-badge" /></a></td><td><a href="https://crates.io/categories/concurrency"><img src="https://badge-cache.kominick.com/badge/concurrency--x.svg?style=social" alt="cat-concurrency-badge" /></a></td></tr>
<tr><td><a href="concurrency/parallel.html#map-reduce-in-parallel">Map-reduce in parallel</a></td><td><a href="https://docs.rs/rayon/"><img src="https://badge-cache.kominick.com/crates/v/rayon.svg?label=rayon" alt="rayon-badge" /></a></td><td><a href="https://crates.io/categories/concurrency"><img src="https://badge-cache.kominick.com/badge/concurrency--x.svg?style=social" alt="cat-concurrency-badge" /></a></td></tr>
<tr><td><a href="concurrency/parallel.html#generate-jpg-thumbnails-in-parallel">Generate jpg thumbnails in parallel</a></td><td><a href="https://docs.rs/rayon/"><img src="https://badge-cache.kominick.com/crates/v/rayon.svg?label=rayon" alt="rayon-badge" /></a> <a href="https://docs.rs/glob/"><img src="https://badge-cache.kominick.com/crates/v/glob.svg?label=glob" alt="glob-badge" /></a> <a href="https://docs.rs/image/"><img src="https://badge-cache.kominick.com/crates/v/image.svg?label=image" alt="image-badge" /></a></td><td><a href="https://crates.io/categories/concurrency"><img src="https://badge-cache.kominick.com/badge/concurrency--x.svg?style=social" alt="cat-concurrency-badge" /></a><a href="https://crates.io/categories/filesystem"><img src="https://badge-cache.kominick.com/badge/filesystem--x.svg?style=social" alt="cat-filesystem-badge" /></a></td></tr>
</tbody></table>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#cryptography" id="cryptography">Cryptography</a></h1>
<table><thead><tr><th>Recipe</th><th>Crates</th><th>Categories</th></tr></thead><tbody>
<tr><td><a href="cryptography/hashing.html#calculate-the-sha-256-digest-of-a-file">Calculate the SHA-256 digest of a file</a></td><td><a href="https://briansmith.org/rustdoc/ring/"><img src="https://badge-cache.kominick.com/crates/v/ring.svg?label=ring" alt="ring-badge" /></a> <a href="https://docs.rs/data-encoding/"><img src="https://badge-cache.kominick.com/crates/v/data-encoding.svg?label=data-encoding" alt="data-encoding-badge" /></a></td><td><a href="https://crates.io/categories/cryptography"><img src="https://badge-cache.kominick.com/badge/cryptography--x.svg?style=social" alt="cat-cryptography-badge" /></a></td></tr>
<tr><td><a href="cryptography/hashing.html#sign-and-verify-a-message-with-hmac-digest">Sign and verify a message with an HMAC digest</a></td><td><a href="https://briansmith.org/rustdoc/ring/"><img src="https://badge-cache.kominick.com/crates/v/ring.svg?label=ring" alt="ring-badge" /></a></td><td><a href="https://crates.io/categories/cryptography"><img src="https://badge-cache.kominick.com/badge/cryptography--x.svg?style=social" alt="cat-cryptography-badge" /></a></td></tr>
<tr><td><a href="cryptography/encryption.html#salt-and-hash-a-password-with-pbkdf2">Salt and hash a password with PBKDF2</a></td><td><a href="https://briansmith.org/rustdoc/ring/"><img src="https://badge-cache.kominick.com/crates/v/ring.svg?label=ring" alt="ring-badge" /></a> <a href="https://docs.rs/data-encoding/"><img src="https://badge-cache.kominick.com/crates/v/data-encoding.svg?label=data-encoding" alt="data-encoding-badge" /></a></td><td><a href="https://crates.io/categories/cryptography"><img src="https://badge-cache.kominick.com/badge/cryptography--x.svg?style=social" alt="cat-cryptography-badge" /></a></td></tr>
</tbody></table>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#data-structures" id="data-structures">Data Structures</a></h1>
<table><thead><tr><th>Recipe</th><th>Crates</th><th>Categories</th></tr></thead><tbody>
<tr><td><a href="data_structures/bitfield.html#define-and-operate-on-a-type-represented-as-a-bitfield">Define and operate on a type represented as a bitfield</a></td><td><a href="https://docs.rs/bitflags/"><img src="https://badge-cache.kominick.com/crates/v/bitflags.svg?label=bitflags" alt="bitflags-badge" /></a></td><td><a href="https://crates.io/categories/no-std"><img src="https://badge-cache.kominick.com/badge/no_std--x.svg?style=social" alt="cat-no-std-badge" /></a></td></tr>
</tbody></table>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#database" id="database">Database</a></h1>
<table><thead><tr><th>Recipe</th><th>Crates</th><th>Categories</th></tr></thead><tbody>
<tr><td><a href="database/sqlite.html#create-a-sqlite-database">Create a SQLite database</a></td><td><a href="https://crates.io/crates/rusqlite/"><img src="https://badge-cache.kominick.com/crates/v/rusqlite.svg?label=rusqlite" alt="rusqlite-badge" /></a></td><td><a href="https://crates.io/categories/database"><img src="https://badge-cache.kominick.com/badge/database--x.svg?style=social" alt="cat-database-badge" /></a></td></tr>
<tr><td><a href="database/sqlite.html#insert-and-select-data">Insert and Query data</a></td><td><a href="https://crates.io/crates/rusqlite/"><img src="https://badge-cache.kominick.com/crates/v/rusqlite.svg?label=rusqlite" alt="rusqlite-badge" /></a></td><td><a href="https://crates.io/categories/database"><img src="https://badge-cache.kominick.com/badge/database--x.svg?style=social" alt="cat-database-badge" /></a></td></tr>
<tr><td><a href="database/postgres.html#create-tables-in-a-postgres-database">Create tables in a Postgres database</a></td><td><a href="https://docs.rs/postgres/0.15.2/postgres/"><img src="https://badge-cache.kominick.com/crates/v/postgres.svg?label=postgres" alt="postgres-badge" /></a></td><td><a href="https://crates.io/categories/database"><img src="https://badge-cache.kominick.com/badge/database--x.svg?style=social" alt="cat-database-badge" /></a></td></tr>
<tr><td><a href="database/postgres.html#insert-and-query-data">Insert and Query data</a></td><td><a href="https://docs.rs/postgres/0.15.2/postgres/"><img src="https://badge-cache.kominick.com/crates/v/postgres.svg?label=postgres" alt="postgres-badge" /></a></td><td><a href="https://crates.io/categories/database"><img src="https://badge-cache.kominick.com/badge/database--x.svg?style=social" alt="cat-database-badge" /></a></td></tr>
<tr><td><a href="database/postgres.html#aggregate-data">Aggregate data</a></td><td><a href="https://docs.rs/postgres/0.15.2/postgres/"><img src="https://badge-cache.kominick.com/crates/v/postgres.svg?label=postgres" alt="postgres-badge" /></a></td><td><a href="https://crates.io/categories/database"><img src="https://badge-cache.kominick.com/badge/database--x.svg?style=social" alt="cat-database-badge" /></a></td></tr>
</tbody></table>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#date-and-time" id="date-and-time">Date and Time</a></h1>
<table><thead><tr><th>Recipe</th><th>Crates</th><th>Categories</th></tr></thead><tbody>
<tr><td><a href="datetime/duration.html#measure-the-elapsed-time-between-two-code-sections">Measure elapsed time</a></td><td><a href="https://doc.rust-lang.org/std"><img src="https://badge-cache.kominick.com/badge/std-1.29.1-blue.svg" alt="std-badge" /></a></td><td><a href="https://crates.io/categories/date-and-time"><img src="https://badge-cache.kominick.com/badge/time--x.svg?style=social" alt="cat-time-badge" /></a></td></tr>
<tr><td><a href="datetime/duration.html#perform-checked-date-and-time-calculations">Perform checked date and time calculations</a></td><td><a href="https://docs.rs/chrono/"><img src="https://badge-cache.kominick.com/crates/v/chrono.svg?label=chrono" alt="chrono-badge" /></a></td><td><a href="https://crates.io/categories/date-and-time"><img src="https://badge-cache.kominick.com/badge/date_and_time--x.svg?style=social" alt="cat-date-and-time-badge" /></a></td></tr>
<tr><td><a href="datetime/duration.html#convert-a-local-time-to-another-timezone">Convert a local time to another timezone</a></td><td><a href="https://docs.rs/chrono/"><img src="https://badge-cache.kominick.com/crates/v/chrono.svg?label=chrono" alt="chrono-badge" /></a></td><td><a href="https://crates.io/categories/date-and-time"><img src="https://badge-cache.kominick.com/badge/date_and_time--x.svg?style=social" alt="cat-date-and-time-badge" /></a></td></tr>
<tr><td><a href="datetime/parse.html#examine-the-date-and-time">Examine the date and time</a></td><td><a href="https://docs.rs/chrono/"><img src="https://badge-cache.kominick.com/crates/v/chrono.svg?label=chrono" alt="chrono-badge" /></a></td><td><a href="https://crates.io/categories/date-and-time"><img src="https://badge-cache.kominick.com/badge/date_and_time--x.svg?style=social" alt="cat-date-and-time-badge" /></a></td></tr>
<tr><td><a href="datetime/parse.html#convert-date-to-unix-timestamp-and-vice-versa">Convert date to UNIX timestamp and vice versa</a></td><td><a href="https://docs.rs/chrono/"><img src="https://badge-cache.kominick.com/crates/v/chrono.svg?label=chrono" alt="chrono-badge" /></a></td><td><a href="https://crates.io/categories/date-and-time"><img src="https://badge-cache.kominick.com/badge/date_and_time--x.svg?style=social" alt="cat-date-and-time-badge" /></a></td></tr>
<tr><td><a href="datetime/parse.html#display-formatted-date-and-time">Display formatted date and time</a></td><td><a href="https://docs.rs/chrono/"><img src="https://badge-cache.kominick.com/crates/v/chrono.svg?label=chrono" alt="chrono-badge" /></a></td><td><a href="https://crates.io/categories/date-and-time"><img src="https://badge-cache.kominick.com/badge/date_and_time--x.svg?style=social" alt="cat-date-and-time-badge" /></a></td></tr>
<tr><td><a href="datetime/parse.html#parse-string-into-datetime-struct">Parse string into DateTime struct</a></td><td><a href="https://docs.rs/chrono/"><img src="https://badge-cache.kominick.com/crates/v/chrono.svg?label=chrono" alt="chrono-badge" /></a></td><td><a href="https://crates.io/categories/date-and-time"><img src="https://badge-cache.kominick.com/badge/date_and_time--x.svg?style=social" alt="cat-date-and-time-badge" /></a></td></tr>
</tbody></table>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#development-tools" id="development-tools">Development Tools</a></h1>
<h2><a class="header" href="#debugging" id="debugging">Debugging</a></h2>
<table><thead><tr><th>Recipe</th><th>Crates</th><th>Categories</th></tr></thead><tbody>
<tr><td><a href="development_tools/debugging/log.html#log-a-debug-message-to-the-console">Log a debug message to the console</a></td><td><a href="https://docs.rs/log/"><img src="https://badge-cache.kominick.com/crates/v/log.svg?label=log" alt="log-badge" /></a> <a href="https://docs.rs/env_logger/"><img src="https://badge-cache.kominick.com/crates/v/env_logger.svg?label=env_logger" alt="env_logger-badge" /></a></td><td><a href="https://crates.io/categories/debugging"><img src="https://badge-cache.kominick.com/badge/debugging--x.svg?style=social" alt="cat-debugging-badge" /></a></td></tr>
<tr><td><a href="development_tools/debugging/log.html#log-an-error-message-to-the-console">Log an error message to the console</a></td><td><a href="https://docs.rs/log/"><img src="https://badge-cache.kominick.com/crates/v/log.svg?label=log" alt="log-badge" /></a> <a href="https://docs.rs/env_logger/"><img src="https://badge-cache.kominick.com/crates/v/env_logger.svg?label=env_logger" alt="env_logger-badge" /></a></td><td><a href="https://crates.io/categories/debugging"><img src="https://badge-cache.kominick.com/badge/debugging--x.svg?style=social" alt="cat-debugging-badge" /></a></td></tr>
<tr><td><a href="development_tools/debugging/log.html#log-to-stdout-instead-of-stderr">Log to stdout instead of stderr</a></td><td><a href="https://docs.rs/log/"><img src="https://badge-cache.kominick.com/crates/v/log.svg?label=log" alt="log-badge" /></a> <a href="https://docs.rs/env_logger/"><img src="https://badge-cache.kominick.com/crates/v/env_logger.svg?label=env_logger" alt="env_logger-badge" /></a></td><td><a href="https://crates.io/categories/debugging"><img src="https://badge-cache.kominick.com/badge/debugging--x.svg?style=social" alt="cat-debugging-badge" /></a></td></tr>
<tr><td><a href="development_tools/debugging/log.html#log-messages-with-a-custom-logger">Log messages with a custom logger</a></td><td><a href="https://docs.rs/log/"><img src="https://badge-cache.kominick.com/crates/v/log.svg?label=log" alt="log-badge" /></a></td><td><a href="https://crates.io/categories/debugging"><img src="https://badge-cache.kominick.com/badge/debugging--x.svg?style=social" alt="cat-debugging-badge" /></a></td></tr>
<tr><td><a href="development_tools/debugging/log.html#log-to-the-unix-syslog">Log to the Unix syslog</a></td><td><a href="https://docs.rs/log/"><img src="https://badge-cache.kominick.com/crates/v/log.svg?label=log" alt="log-badge" /></a> <a href="https://docs.rs/syslog/"><img src="https://badge-cache.kominick.com/crates/v/syslog.svg?label=syslog" alt="syslog-badge" /></a></td><td><a href="https://crates.io/categories/debugging"><img src="https://badge-cache.kominick.com/badge/debugging--x.svg?style=social" alt="cat-debugging-badge" /></a></td></tr>
<tr><td><a href="development_tools/debugging/config_log.html#enable-log-levels-per-module">Enable log levels per module</a></td><td><a href="https://docs.rs/log/"><img src="https://badge-cache.kominick.com/crates/v/log.svg?label=log" alt="log-badge" /></a> <a href="https://docs.rs/env_logger/"><img src="https://badge-cache.kominick.com/crates/v/env_logger.svg?label=env_logger" alt="env_logger-badge" /></a></td><td><a href="https://crates.io/categories/debugging"><img src="https://badge-cache.kominick.com/badge/debugging--x.svg?style=social" alt="cat-debugging-badge" /></a></td></tr>
<tr><td><a href="development_tools/debugging/config_log.html#use-a-custom-environment-variable-to-set-up-logging">Use a custom environment variable to set up logging</a></td><td><a href="https://docs.rs/log/"><img src="https://badge-cache.kominick.com/crates/v/log.svg?label=log" alt="log-badge" /></a> <a href="https://docs.rs/env_logger/"><img src="https://badge-cache.kominick.com/crates/v/env_logger.svg?label=env_logger" alt="env_logger-badge" /></a></td><td><a href="https://crates.io/categories/debugging"><img src="https://badge-cache.kominick.com/badge/debugging--x.svg?style=social" alt="cat-debugging-badge" /></a></td></tr>
<tr><td><a href="development_tools/debugging/config_log.html#include-timestamp-in-log-messages">Include timestamp in log messages</a></td><td><a href="https://docs.rs/log/"><img src="https://badge-cache.kominick.com/crates/v/log.svg?label=log" alt="log-badge" /></a> <a href="https://docs.rs/env_logger/"><img src="https://badge-cache.kominick.com/crates/v/env_logger.svg?label=env_logger" alt="env_logger-badge" /></a> <a href="https://docs.rs/chrono/"><img src="https://badge-cache.kominick.com/crates/v/chrono.svg?label=chrono" alt="chrono-badge" /></a></td><td><a href="https://crates.io/categories/debugging"><img src="https://badge-cache.kominick.com/badge/debugging--x.svg?style=social" alt="cat-debugging-badge" /></a></td></tr>
<tr><td><a href="development_tools/debugging/config_log.html#log-messages-to-a-custom-location">Log messages to a custom location</a></td><td><a href="https://docs.rs/log/"><img src="https://badge-cache.kominick.com/crates/v/log.svg?label=log" alt="log-badge" /></a> <a href="https://docs.rs/log4rs/"><img src="https://badge-cache.kominick.com/crates/v/log4rs.svg?label=log4rs" alt="log4rs-badge" /></a></td><td><a href="https://crates.io/categories/debugging"><img src="https://badge-cache.kominick.com/badge/debugging--x.svg?style=social" alt="cat-debugging-badge" /></a></td></tr>
</tbody></table>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h2><a class="header" href="#versioning" id="versioning">Versioning</a></h2>
<table><thead><tr><th>Recipe</th><th>Crates</th><th>Categories</th></tr></thead><tbody>
<tr><td><a href="development_tools/versioning.html#parse-and-increment-a-version-string">Parse and increment a version string</a></td><td><a href="https://docs.rs/semver/"><img src="https://badge-cache.kominick.com/crates/v/semver.svg?label=semver" alt="semver-badge" /></a></td><td><a href="https://crates.io/categories/config"><img src="https://badge-cache.kominick.com/badge/config--x.svg?style=social" alt="cat-config-badge" /></a></td></tr>
<tr><td><a href="development_tools/versioning.html#parse-a-complex-version-string">Parse a complex version string</a></td><td><a href="https://docs.rs/semver/"><img src="https://badge-cache.kominick.com/crates/v/semver.svg?label=semver" alt="semver-badge" /></a></td><td><a href="https://crates.io/categories/config"><img src="https://badge-cache.kominick.com/badge/config--x.svg?style=social" alt="cat-config-badge" /></a></td></tr>
<tr><td><a href="development_tools/versioning.html#check-if-given-version-is-pre-release">Check if given version is pre-release</a></td><td><a href="https://docs.rs/semver/"><img src="https://badge-cache.kominick.com/crates/v/semver.svg?label=semver" alt="semver-badge" /></a></td><td><a href="https://crates.io/categories/config"><img src="https://badge-cache.kominick.com/badge/config--x.svg?style=social" alt="cat-config-badge" /></a></td></tr>
<tr><td><a href="development_tools/versioning.html#find-the-latest-version-satisfying-given-range">Find the latest version satisfying given range</a></td><td><a href="https://docs.rs/semver/"><img src="https://badge-cache.kominick.com/crates/v/semver.svg?label=semver" alt="semver-badge" /></a></td><td><a href="https://crates.io/categories/config"><img src="https://badge-cache.kominick.com/badge/config--x.svg?style=social" alt="cat-config-badge" /></a></td></tr>
<tr><td><a href="development_tools/versioning.html#check-external-command-version-for-compatibility">Check external command version for compatibility</a></td><td><a href="https://docs.rs/semver/"><img src="https://badge-cache.kominick.com/crates/v/semver.svg?label=semver" alt="semver-badge" /></a></td><td><a href="https://crates.io/categories/text-processing"><img src="https://badge-cache.kominick.com/badge/text_processing--x.svg?style=social" alt="cat-text-processing-badge" /></a> <a href="https://crates.io/categories/os"><img src="https://badge-cache.kominick.com/badge/OS--x.svg?style=social" alt="cat-os-badge" /></a></td></tr>
</tbody></table>
<h2><a class="header" href="#build-time" id="build-time">Build Time</a></h2>
<table><thead><tr><th>Recipe</th><th>Crates</th><th>Categories</th></tr></thead><tbody>
<tr><td><a href="development_tools/build_tools.html#compile-and-link-statically-to-a-bundled-c-library">Compile and link statically to a bundled C library</a></td><td><a href="https://docs.rs/cc"><img src="https://badge-cache.kominick.com/crates/v/cc.svg?label=cc" alt="cc-badge" /></a></td><td><a href="https://crates.io/categories/development-tools"><img src="https://badge-cache.kominick.com/badge/development_tools--x.svg?style=social" alt="cat-development-tools-badge" /></a></td></tr>
<tr><td><a href="development_tools/build_tools.html#compile-and-link-statically-to-a-bundled-c-library-1">Compile and link statically to a bundled C++ library</a></td><td><a href="https://docs.rs/cc"><img src="https://badge-cache.kominick.com/crates/v/cc.svg?label=cc" alt="cc-badge" /></a></td><td><a href="https://crates.io/categories/development-tools"><img src="https://badge-cache.kominick.com/badge/development_tools--x.svg?style=social" alt="cat-development-tools-badge" /></a></td></tr>
<tr><td><a href="development_tools/build_tools.html#compile-a-c-library-while-setting-custom-defines">Compile a C library while setting custom defines</a></td><td><a href="https://docs.rs/cc"><img src="https://badge-cache.kominick.com/crates/v/cc.svg?label=cc" alt="cc-badge" /></a></td><td><a href="https://crates.io/categories/development-tools"><img src="https://badge-cache.kominick.com/badge/development_tools--x.svg?style=social" alt="cat-development-tools-badge" /></a></td></tr>
</tbody></table>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#encoding" id="encoding">Encoding</a></h1>
<table><thead><tr><th>Recipe</th><th>Crates</th><th>Categories</th></tr></thead><tbody>
<tr><td><a href="encoding/strings.html#percent-encode-a-string">Percent-encode a string</a></td><td><a href="https://docs.rs/url/"><img src="https://badge-cache.kominick.com/crates/v/percent-encoding.svg?label=percent-encoding" alt="percent-encoding-badge" /></a></td><td><a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></td></tr>
<tr><td><a href="encoding/strings.html#encode-a-string-as-applicationx-www-form-urlencoded">Encode a string as application/x-www-form-urlencoded</a></td><td><a href="https://docs.rs/url/"><img src="https://badge-cache.kominick.com/crates/v/url.svg?label=url" alt="url-badge" /></a></td><td><a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></td></tr>
<tr><td><a href="encoding/strings.html#encode-and-decode-hex">Encode and decode hex</a></td><td><a href="https://docs.rs/data-encoding/"><img src="https://badge-cache.kominick.com/crates/v/data-encoding.svg?label=data-encoding" alt="data-encoding-badge" /></a></td><td><a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></td></tr>
<tr><td><a href="encoding/strings.html#encode-and-decode-base64">Encode and decode base64</a></td><td><a href="https://docs.rs/base64/"><img src="https://badge-cache.kominick.com/crates/v/base64.svg?label=base64" alt="base64-badge" /></a></td><td><a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></td></tr>
<tr><td><a href="encoding/csv.html#read-csv-records">Read CSV records</a></td><td><a href="https://docs.rs/csv/"><img src="https://badge-cache.kominick.com/crates/v/csv.svg?label=csv" alt="csv-badge" /></a></td><td><a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></td></tr>
<tr><td><a href="encoding/csv.html#read-csv-records-with-different-delimiter">Read CSV records with different delimiter</a></td><td><a href="https://docs.rs/csv/"><img src="https://badge-cache.kominick.com/crates/v/csv.svg?label=csv" alt="csv-badge" /></a></td><td><a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></td></tr>
<tr><td><a href="encoding/csv.html#filter-csv-records-matching-a-predicate">Filter CSV records matching a predicate</a></td><td><a href="https://docs.rs/csv/"><img src="https://badge-cache.kominick.com/crates/v/csv.svg?label=csv" alt="csv-badge" /></a></td><td><a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></td></tr>
<tr><td><a href="encoding/csv.html#handle-invalid-csv-data-with-serde">Handle invalid CSV data with Serde</a></td><td><a href="https://docs.rs/csv/"><img src="https://badge-cache.kominick.com/crates/v/csv.svg?label=csv" alt="csv-badge" /></a> <a href="https://docs.rs/serde/"><img src="https://badge-cache.kominick.com/crates/v/serde.svg?label=serde" alt="serde-badge" /></a></td><td><a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></td></tr>
<tr><td><a href="encoding/csv.html#serialize-records-to-csv">Serialize records to CSV</a></td><td><a href="https://docs.rs/csv/"><img src="https://badge-cache.kominick.com/crates/v/csv.svg?label=csv" alt="csv-badge" /></a></td><td><a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></td></tr>
<tr><td><a href="encoding/csv.html#serialize-records-to-csv-using-serde">Serialize records to CSV using Serde</a></td><td><a href="https://docs.rs/csv/"><img src="https://badge-cache.kominick.com/crates/v/csv.svg?label=csv" alt="csv-badge" /></a> <a href="https://docs.rs/serde/"><img src="https://badge-cache.kominick.com/crates/v/serde.svg?label=serde" alt="serde-badge" /></a></td><td><a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></td></tr>
<tr><td><a href="encoding/csv.html#transform-csv-column">Transform one column of a CSV file</a></td><td><a href="https://docs.rs/csv/"><img src="https://badge-cache.kominick.com/crates/v/csv.svg?label=csv" alt="csv-badge" /></a> <a href="https://docs.rs/serde/"><img src="https://badge-cache.kominick.com/crates/v/serde.svg?label=serde" alt="serde-badge" /></a></td><td><a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></td></tr>
<tr><td><a href="encoding/complex.html#serialize-and-deserialize-unstructured-json">Serialize and deserialize unstructured JSON</a></td><td><a href="https://docs.rs/serde_json/*/serde_json/"><img src="https://badge-cache.kominick.com/crates/v/serde_json.svg?label=serde_json" alt="serde-json-badge" /></a></td><td><a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></td></tr>
<tr><td><a href="encoding/complex.html#deserialize-a-toml-configuration-file">Deserialize a TOML configuration file</a></td><td><a href="https://docs.rs/toml/"><img src="https://badge-cache.kominick.com/crates/v/toml.svg?label=toml" alt="toml-badge" /></a></td><td><a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></td></tr>
<tr><td><a href="encoding/complex.html#read-and-write-integers-in-little-endian-byte-order">Read and write integers in little-endian byte order</a></td><td><a href="https://docs.rs/byteorder/"><img src="https://badge-cache.kominick.com/crates/v/byteorder.svg?label=byteorder" alt="byteorder-badge" /></a></td><td><a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></td></tr>
</tbody></table>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#file-system" id="file-system">File System</a></h1>
<table><thead><tr><th>Recipe</th><th>Crates</th><th>Categories</th></tr></thead><tbody>
<tr><td><a href="file/read-write.html#read-lines-of-strings-from-a-file">Read lines of strings from a file</a></td><td><a href="https://doc.rust-lang.org/std"><img src="https://badge-cache.kominick.com/badge/std-1.29.1-blue.svg" alt="std-badge" /></a></td><td><a href="https://crates.io/categories/filesystem"><img src="https://badge-cache.kominick.com/badge/filesystem--x.svg?style=social" alt="cat-filesystem-badge" /></a></td></tr>
<tr><td><a href="file/read-write.html#avoid-writing-and-reading-from-a-same-file">Avoid writing and reading from a same file</a></td><td><a href="https://docs.rs/same-file/"><img src="https://badge-cache.kominick.com/crates/v/same_file.svg?label=same_file" alt="same_file-badge" /></a></td><td><a href="https://crates.io/categories/filesystem"><img src="https://badge-cache.kominick.com/badge/filesystem--x.svg?style=social" alt="cat-filesystem-badge" /></a></td></tr>
<tr><td><a href="file/read-write.html#access-a-file-randomly-using-a-memory-map">Access a file randomly using a memory map</a></td><td><a href="https://docs.rs/memmap/"><img src="https://badge-cache.kominick.com/crates/v/memmap.svg?label=memmap" alt="memmap-badge" /></a></td><td><a href="https://crates.io/categories/filesystem"><img src="https://badge-cache.kominick.com/badge/filesystem--x.svg?style=social" alt="cat-filesystem-badge" /></a></td></tr>
<tr><td><a href="file/dir.html#file-names-that-have-been-modified-in-the-last-24-hours">File names that have been modified in the last 24 hours</a></td><td><a href="https://doc.rust-lang.org/std"><img src="https://badge-cache.kominick.com/badge/std-1.29.1-blue.svg" alt="std-badge" /></a></td><td><a href="https://crates.io/categories/filesystem"><img src="https://badge-cache.kominick.com/badge/filesystem--x.svg?style=social" alt="cat-filesystem-badge" /></a> <a href="https://crates.io/categories/os"><img src="https://badge-cache.kominick.com/badge/OS--x.svg?style=social" alt="cat-os-badge" /></a></td></tr>
<tr><td><a href="file/dir.html#find-loops-for-a-given-path">Find loops for a given path</a></td><td><a href="https://docs.rs/same-file/"><img src="https://badge-cache.kominick.com/crates/v/same_file.svg?label=same_file" alt="same_file-badge" /></a></td><td><a href="https://crates.io/categories/filesystem"><img src="https://badge-cache.kominick.com/badge/filesystem--x.svg?style=social" alt="cat-filesystem-badge" /></a></td></tr>
<tr><td><a href="file/dir.html#recursively-find-duplicate-file-names">Recursively find duplicate file names</a></td><td><a href="https://docs.rs/walkdir/"><img src="https://badge-cache.kominick.com/crates/v/walkdir.svg?label=walkdir" alt="walkdir-badge" /></a></td><td><a href="https://crates.io/categories/filesystem"><img src="https://badge-cache.kominick.com/badge/filesystem--x.svg?style=social" alt="cat-filesystem-badge" /></a></td></tr>
<tr><td><a href="file/dir.html#recursively-find-all-files-with-given-predicate">Recursively find all files with given predicate</a></td><td><a href="https://docs.rs/walkdir/"><img src="https://badge-cache.kominick.com/crates/v/walkdir.svg?label=walkdir" alt="walkdir-badge" /></a></td><td><a href="https://crates.io/categories/filesystem"><img src="https://badge-cache.kominick.com/badge/filesystem--x.svg?style=social" alt="cat-filesystem-badge" /></a></td></tr>
<tr><td><a href="file/dir.html#traverse-directories-while-skipping-dotfiles">Traverse directories while skipping dotfiles</a></td><td><a href="https://docs.rs/walkdir/"><img src="https://badge-cache.kominick.com/crates/v/walkdir.svg?label=walkdir" alt="walkdir-badge" /></a></td><td><a href="https://crates.io/categories/filesystem"><img src="https://badge-cache.kominick.com/badge/filesystem--x.svg?style=social" alt="cat-filesystem-badge" /></a></td></tr>
<tr><td><a href="file/dir.html#recursively-calculate-file-sizes-at-given-depth">Recursively calculate file sizes at given depth</a></td><td><a href="https://docs.rs/walkdir/"><img src="https://badge-cache.kominick.com/crates/v/walkdir.svg?label=walkdir" alt="walkdir-badge" /></a></td><td><a href="https://crates.io/categories/filesystem"><img src="https://badge-cache.kominick.com/badge/filesystem--x.svg?style=social" alt="cat-filesystem-badge" /></a></td></tr>
<tr><td><a href="file/dir.html#find-all-png-files-recursively">Find all png files recursively</a></td><td><a href="https://docs.rs/glob/"><img src="https://badge-cache.kominick.com/crates/v/glob.svg?label=glob" alt="glob-badge" /></a></td><td><a href="https://crates.io/categories/filesystem"><img src="https://badge-cache.kominick.com/badge/filesystem--x.svg?style=social" alt="cat-filesystem-badge" /></a></td></tr>
<tr><td><a href="file/dir.html#find-all-files-with-given-pattern-ignoring-filename-case">Find all files with given pattern ignoring filename case</a></td><td><a href="https://docs.rs/glob/"><img src="https://badge-cache.kominick.com/crates/v/glob.svg?label=glob" alt="glob-badge" /></a></td><td><a href="https://crates.io/categories/filesystem"><img src="https://badge-cache.kominick.com/badge/filesystem--x.svg?style=social" alt="cat-filesystem-badge" /></a></td></tr>
</tbody></table>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#hardware-support" id="hardware-support">Hardware Support</a></h1>
<table><thead><tr><th>Recipe</th><th>Crates</th><th>Categories</th></tr></thead><tbody>
<tr><td><a href="hardware/processor.html#check-number-of-logical-cpu-cores">Check number of logical cpu cores</a></td><td><a href="https://docs.rs/num_cpus/"><img src="https://badge-cache.kominick.com/crates/v/num_cpus.svg?label=num_cpus" alt="num_cpus-badge" /></a></td><td><a href="https://crates.io/categories/hardware-support"><img src="https://badge-cache.kominick.com/badge/hardware_support--x.svg?style=social" alt="cat-hardware-support-badge" /></a></td></tr>
</tbody></table>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#memory-management" id="memory-management">Memory Management</a></h1>
<table><thead><tr><th>Recipe</th><th>Crates</th><th>Categories</th></tr></thead><tbody>
<tr><td><a href="mem/global_static.html#declare-lazily-evaluated-constant">Declare lazily evaluated constant</a></td><td><a href="https://docs.rs/lazy_static/"><img src="https://badge-cache.kominick.com/crates/v/lazy_static.svg?label=lazy_static" alt="lazy_static-badge" /></a></td><td><a href="https://crates.io/categories/caching"><img src="https://badge-cache.kominick.com/badge/caching--x.svg?style=social" alt="cat-caching-badge" /></a> <a href="https://crates.io/categories/rust-patterns"><img src="https://badge-cache.kominick.com/badge/rust_patterns--x.svg?style=social" alt="cat-rust-patterns-badge" /></a></td></tr>
</tbody></table>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#networking" id="networking">Networking</a></h1>
<table><thead><tr><th>Recipe</th><th>Crates</th><th>Categories</th></tr></thead><tbody>
<tr><td><a href="net/server.html#listen-on-unused-port-tcpip">Listen on unused port TCP/IP</a></td><td><a href="https://doc.rust-lang.org/std"><img src="https://badge-cache.kominick.com/badge/std-1.29.1-blue.svg" alt="std-badge" /></a></td><td><a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a></td></tr>
</tbody></table>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#operating-system" id="operating-system">Operating System</a></h1>
<table><thead><tr><th>Recipe</th><th>Crates</th><th>Categories</th></tr></thead><tbody>
<tr><td><a href="os/external.html#run-an-external-command-and-process-stdout">Run an external command and process stdout</a></td><td><a href="https://docs.rs/regex/"><img src="https://badge-cache.kominick.com/crates/v/regex.svg?label=regex" alt="regex-badge" /></a></td><td><a href="https://crates.io/categories/os"><img src="https://badge-cache.kominick.com/badge/OS--x.svg?style=social" alt="cat-os-badge" /></a> <a href="https://crates.io/categories/text-processing"><img src="https://badge-cache.kominick.com/badge/text_processing--x.svg?style=social" alt="cat-text-processing-badge" /></a></td></tr>
<tr><td><a href="os/external.html#run-an-external-command-passing-it-stdin-and-check-for-an-error-code">Run an external command passing it stdin and check for an error code</a></td><td><a href="https://docs.rs/regex/"><img src="https://badge-cache.kominick.com/crates/v/regex.svg?label=regex" alt="regex-badge" /></a></td><td><a href="https://crates.io/categories/os"><img src="https://badge-cache.kominick.com/badge/OS--x.svg?style=social" alt="cat-os-badge" /></a> <a href="https://crates.io/categories/text-processing"><img src="https://badge-cache.kominick.com/badge/text_processing--x.svg?style=social" alt="cat-text-processing-badge" /></a></td></tr>
<tr><td><a href="os/external.html#run-piped-external-commands">Run piped external commands</a></td><td><a href="https://doc.rust-lang.org/std"><img src="https://badge-cache.kominick.com/badge/std-1.29.1-blue.svg" alt="std-badge" /></a></td><td><a href="https://crates.io/categories/os"><img src="https://badge-cache.kominick.com/badge/OS--x.svg?style=social" alt="cat-os-badge" /></a></td></tr>
<tr><td><a href="os/external.html#redirect-both-stdout-and-stderr-of-child-process-to-the-same-file">Redirect both stdout and stderr of child process to the same file</a></td><td><a href="https://doc.rust-lang.org/std"><img src="https://badge-cache.kominick.com/badge/std-1.29.1-blue.svg" alt="std-badge" /></a></td><td><a href="https://crates.io/categories/os"><img src="https://badge-cache.kominick.com/badge/OS--x.svg?style=social" alt="cat-os-badge" /></a></td></tr>
<tr><td><a href="os/external.html#continuously-process-child-process-outputs">Continuously process child process' outputs</a></td><td><a href="https://doc.rust-lang.org/std"><img src="https://badge-cache.kominick.com/badge/std-1.29.1-blue.svg" alt="std-badge" /></a></td><td><a href="https://crates.io/categories/os"><img src="https://badge-cache.kominick.com/badge/OS--x.svg?style=social" alt="cat-os-badge" /></a><a href="https://crates.io/categories/text-processing"><img src="https://badge-cache.kominick.com/badge/text_processing--x.svg?style=social" alt="cat-text-processing-badge" /></a></td></tr>
<tr><td><a href="os/external.html#read-environment-variable">Read environment variable</a></td><td><a href="https://doc.rust-lang.org/std"><img src="https://badge-cache.kominick.com/badge/std-1.29.1-blue.svg" alt="std-badge" /></a></td><td><a href="https://crates.io/categories/os"><img src="https://badge-cache.kominick.com/badge/OS--x.svg?style=social" alt="cat-os-badge" /></a></td></tr>
</tbody></table>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#science" id="science">Science</a></h1>
<h2><a class="header" href="#mathematics" id="mathematics">Mathematics</a></h2>
<table><thead><tr><th>Recipe</th><th>Crates</th><th>Categories</th></tr></thead><tbody>
<tr><td><a href="mathematics/linear_algebra.html#vector-norm">Vector Norm</a></td><td><a href="https://docs.rs/ndarray"><img src="https://badge-cache.kominick.com/crate/ndarray.svg?label=ndarray" alt="ndarray-badge" /></a></td><td><a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></td></tr>
<tr><td><a href="mathematics/linear_algebra.html#adding-matrices">Adding matrices</a></td><td><a href="https://docs.rs/ndarray"><img src="https://badge-cache.kominick.com/crate/ndarray.svg?label=ndarray" alt="ndarray-badge" /></a></td><td><a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></td></tr>
<tr><td><a href="mathematics/linear_algebra.html#multiplying-matrices">Multiplying matrices</a></td><td><a href="https://docs.rs/ndarray"><img src="https://badge-cache.kominick.com/crate/ndarray.svg?label=ndarray" alt="ndarray-badge" /></a></td><td><a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></td></tr>
<tr><td><a href="mathematics/linear_algebra.html#multiply-a-scalar-with-a-vector-with-a-matrix">Multiply a scalar with a vector with a matrix</a></td><td><a href="https://docs.rs/ndarray"><img src="https://badge-cache.kominick.com/crate/ndarray.svg?label=ndarray" alt="ndarray-badge" /></a></td><td><a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></td></tr>
<tr><td><a href="mathematics/linear_algebra.html#invert-matrix">Invert matrix</a></td><td><a href="https://docs.rs/nalgebra"><img src="https://badge-cache.kominick.com/crate/nalgebra.svg?label=nalgebra" alt="nalgebra-badge" /></a></td><td><a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></td></tr>
<tr><td><a href="mathematics/trigonometry.html#calculating-the-side-length-of-a-triangle">Calculating the side length of a triangle</a></td><td><a href="https://doc.rust-lang.org/std"><img src="https://badge-cache.kominick.com/badge/std-1.29.1-blue.svg" alt="std-badge" /></a></td><td><a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></td></tr>
<tr><td><a href="mathematics/trigonometry.html#verifying-tan-is-equal-to-sin-divided-by-cos">Verifying tan is equal to sin divided by cos</a></td><td><a href="https://doc.rust-lang.org/std"><img src="https://badge-cache.kominick.com/badge/std-1.29.1-blue.svg" alt="std-badge" /></a></td><td><a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></td></tr>
<tr><td><a href="mathematics/trigonometry.html#distance-between-two-points-on-the-earth">Distance between two points on the Earth</a></td><td><a href="https://doc.rust-lang.org/std"><img src="https://badge-cache.kominick.com/badge/std-1.29.1-blue.svg" alt="std-badge" /></a></td><td><a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></td></tr>
<tr><td><a href="mathematics/complex_numbers.html#creating-complex-numbers">Creating complex numbers</a></td><td><a href="https://docs.rs/num/"><img src="https://badge-cache.kominick.com/crates/v/num.svg?label=num" alt="num-badge" /></a></td><td><a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></td></tr>
<tr><td><a href="mathematics/complex_numbers.html#adding-complex-numbers">Adding complex numbers</a></td><td><a href="https://docs.rs/num/"><img src="https://badge-cache.kominick.com/crates/v/num.svg?label=num" alt="num-badge" /></a></td><td><a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></td></tr>
<tr><td><a href="mathematics/complex_numbers.html#mathematical-functions">Mathematical functions on complex numbers</a></td><td><a href="https://docs.rs/num/"><img src="https://badge-cache.kominick.com/crates/v/num.svg?label=num" alt="num-badge" /></a></td><td><a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></td></tr>
<tr><td><a href="mathematics/statistics.html#measures-of-central-tendency">Measures of central tendency</a></td><td><a href="https://doc.rust-lang.org/std"><img src="https://badge-cache.kominick.com/badge/std-1.29.1-blue.svg" alt="std-badge" /></a></td><td><a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></td></tr>
<tr><td><a href="mathematics/statistics.html#standard-deviation">Computing standard deviation</a></td><td><a href="https://doc.rust-lang.org/std"><img src="https://badge-cache.kominick.com/badge/std-1.29.1-blue.svg" alt="std-badge" /></a></td><td><a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></td></tr>
<tr><td><a href="mathematics/miscellaneous.html#big-integers">Big integers</a></td><td><a href="https://docs.rs/num/"><img src="https://badge-cache.kominick.com/crates/v/num.svg?label=num" alt="num-badge" /></a></td><td><a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></td></tr>
</tbody></table>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#text-processing" id="text-processing">Text Processing</a></h1>
<table><thead><tr><th>Recipe</th><th>Crates</th><th>Categories</th></tr></thead><tbody>
<tr><td><a href="text/string_parsing.html#collect-unicode-graphemes">Collect Unicode Graphemes</a></td><td><a href="https://docs.rs/unicode-segmentation/"><img src="https://badge-cache.kominick.com/crates/v/unicode-segmentation.svg?label=unicode-segmentation" alt="unicode-segmentation-badge" /></a></td><td><a href="https://crates.io/categories/text-processing"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></td></tr>
<tr><td><a href="text/regex.html#verify-and-extract-login-from-an-email-address">Verify and extract login from an email address</a></td><td><a href="https://docs.rs/regex/"><img src="https://badge-cache.kominick.com/crates/v/regex.svg?label=regex" alt="regex-badge" /></a> <a href="https://docs.rs/lazy_static/"><img src="https://badge-cache.kominick.com/crates/v/lazy_static.svg?label=lazy_static" alt="lazy_static-badge" /></a></td><td><a href="https://crates.io/categories/text-processing"><img src="https://badge-cache.kominick.com/badge/text_processing--x.svg?style=social" alt="cat-text-processing-badge" /></a></td></tr>
<tr><td><a href="text/regex.html#extract-a-list-of-unique-hashtags-from-a-text">Extract a list of unique #Hashtags from a text</a></td><td><a href="https://docs.rs/regex/"><img src="https://badge-cache.kominick.com/crates/v/regex.svg?label=regex" alt="regex-badge" /></a> <a href="https://docs.rs/lazy_static/"><img src="https://badge-cache.kominick.com/crates/v/lazy_static.svg?label=lazy_static" alt="lazy_static-badge" /></a></td><td><a href="https://crates.io/categories/text-processing"><img src="https://badge-cache.kominick.com/badge/text_processing--x.svg?style=social" alt="cat-text-processing-badge" /></a></td></tr>
<tr><td><a href="text/regex.html#extract-phone-numbers-from-text">Extract phone numbers from text</a></td><td><a href="https://docs.rs/regex/"><img src="https://badge-cache.kominick.com/crates/v/regex.svg?label=regex" alt="regex-badge" /></a></td><td><a href="https://crates.io/categories/text-processing"><img src="https://badge-cache.kominick.com/badge/text_processing--x.svg?style=social" alt="cat-text-processing-badge" /></a></td></tr>
<tr><td><a href="text/regex.html#filter-a-log-file-by-matching-multiple-regular-expressions">Filter a log file by matching multiple regular expressions</a></td><td><a href="https://docs.rs/regex/"><img src="https://badge-cache.kominick.com/crates/v/regex.svg?label=regex" alt="regex-badge" /></a></td><td><a href="https://crates.io/categories/text-processing"><img src="https://badge-cache.kominick.com/badge/text_processing--x.svg?style=social" alt="cat-text-processing-badge" /></a></td></tr>
<tr><td><a href="text/regex.html#replace-all-occurrences-of-one-text-pattern-with-another-pattern">Replace all occurrences of one text pattern with another pattern.</a></td><td><a href="https://docs.rs/regex/"><img src="https://badge-cache.kominick.com/crates/v/regex.svg?label=regex" alt="regex-badge" /></a> <a href="https://docs.rs/lazy_static/"><img src="https://badge-cache.kominick.com/crates/v/lazy_static.svg?label=lazy_static" alt="lazy_static-badge" /></a></td><td><a href="https://crates.io/categories/text-processing"><img src="https://badge-cache.kominick.com/badge/text_processing--x.svg?style=social" alt="cat-text-processing-badge" /></a></td></tr>
<tr><td><a href="text/string_parsing.html#implement-the-fromstr-trait-for-a-custom-struct">Implement the <code>FromStr</code> trait for a custom <code>struct</code></a></td><td><a href="https://doc.rust-lang.org/std"><img src="https://badge-cache.kominick.com/badge/std-1.29.1-blue.svg" alt="std-badge" /></a></td><td><a href="https://crates.io/categories/text-processing"><img src="https://badge-cache.kominick.com/badge/text_processing--x.svg?style=social" alt="cat-text-processing-badge" /></a></td></tr>
</tbody></table>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#web-programming" id="web-programming">Web Programming</a></h1>
<h2><a class="header" href="#scraping-web-pages" id="scraping-web-pages">Scraping Web Pages</a></h2>
<table><thead><tr><th>Recipe</th><th>Crates</th><th>Categories</th></tr></thead><tbody>
<tr><td><a href="web/scraping.html#extract-all-links-from-a-webpage-html">Extract all links from a webpage HTML</a></td><td><a href="https://docs.rs/reqwest/"><img src="https://badge-cache.kominick.com/crates/v/reqwest.svg?label=reqwest" alt="reqwest-badge" /></a> <a href="https://docs.rs/select/"><img src="https://badge-cache.kominick.com/crates/v/select.svg?label=select" alt="select-badge" /></a></td><td><a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a></td></tr>
<tr><td><a href="web/scraping.html#check-a-webpage-for-broken-links">Check webpage for broken links</a></td><td><a href="https://docs.rs/reqwest/"><img src="https://badge-cache.kominick.com/crates/v/reqwest.svg?label=reqwest" alt="reqwest-badge" /></a> <a href="https://docs.rs/select/"><img src="https://badge-cache.kominick.com/crates/v/select.svg?label=select" alt="select-badge" /></a> <a href="https://docs.rs/url/"><img src="https://badge-cache.kominick.com/crates/v/url.svg?label=url" alt="url-badge" /></a></td><td><a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a></td></tr>
<tr><td><a href="web/scraping.html#extract-all-unique-links-from-a-mediawiki-markup">Extract all unique links from a MediaWiki markup</a></td><td><a href="https://docs.rs/reqwest/"><img src="https://badge-cache.kominick.com/crates/v/reqwest.svg?label=reqwest" alt="reqwest-badge" /></a> <a href="https://docs.rs/regex/"><img src="https://badge-cache.kominick.com/crates/v/regex.svg?label=regex" alt="regex-badge" /></a></td><td><a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a></td></tr>
</tbody></table>
<h2><a class="header" href="#uniform-resource-locations-url" id="uniform-resource-locations-url">Uniform Resource Locations (URL)</a></h2>
<table><thead><tr><th>Recipe</th><th>Crates</th><th>Categories</th></tr></thead><tbody>
<tr><td><a href="web/url.html#parse-a-url-from-a-string-to-a-url-type">Parse a URL from a string to a <code>Url</code> type</a></td><td><a href="https://docs.rs/url/"><img src="https://badge-cache.kominick.com/crates/v/url.svg?label=url" alt="url-badge" /></a></td><td><a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a></td></tr>
<tr><td><a href="web/url.html#create-a-base-url-by-removing-path-segments">Create a base URL by removing path segments</a></td><td><a href="https://docs.rs/url/"><img src="https://badge-cache.kominick.com/crates/v/url.svg?label=url" alt="url-badge" /></a></td><td><a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a></td></tr>
<tr><td><a href="web/url.html#create-new-urls-from-a-base-url">Create new URLs from a base URL</a></td><td><a href="https://docs.rs/url/"><img src="https://badge-cache.kominick.com/crates/v/url.svg?label=url" alt="url-badge" /></a></td><td><a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a></td></tr>
<tr><td><a href="web/url.html#extract-the-url-origin-scheme--host--port">Extract the URL origin (scheme / host / port)</a></td><td><a href="https://docs.rs/url/"><img src="https://badge-cache.kominick.com/crates/v/url.svg?label=url" alt="url-badge" /></a></td><td><a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a></td></tr>
<tr><td><a href="web/url.html#remove-fragment-identifiers-and-query-pairs-from-a-url">Remove fragment identifiers and query pairs from a URL</a></td><td><a href="https://docs.rs/url/"><img src="https://badge-cache.kominick.com/crates/v/url.svg?label=url" alt="url-badge" /></a></td><td><a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a></td></tr>
</tbody></table>
<h2><a class="header" href="#media-types-mime" id="media-types-mime">Media Types (MIME)</a></h2>
<table><thead><tr><th>Recipe</th><th>Crates</th><th>Categories</th></tr></thead><tbody>
<tr><td><a href="web/mime.html#get-mime-type-from-string">Get MIME type from string</a></td><td><a href="https://docs.rs/mime/"><img src="https://badge-cache.kominick.com/crates/v/csv.svg?label=mime" alt="mime-badge" /></a></td><td><a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></td></tr>
<tr><td><a href="web/mime.html#get-mime-type-from-filename">Get MIME type from filename</a></td><td><a href="https://docs.rs/mime/"><img src="https://badge-cache.kominick.com/crates/v/csv.svg?label=mime" alt="mime-badge" /></a></td><td><a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></td></tr>
<tr><td><a href="web/mime.html#parse-the-mime-type-of-a-http-response">Parse the MIME type of a HTTP response</a></td><td><a href="https://docs.rs/mime/"><img src="https://badge-cache.kominick.com/crates/v/csv.svg?label=mime" alt="mime-badge" /></a> <a href="https://docs.rs/reqwest/"><img src="https://badge-cache.kominick.com/crates/v/reqwest.svg?label=reqwest" alt="reqwest-badge" /></a></td><td><a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a> <a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></td></tr>
</tbody></table>
<h2><a class="header" href="#clients" id="clients">Clients</a></h2>
<table><thead><tr><th>Recipe</th><th>Crates</th><th>Categories</th></tr></thead><tbody>
<tr><td><a href="web/clients/requests.html#make-a-http-get-request">Make a HTTP GET request</a></td><td><a href="https://docs.rs/reqwest/"><img src="https://badge-cache.kominick.com/crates/v/reqwest.svg?label=reqwest" alt="reqwest-badge" /></a></td><td><a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a></td></tr>
<tr><td><a href="web/clients/apis.html#query-the-github-api">Query the GitHub API</a></td><td><a href="https://docs.rs/reqwest/"><img src="https://badge-cache.kominick.com/crates/v/reqwest.svg?label=reqwest" alt="reqwest-badge" /></a> <a href="https://docs.rs/serde/"><img src="https://badge-cache.kominick.com/crates/v/serde.svg?label=serde" alt="serde-badge" /></a></td><td><a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a> <a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></td></tr>
<tr><td><a href="web/clients/apis.html#check-if-an-api-resource-exists">Check if an API resource exists</a></td><td><a href="https://docs.rs/reqwest/"><img src="https://badge-cache.kominick.com/crates/v/reqwest.svg?label=reqwest" alt="reqwest-badge" /></a></td><td><a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a></td></tr>
<tr><td><a href="web/clients/apis.html#create-and-delete-gist-with-github-api">Create and delete Gist with GitHub API</a></td><td><a href="https://docs.rs/reqwest/"><img src="https://badge-cache.kominick.com/crates/v/reqwest.svg?label=reqwest" alt="reqwest-badge" /></a> <a href="https://docs.rs/serde/"><img src="https://badge-cache.kominick.com/crates/v/serde.svg?label=serde" alt="serde-badge" /></a></td><td><a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a> <a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></td></tr>
<tr><td><a href="web/clients/apis.html#consume-a-paginated-restful-api">Consume a paginated RESTful API</a></td><td><a href="https://docs.rs/reqwest/"><img src="https://badge-cache.kominick.com/crates/v/reqwest.svg?label=reqwest" alt="reqwest-badge" /></a> <a href="https://docs.rs/serde/"><img src="https://badge-cache.kominick.com/crates/v/serde.svg?label=serde" alt="serde-badge" /></a></td><td><a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a> <a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></td></tr>
<tr><td><a href="web/clients/download.html#download-a-file-to-a-temporary-directory">Download a file to a temporary directory</a></td><td><a href="https://docs.rs/reqwest/"><img src="https://badge-cache.kominick.com/crates/v/reqwest.svg?label=reqwest" alt="reqwest-badge" /></a> <a href="https://docs.rs/tempdir/"><img src="https://badge-cache.kominick.com/crates/v/tempdir.svg?label=tempdir" alt="tempdir-badge" /></a></td><td><a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a> <a href="https://crates.io/categories/filesystem"><img src="https://badge-cache.kominick.com/badge/filesystem--x.svg?style=social" alt="cat-filesystem-badge" /></a></td></tr>
<tr><td><a href="web/clients/download.html#make-a-partial-download-with-http-range-headers">Make a partial download with HTTP range headers</a></td><td><a href="https://docs.rs/reqwest/"><img src="https://badge-cache.kominick.com/crates/v/reqwest.svg?label=reqwest" alt="reqwest-badge" /></a></td><td><a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a></td></tr>
<tr><td><a href="web/clients/download.html#post-a-file-to-paste-rs">POST a file to paste-rs</a></td><td><a href="https://docs.rs/reqwest/"><img src="https://badge-cache.kominick.com/crates/v/reqwest.svg?label=reqwest" alt="reqwest-badge" /></a></td><td><a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a></td></tr>
</tbody></table>
<h2><a class="header" href="#web-authentication" id="web-authentication">Web Authentication</a></h2>
<table><thead><tr><th>Recipe</th><th>Crates</th><th>Categories</th></tr></thead><tbody>
<tr><td><a href="web/clients/authentication.html#basic-authentication">Basic Authentication</a></td><td><a href="https://docs.rs/reqwest/"><img src="https://badge-cache.kominick.com/crates/v/reqwest.svg?label=reqwest" alt="reqwest-badge" /></a></td><td><a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a></td></tr>
</tbody></table>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#about-cookin-with-rust" id="about-cookin-with-rust">About &quot;Cookin' with Rust&quot;</a></h1>
<h2><a class="header" href="#table-of-contents" id="table-of-contents">Table of contents</a></h2>
<ul>
<li><a href="about.html#who-this-book-is-for">Who this book is for</a></li>
<li><a href="about.html#how-to-read-this-book">How to read this book</a></li>
<li><a href="about.html#how-to-use-the-recipes">How to use the recipes</a></li>
<li><a href="about.html#a-note-about-error-handling">A note about error handling</a></li>
<li><a href="about.html#a-note-about-crate-representation">A note about crate representation</a></li>
</ul>
<h2><a class="header" href="#who-this-book-is-for" id="who-this-book-is-for">Who this book is for</a></h2>
<p>This cookbook is intended for new Rust programmers, so that they may
quickly get an overview of the capabilities of the Rust crate
ecosystem. It is also intended for experienced Rust programmers, who
should find in the recipes an easy reminder of how to accomplish
common tasks.</p>
<h2><a class="header" href="#how-to-read-this-book" id="how-to-read-this-book">How to read this book</a></h2>
<p>The cookbook <a href="intro.html">index</a> contains the full list of recipes, organized into
a number of sections: &quot;basics&quot;, &quot;encoding&quot;, &quot;concurrency&quot;, etc. The
sections themselves are more or less ordered in progression, with
later sections being more advanced, and occasionally building on
concepts from earlier sections.</p>
<p>Within the index, each section contains a list of recipes. The recipes
are simple statements of a task to accomplish, like &quot;generate random
numbers in a range&quot;; and each recipe is tagged with badges indicating
which <em>crates</em> they use, like <a href="https://docs.rs/rand/"><img src="https://badge-cache.kominick.com/crates/v/rand.svg?label=rand" alt="rand-badge" /></a>, and which
categories on <a href="https://crates.io">crates.io</a> those crates belong to, like
<a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a>.</p>
<p>New Rust programmers should be comfortable reading from the first
section to the last, and doing so should give one a strong overview of
the crate ecosystem. Click on the section header in the index, or in
the sidebar to navigate to the page for that section of the book.</p>
<p>If you are simply looking for the solution to a simple task, the
cookbook is today more difficult to navigate. The easiest way to find
a specific recipe is to scan the index looking for the crates and
categories one is interested in. From there, click on the name of the
recipe to view it. This will improve in the future.</p>
<h2><a class="header" href="#how-to-use-the-recipes" id="how-to-use-the-recipes">How to use the recipes</a></h2>
<p>Recipes are designed to give you instant access to working code, along
with a full explanation of what it is doing, and to guide you to
further information.</p>
<p>All recipes in the cookbook are full, self contained programs, so
that they may be copied directly into your own projects for
experimentation. To do so follow the instructions below.</p>
<p>Consider this example for &quot;generate random numbers within a range&quot;:</p>
<p><a href="https://docs.rs/rand/"><img src="https://badge-cache.kominick.com/crates/v/rand.svg?label=rand" alt="rand-badge" /></a> <a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></p>
<pre><pre class="playground"><code class="language-rust edition2018">use rand::Rng;
fn main() {
let mut rng = rand::thread_rng();
println!(&quot;Random f64: {}&quot;, rng.gen::&lt;f64&gt;());
}
</code></pre></pre>
<p>To work with it locally we can run the following commands to create
a new cargo project, and change to that directory:</p>
<pre><code class="language-sh">cargo new my-example --bin
cd my-example
</code></pre>
<p>Now, we also need to add the necessary crates to <a href="http://doc.crates.io/manifest.html">Cargo.toml</a>, as
indicated by the crate badges, in this case just &quot;rand&quot;. To do so,
we'll use the <code>cargo add</code> command, which is provided by the
<a href="https://github.com/killercup/cargo-edit"><code>cargo-edit</code></a> crate, which we need to install first:</p>
<pre><code class="language-sh">cargo install cargo-edit
cargo add rand
</code></pre>
<p>Now you can replace <code>src/main.rs</code> with the full contents of the
example and run it:</p>
<pre><code class="language-sh">cargo run
</code></pre>
<p>The crate badges that accompany the examples link to the crates' full
documentation on <a href="https://docs.rs">docs.rs</a>, and is often the next documentation you
should read after deciding which crate suites your purpose.</p>
<h2><a class="header" href="#a-note-about-error-handling" id="a-note-about-error-handling">A note about error handling</a></h2>
<p>Error handling in Rust is robust when done correctly, but in today's
Rust it requires a fair bit of boilerplate. Because of this one often
sees Rust examples filled with <code>unwrap</code> calls instead of proper error
handling.</p>
<p>Since these recipes are intended to be reused as-is and encourage best
practices, they set up error handling correctly when there are
<code>Result</code> types involved.</p>
<p>The basic pattern we use is to have a <code>fn main() -&gt; Result</code>.</p>
<p>The structure generally looks like:</p>
<pre><pre class="playground"><code class="language-rust edition2018">use error_chain::error_chain;
use std::net::IpAddr;
use std::str;
error_chain! {
foreign_links {
Utf8(std::str::Utf8Error);
AddrParse(std::net::AddrParseError);
}
}
fn main() -&gt; Result&lt;()&gt; {
let bytes = b&quot;2001:db8::1&quot;;
// Bytes to string.
let s = str::from_utf8(bytes)?;
// String to IP address.
let addr: IpAddr = s.parse()?;
println!(&quot;{:?}&quot;, addr);
Ok(())
}
</code></pre></pre>
<p>This is using the <code>error_chain!</code> macro to define a custom <code>Error</code> and
<code>Result</code> type, along with automatic conversions from two standard
library error types. The automatic conversions make the <code>?</code> operator
work.</p>
<p>For the sake of readability error handling boilerplate is hidden by
default like below. In order to read full contents click on the
&quot;expand&quot; (<i class="fa fa-expand"></i>) button located in the top
right corner of the snippet.</p>
<pre><pre class="playground"><code class="language-rust edition2018"><span class="boring">use error_chain::error_chain;
</span>
use url::{Url, Position};
<span class="boring">
</span><span class="boring">error_chain! {
</span><span class="boring"> foreign_links {
</span><span class="boring"> UrlParse(url::ParseError);
</span><span class="boring"> }
</span><span class="boring">}
</span>
fn main() -&gt; Result&lt;()&gt; {
let parsed = Url::parse(&quot;https://httpbin.org/cookies/set?k2=v2&amp;k1=v1&quot;)?;
let cleaned: &amp;str = &amp;parsed[..Position::AfterPath];
println!(&quot;cleaned: {}&quot;, cleaned);
Ok(())
}
</code></pre></pre>
<p>For more background on error handling in Rust, read <a href="https://doc.rust-lang.org/book/error-handling.html">this page of the
Rust book</a> and <a href="https://brson.github.io/2016/11/30/starting-with-error-chain">this blog post</a>.</p>
<h2><a class="header" href="#a-note-about-crate-representation" id="a-note-about-crate-representation">A note about crate representation</a></h2>
<p>This cookbook is intended eventually to provide expansive coverage of
the Rust crate ecosystem, but today is limited in scope while we get
it bootstrapped and work on the presentation. Hopefully, starting
from a small scope and slowly expanding will help the cookbook become
a high-quality resource sooner, and allow it to maintain consistent
quality levels as it grows.</p>
<p>At present the cookbook is focused on the standard library, and on
&quot;core&quot;, or &quot;foundational&quot;, crates—those crates that make up the most
common programming tasks, and that the rest of the ecosystem builds
off of.</p>
<p>The cookbook is closely tied to the <a href="https://internals.rust-lang.org/t/rust-libz-blitz/5184">Rust Libz Blitz</a>, a project to
identify, and improve the quality of such crates, and so it largely
defers crate selection to that project. Any crates that have already
been evaluated as part of that process are in scope for the cookbook,
as are crates that are pending evaluation.</p>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#algorithms-1" id="algorithms-1">Algorithms</a></h1>
<table><thead><tr><th>Recipe</th><th>Crates</th><th>Categories</th></tr></thead><tbody>
<tr><td><a href="algorithms/randomness.html#generate-random-numbers">Generate random numbers</a></td><td><a href="https://docs.rs/rand/"><img src="https://badge-cache.kominick.com/crates/v/rand.svg?label=rand" alt="rand-badge" /></a></td><td><a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></td></tr>
<tr><td><a href="algorithms/randomness.html#generate-random-numbers-within-a-range">Generate random numbers within a range</a></td><td><a href="https://docs.rs/rand/"><img src="https://badge-cache.kominick.com/crates/v/rand.svg?label=rand" alt="rand-badge" /></a></td><td><a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></td></tr>
<tr><td><a href="algorithms/randomness.html#generate-random-numbers-with-given-distribution">Generate random numbers with given distribution</a></td><td><a href="https://docs.rs/rand/"><img src="https://badge-cache.kominick.com/crates/v/rand.svg?label=rand" alt="rand-badge" /></a> <a href="https://docs.rs/rand_distr/"><img src="https://badge-cache.kominick.com/crates/v/rand.svg?label=rand_distr" alt="rand_distr-badge" /></a></td><td><a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></td></tr>
<tr><td><a href="algorithms/randomness.html#generate-random-values-of-a-custom-type">Generate random values of a custom type</a></td><td><a href="https://docs.rs/rand/"><img src="https://badge-cache.kominick.com/crates/v/rand.svg?label=rand" alt="rand-badge" /></a></td><td><a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></td></tr>
<tr><td><a href="algorithms/randomness.html#create-random-passwords-from-a-set-of-alphanumeric-characters">Create random passwords from a set of alphanumeric characters</a></td><td><a href="https://docs.rs/rand/"><img src="https://badge-cache.kominick.com/crates/v/rand.svg?label=rand" alt="rand-badge" /></a></td><td><a href="https://crates.io/categories/os"><img src="https://badge-cache.kominick.com/badge/OS--x.svg?style=social" alt="cat-os-badge" /></a></td></tr>
<tr><td><a href="algorithms/randomness.html#create-random-passwords-from-a-set-of-user-defined-characters">Create random passwords from a set of user-defined characters</a></td><td><a href="https://docs.rs/rand/"><img src="https://badge-cache.kominick.com/crates/v/rand.svg?label=rand" alt="rand-badge" /></a></td><td><a href="https://crates.io/categories/os"><img src="https://badge-cache.kominick.com/badge/OS--x.svg?style=social" alt="cat-os-badge" /></a></td></tr>
<tr><td><a href="algorithms/sorting.html#sort-a-vector-of-integers">Sort a Vector of Integers</a></td><td><a href="https://doc.rust-lang.org/std"><img src="https://badge-cache.kominick.com/badge/std-1.29.1-blue.svg" alt="std-badge" /></a></td><td><a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></td></tr>
<tr><td><a href="algorithms/sorting.html#sort-a-vector-of-floats">Sort a Vector of Floats</a></td><td><a href="https://doc.rust-lang.org/std"><img src="https://badge-cache.kominick.com/badge/std-1.29.1-blue.svg" alt="std-badge" /></a></td><td><a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></td></tr>
<tr><td><a href="algorithms/sorting.html#sort-a-vector-of-structs">Sort a Vector of Structs</a></td><td><a href="https://doc.rust-lang.org/std"><img src="https://badge-cache.kominick.com/badge/std-1.29.1-blue.svg" alt="std-badge" /></a></td><td><a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></td></tr>
</tbody></table>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#generate-random-values" id="generate-random-values">Generate Random Values</a></h1>
<h2><a class="header" href="#generate-random-numbers" id="generate-random-numbers">Generate random numbers</a></h2>
<p><a href="https://docs.rs/rand/"><img src="https://badge-cache.kominick.com/crates/v/rand.svg?label=rand" alt="rand-badge" /></a> <a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></p>
<p>Generates random numbers with help of random-number
generator <a href="https://docs.rs/rand/*/rand/trait.Rng.html"><code>rand::Rng</code></a> obtained via <a href="https://docs.rs/rand/*/rand/fn.thread_rng.html"><code>rand::thread_rng</code></a>. Each thread has an
initialized generator. Integers are uniformly distributed over the range of the
type, and floating point numbers are uniformly distributed from 0 up to but not
including 1.</p>
<pre><pre class="playground"><code class="language-rust edition2018">use rand::Rng;
fn main() {
let mut rng = rand::thread_rng();
let n1: u8 = rng.gen();
let n2: u16 = rng.gen();
println!(&quot;Random u8: {}&quot;, n1);
println!(&quot;Random u16: {}&quot;, n2);
println!(&quot;Random u32: {}&quot;, rng.gen::&lt;u32&gt;());
println!(&quot;Random i32: {}&quot;, rng.gen::&lt;i32&gt;());
println!(&quot;Random float: {}&quot;, rng.gen::&lt;f64&gt;());
}
</code></pre></pre>
<h2><a class="header" href="#generate-random-numbers-within-a-range" id="generate-random-numbers-within-a-range">Generate random numbers within a range</a></h2>
<p><a href="https://docs.rs/rand/"><img src="https://badge-cache.kominick.com/crates/v/rand.svg?label=rand" alt="rand-badge" /></a> <a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></p>
<p>Generates a random value within half-open <code>[0, 10)</code> range (not including <code>10</code>) with <a href="https://doc.rust-lang.org/rand/*/rand/trait.Rng.html#method.gen_range"><code>Rng::gen_range</code></a>.</p>
<pre><pre class="playground"><code class="language-rust edition2018">use rand::Rng;
fn main() {
let mut rng = rand::thread_rng();
println!(&quot;Integer: {}&quot;, rng.gen_range(0..10));
println!(&quot;Float: {}&quot;, rng.gen_range(0.0..10.0));
}
</code></pre></pre>
<p><a href="https://docs.rs/rand/*/rand/distributions/uniform/struct.Uniform.html"><code>Uniform</code></a> can obtain values with <a href="https://en.wikipedia.org/wiki/Uniform_distribution_(continuous)">uniform distribution</a>.
This has the same effect, but may be faster when repeatedly generating numbers
in the same range.</p>
<pre><pre class="playground"><code class="language-rust edition2018">
use rand::distributions::{Distribution, Uniform};
fn main() {
let mut rng = rand::thread_rng();
let die = Uniform::from(1..7);
loop {
let throw = die.sample(&amp;mut rng);
println!(&quot;Roll the die: {}&quot;, throw);
if throw == 6 {
break;
}
}
}
</code></pre></pre>
<h2><a class="header" href="#generate-random-numbers-with-given-distribution" id="generate-random-numbers-with-given-distribution">Generate random numbers with given distribution</a></h2>
<p><a href="https://docs.rs/rand_distr/"><img src="https://badge-cache.kominick.com/crates/v/rand.svg?label=rand_distr" alt="rand_distr-badge" /></a> <a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></p>
<p>By default, random numbers in the <code>rand</code> crate have
<a href="https://en.wikipedia.org/wiki/Uniform_distribution_(continuous)">uniform distribution</a>. The <a href="https://docs.rs/rand_distr/*/rand_distr/index.html"><code>rand_distr</code></a> crate provides
other kinds of distributions. To use them, you instantiate
a distribution, then sample from that distribution using
<a href="https://docs.rs/rand/*/rand/distributions/trait.Distribution.html#tymethod.sample"><code>Distribution::sample</code></a> with help of a random-number
generator <a href="https://docs.rs/rand/*/rand/trait.Rng.html"><code>rand::Rng</code></a>.</p>
<p>The <a href="https://docs.rs/rand_distr/*/rand_distr/index.html">distributions available are documented here</a>.
An example using the <a href="https://docs.rs/rand_distr/*/rand_distr/struct.Normal.html"><code>Normal</code></a> distribution is shown below.</p>
<pre><code class="language-rust edition2018 ignore">use rand_distr::{Distribution, Normal, NormalError};
use rand::thread_rng;
fn main() -&gt; Result&lt;(), NormalError&gt; {
let mut rng = thread_rng();
let normal = Normal::new(2.0, 3.0)?;
let v = normal.sample(&amp;mut rng);
println!(&quot;{} is from a N(2, 9) distribution&quot;, v);
Ok(())
}
</code></pre>
<h2><a class="header" href="#generate-random-values-of-a-custom-type" id="generate-random-values-of-a-custom-type">Generate random values of a custom type</a></h2>
<p><a href="https://docs.rs/rand/"><img src="https://badge-cache.kominick.com/crates/v/rand.svg?label=rand" alt="rand-badge" /></a> <a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></p>
<p>Randomly generates a tuple <code>(i32, bool, f64)</code> and variable of user defined type <code>Point</code>.
Implements the <a href="https://docs.rs/rand/*/rand/distributions/trait.Distribution.html"><code>Distribution</code></a> trait on type Point for <a href="https://docs.rs/rand/*/rand/distributions/struct.Standard.html"><code>Standard</code></a> in order to allow random generation.</p>
<pre><pre class="playground"><code class="language-rust edition2018">use rand::Rng;
use rand::distributions::{Distribution, Standard};
#[derive(Debug)]
struct Point {
x: i32,
y: i32,
}
impl Distribution&lt;Point&gt; for Standard {
fn sample&lt;R: Rng + ?Sized&gt;(&amp;self, rng: &amp;mut R) -&gt; Point {
let (rand_x, rand_y) = rng.gen();
Point {
x: rand_x,
y: rand_y,
}
}
}
fn main() {
let mut rng = rand::thread_rng();
let rand_tuple = rng.gen::&lt;(i32, bool, f64)&gt;();
let rand_point: Point = rng.gen();
println!(&quot;Random tuple: {:?}&quot;, rand_tuple);
println!(&quot;Random Point: {:?}&quot;, rand_point);
}
</code></pre></pre>
<h2><a class="header" href="#create-random-passwords-from-a-set-of-alphanumeric-characters" id="create-random-passwords-from-a-set-of-alphanumeric-characters">Create random passwords from a set of alphanumeric characters</a></h2>
<p><a href="https://docs.rs/rand/"><img src="https://badge-cache.kominick.com/crates/v/rand.svg?label=rand" alt="rand-badge" /></a> <a href="https://crates.io/categories/os"><img src="https://badge-cache.kominick.com/badge/OS--x.svg?style=social" alt="cat-os-badge" /></a></p>
<p>Randomly generates a string of given length ASCII characters in the range <code>A-Z, a-z, 0-9</code>, with <a href="https://docs.rs/rand/*/rand/distributions/struct.Alphanumeric.html"><code>Alphanumeric</code></a> sample.</p>
<pre><pre class="playground"><code class="language-rust edition2018">use rand::{thread_rng, Rng};
use rand::distributions::Alphanumeric;
fn main() {
let rand_string: String = thread_rng()
.sample_iter(&amp;Alphanumeric)
.take(30)
.map(char::from)
.collect();
println!(&quot;{}&quot;, rand_string);
}
</code></pre></pre>
<h2><a class="header" href="#create-random-passwords-from-a-set-of-user-defined-characters" id="create-random-passwords-from-a-set-of-user-defined-characters">Create random passwords from a set of user-defined characters</a></h2>
<p><a href="https://docs.rs/rand/"><img src="https://badge-cache.kominick.com/crates/v/rand.svg?label=rand" alt="rand-badge" /></a> <a href="https://crates.io/categories/os"><img src="https://badge-cache.kominick.com/badge/OS--x.svg?style=social" alt="cat-os-badge" /></a></p>
<p>Randomly generates a string of given length ASCII characters with custom
user-defined bytestring, with <a href="https://docs.rs/rand/*/rand/trait.Rng.html#method.gen_range"><code>gen_range</code></a>.</p>
<pre><pre class="playground"><code class="language-rust edition2018">fn main() {
use rand::Rng;
const CHARSET: &amp;[u8] = b&quot;ABCDEFGHIJKLMNOPQRSTUVWXYZ\
abcdefghijklmnopqrstuvwxyz\
0123456789)(*&amp;^%$#@!~&quot;;
const PASSWORD_LEN: usize = 30;
let mut rng = rand::thread_rng();
let password: String = (0..PASSWORD_LEN)
.map(|_| {
let idx = rng.gen_range(0..CHARSET.len());
CHARSET[idx] as char
})
.collect();
println!(&quot;{:?}&quot;, password);
}
</code></pre></pre>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#sorting-vectors" id="sorting-vectors">Sorting Vectors</a></h1>
<h2><a class="header" href="#sort-a-vector-of-integers" id="sort-a-vector-of-integers">Sort a Vector of Integers</a></h2>
<p><a href="https://doc.rust-lang.org/std"><img src="https://badge-cache.kominick.com/badge/std-1.29.1-blue.svg" alt="std-badge" /></a> <a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></p>
<p>This example sorts a Vector of integers via <a href="https://doc.rust-lang.org/std/vec/struct.Vec.html#method.sort"><code>vec::sort</code></a>. Alternative would
be to use <a href="https://doc.rust-lang.org/std/vec/struct.Vec.html#method.sort_unstable"><code>vec::sort_unstable</code></a> which can be faster, but does not preserve
the order of equal elements.</p>
<pre><pre class="playground"><code class="language-rust edition2018">fn main() {
let mut vec = vec![1, 5, 10, 2, 15];
vec.sort();
assert_eq!(vec, vec![1, 2, 5, 10, 15]);
}
</code></pre></pre>
<h2><a class="header" href="#sort-a-vector-of-floats" id="sort-a-vector-of-floats">Sort a Vector of Floats</a></h2>
<p><a href="https://doc.rust-lang.org/std"><img src="https://badge-cache.kominick.com/badge/std-1.29.1-blue.svg" alt="std-badge" /></a> <a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></p>
<p>A Vector of f32 or f64 can be sorted with <a href="https://doc.rust-lang.org/std/primitive.slice.html#method.sort_by"><code>vec::sort_by</code></a> and <a href="https://doc.rust-lang.org/std/cmp/trait.PartialOrd.html#tymethod.partial_cmp"><code>PartialOrd::partial_cmp</code></a>.</p>
<pre><pre class="playground"><code class="language-rust edition2018">fn main() {
let mut vec = vec![1.1, 1.15, 5.5, 1.123, 2.0];
vec.sort_by(|a, b| a.partial_cmp(b).unwrap());
assert_eq!(vec, vec![1.1, 1.123, 1.15, 2.0, 5.5]);
}
</code></pre></pre>
<h2><a class="header" href="#sort-a-vector-of-structs" id="sort-a-vector-of-structs">Sort a Vector of Structs</a></h2>
<p><a href="https://doc.rust-lang.org/std"><img src="https://badge-cache.kominick.com/badge/std-1.29.1-blue.svg" alt="std-badge" /></a> <a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></p>
<p>Sorts a Vector of Person structs with properties <code>name</code> and <code>age</code> by its natural
order (By name and age). In order to make Person sortable you need four traits <a href="https://doc.rust-lang.org/std/cmp/trait.Eq.html"><code>Eq</code></a>,
<a href="https://doc.rust-lang.org/std/cmp/trait.PartialEq.html"><code>PartialEq</code></a>, <a href="https://doc.rust-lang.org/std/cmp/trait.Ord.html"><code>Ord</code></a> and <a href="https://doc.rust-lang.org/std/cmp/trait.PartialOrd.html"><code>PartialOrd</code></a>. These traits can be simply derived.
You can also provide a custom comparator function using a <a href="https://doc.rust-lang.org/std/vec/struct.Vec.html#method.sort_by"><code>vec:sort_by</code></a> method and sort only by age.</p>
<pre><pre class="playground"><code class="language-rust edition2018">#[derive(Debug, Eq, Ord, PartialEq, PartialOrd)]
struct Person {
name: String,
age: u32
}
impl Person {
pub fn new(name: String, age: u32) -&gt; Self {
Person {
name,
age
}
}
}
fn main() {
let mut people = vec![
Person::new(&quot;Zoe&quot;.to_string(), 25),
Person::new(&quot;Al&quot;.to_string(), 60),
Person::new(&quot;John&quot;.to_string(), 1),
];
// Sort people by derived natural order (Name and age)
people.sort();
assert_eq!(
people,
vec![
Person::new(&quot;Al&quot;.to_string(), 60),
Person::new(&quot;John&quot;.to_string(), 1),
Person::new(&quot;Zoe&quot;.to_string(), 25),
]);
// Sort people by age
people.sort_by(|a, b| b.age.cmp(&amp;a.age));
assert_eq!(
people,
vec![
Person::new(&quot;Al&quot;.to_string(), 60),
Person::new(&quot;Zoe&quot;.to_string(), 25),
Person::new(&quot;John&quot;.to_string(), 1),
]);
}
</code></pre></pre>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#command-line-1" id="command-line-1">Command Line</a></h1>
<table><thead><tr><th>Recipe</th><th>Crates</th><th>Categories</th></tr></thead><tbody>
<tr><td><a href="cli/arguments.html#parse-command-line-arguments">Parse command line arguments</a></td><td><a href="https://docs.rs/clap/"><img src="https://badge-cache.kominick.com/crates/v/clap.svg?label=clap" alt="clap-badge" /></a></td><td><a href="https://crates.io/categories/command-line-interface"><img src="https://badge-cache.kominick.com/badge/command_line--x.svg?style=social" alt="cat-command-line-badge" /></a></td></tr>
<tr><td><a href="cli/ansi_terminal.html#ansi-terminal">ANSI Terminal</a></td><td><a href="https://docs.rs/ansi_term/"><img src="https://badge-cache.kominick.com/crates/v/base64.svg?label=ansi_term" alt="ansi_term-badge" /></a></td><td><a href="https://crates.io/categories/command-line-interface"><img src="https://badge-cache.kominick.com/badge/command_line--x.svg?style=social" alt="cat-command-line-badge" /></a></td></tr>
</tbody></table>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#clap-basic" id="clap-basic">Clap basic</a></h1>
<h2><a class="header" href="#parse-command-line-arguments" id="parse-command-line-arguments">Parse command line arguments</a></h2>
<p><a href="https://docs.rs/clap/"><img src="https://badge-cache.kominick.com/crates/v/clap.svg?label=clap" alt="clap-badge" /></a> <a href="https://crates.io/categories/command-line-interface"><img src="https://badge-cache.kominick.com/badge/command_line--x.svg?style=social" alt="cat-command-line-badge" /></a></p>
<p>This application describes the structure of its command-line interface using
<code>clap</code>'s builder style. The <a href="https://docs.rs/clap/">documentation</a> gives two other possible ways to
instantiate an application.</p>
<p>In the builder style, <code>with_name</code> is the unique identifier that <code>value_of</code> will
use to retrieve the value passed. The <code>short</code> and <code>long</code> options control the
flag the user will be expected to type; short flags look like <code>-f</code> and long
flags look like <code>--file</code>.</p>
<pre><pre class="playground"><code class="language-rust edition2018">use clap::{Arg, App};
fn main() {
let matches = App::new(&quot;My Test Program&quot;)
.version(&quot;0.1.0&quot;)
.author(&quot;Hackerman Jones &lt;hckrmnjones@hack.gov&gt;&quot;)
.about(&quot;Teaches argument parsing&quot;)
.arg(Arg::with_name(&quot;file&quot;)
.short(&quot;f&quot;)
.long(&quot;file&quot;)
.takes_value(true)
.help(&quot;A cool file&quot;))
.arg(Arg::with_name(&quot;num&quot;)
.short(&quot;n&quot;)
.long(&quot;number&quot;)
.takes_value(true)
.help(&quot;Five less than your favorite number&quot;))
.get_matches();
let myfile = matches.value_of(&quot;file&quot;).unwrap_or(&quot;input.txt&quot;);
println!(&quot;The file passed is: {}&quot;, myfile);
let num_str = matches.value_of(&quot;num&quot;);
match num_str {
None =&gt; println!(&quot;No idea what your favorite number is.&quot;),
Some(s) =&gt; {
match s.parse::&lt;i32&gt;() {
Ok(n) =&gt; println!(&quot;Your favorite number must be {}.&quot;, n + 5),
Err(_) =&gt; println!(&quot;That's not a number! {}&quot;, s),
}
}
}
}
</code></pre></pre>
<p>Usage information is generated by <code>clap</code>. The usage for the example application
looks like this.</p>
<pre><code>My Test Program 0.1.0
Hackerman Jones &lt;hckrmnjones@hack.gov&gt;
Teaches argument parsing
USAGE:
testing [OPTIONS]
FLAGS:
-h, --help Prints help information
-V, --version Prints version information
OPTIONS:
-f, --file &lt;file&gt; A cool file
-n, --number &lt;num&gt; Five less than your favorite number
</code></pre>
<p>We can test the application by running a command like the following.</p>
<pre><code>$ cargo run -- -f myfile.txt -n 251
</code></pre>
<p>The output is:</p>
<pre><code>The file passed is: myfile.txt
Your favorite number must be 256.
</code></pre>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#ansi-terminal" id="ansi-terminal">ANSI Terminal</a></h1>
<h2><a class="header" href="#ansi-terminal-1" id="ansi-terminal-1">ANSI Terminal</a></h2>
<p><a href="https://docs.rs/ansi_term/"><img src="https://badge-cache.kominick.com/crates/v/base64.svg?label=ansi_term" alt="ansi_term-badge" /></a> <a href="https://crates.io/categories/command-line-interface"><img src="https://badge-cache.kominick.com/badge/command_line--x.svg?style=social" alt="cat-command-line-badge" /></a></p>
<p>This program depicts the use of <a href="https://crates.io/crates/ansi_term"><code>ansi_term</code></a> crate and how it is used for controlling colours and formatting, such as blue bold text or yellow underlined text, on ANSI terminals.</p>
<p>There are two main data structures in <a href="https://crates.io/crates/ansi_term"><code>ansi_term</code></a>: <a href="https://docs.rs/ansi_term/*/ansi_term/type.ANSIString.html"><code>ANSIString</code></a> and <a href="https://docs.rs/ansi_term/*/ansi_term/struct.Style.html"><code>Style</code></a>. A <a href="https://docs.rs/ansi_term/*/ansi_term/struct.Style.html"><code>Style</code></a> holds stylistic information: colours, whether the text should be bold, or blinking, or whatever. There are also Colour variants that represent simple foreground colour styles. An <a href="https://docs.rs/ansi_term/*/ansi_term/type.ANSIString.html"><code>ANSIString</code></a> is a string paired with a <a href="https://docs.rs/ansi_term/*/ansi_term/struct.Style.html"><code>Style</code></a>.</p>
<p><strong>Note:</strong> British English uses <em>Colour</em> instead of <em>Color</em>, don't get confused</p>
<h3><a class="header" href="#printing-colored-text-to-the-terminal" id="printing-colored-text-to-the-terminal">Printing colored text to the Terminal</a></h3>
<pre><pre class="playground"><code class="language-rust edition2018">use ansi_term::Colour;
fn main() {
println!(&quot;This is {} in color, {} in color and {} in color&quot;,
Colour::Red.paint(&quot;red&quot;),
Colour::Blue.paint(&quot;blue&quot;),
Colour::Green.paint(&quot;green&quot;));
}
</code></pre></pre>
<h3><a class="header" href="#bold-text-in-terminal" id="bold-text-in-terminal">Bold text in Terminal</a></h3>
<p>For anything more complex than plain foreground colour changes, the code
needs to construct <code>Style</code> struct. <a href="https://docs.rs/ansi_term/0.11.0/ansi_term/struct.Style.html#method.new"><code>Style::new()</code></a> creates the struct,
and properties chained.</p>
<pre><pre class="playground"><code class="language-rust edition2018">use ansi_term::Style;
fn main() {
println!(&quot;{} and this is not&quot;,
Style::new().bold().paint(&quot;This is Bold&quot;));
}
</code></pre></pre>
<h3><a class="header" href="#bold-and-colored-text-in-terminal" id="bold-and-colored-text-in-terminal">Bold and colored text in terminal</a></h3>
<p><code>Colour</code> implements many similar functions as <code>Style</code> and can chain methods.</p>
<pre><pre class="playground"><code class="language-rust edition2018">use ansi_term::Colour;
use ansi_term::Style;
fn main(){
println!(&quot;{}, {} and {}&quot;,
Colour::Yellow.paint(&quot;This is colored&quot;),
Style::new().bold().paint(&quot;this is bold&quot;),
Colour::Yellow.bold().paint(&quot;this is bold and colored&quot;));
}
</code></pre></pre>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#compression-1" id="compression-1">Compression</a></h1>
<table><thead><tr><th>Recipe</th><th>Crates</th><th>Categories</th></tr></thead><tbody>
<tr><td><a href="compression/tar.html#decompress-a-tarball">Decompress a tarball</a></td><td><a href="https://docs.rs/flate2/"><img src="https://badge-cache.kominick.com/crates/v/flate2.svg?label=flate2" alt="flate2-badge" /></a> <a href="https://docs.rs/tar/"><img src="https://badge-cache.kominick.com/crates/v/tar.svg?label=tar" alt="tar-badge" /></a></td><td><a href="https://crates.io/categories/compression"><img src="https://badge-cache.kominick.com/badge/compression--x.svg?style=social" alt="cat-compression-badge" /></a></td></tr>
<tr><td><a href="compression/tar.html#compress-a-directory-into-tarball">Compress a directory into a tarball</a></td><td><a href="https://docs.rs/flate2/"><img src="https://badge-cache.kominick.com/crates/v/flate2.svg?label=flate2" alt="flate2-badge" /></a> <a href="https://docs.rs/tar/"><img src="https://badge-cache.kominick.com/crates/v/tar.svg?label=tar" alt="tar-badge" /></a></td><td><a href="https://crates.io/categories/compression"><img src="https://badge-cache.kominick.com/badge/compression--x.svg?style=social" alt="cat-compression-badge" /></a></td></tr>
<tr><td><a href="compression/tar.html#decompress-a-tarball-while-removing-a-prefix-from-the-paths">Decompress a tarball while removing a prefix from the paths</a></td><td><a href="https://docs.rs/flate2/"><img src="https://badge-cache.kominick.com/crates/v/flate2.svg?label=flate2" alt="flate2-badge" /></a> <a href="https://docs.rs/tar/"><img src="https://badge-cache.kominick.com/crates/v/tar.svg?label=tar" alt="tar-badge" /></a></td><td><a href="https://crates.io/categories/compression"><img src="https://badge-cache.kominick.com/badge/compression--x.svg?style=social" alt="cat-compression-badge" /></a></td></tr>
</tbody></table>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#working-with-tarballs" id="working-with-tarballs">Working with Tarballs</a></h1>
<h2><a class="header" href="#decompress-a-tarball" id="decompress-a-tarball">Decompress a tarball</a></h2>
<p><a href="https://docs.rs/flate2/"><img src="https://badge-cache.kominick.com/crates/v/flate2.svg?label=flate2" alt="flate2-badge" /></a> <a href="https://docs.rs/tar/"><img src="https://badge-cache.kominick.com/crates/v/tar.svg?label=tar" alt="tar-badge" /></a> <a href="https://crates.io/categories/compression"><img src="https://badge-cache.kominick.com/badge/compression--x.svg?style=social" alt="cat-compression-badge" /></a></p>
<p>Decompress (<a href="https://docs.rs/flate2/*/flate2/read/struct.GzDecoder.html"><code>GzDecoder</code></a>) and
extract (<a href="https://docs.rs/tar/*/tar/struct.Archive.html#method.unpack"><code>Archive::unpack</code></a>) all files from a compressed tarball
named <code>archive.tar.gz</code> located in the current working directory
to the same location.</p>
<pre><pre class="playground"><code class="language-rust edition2018 no_run">
use std::fs::File;
use flate2::read::GzDecoder;
use tar::Archive;
fn main() -&gt; Result&lt;(), std::io::Error&gt; {
let path = &quot;archive.tar.gz&quot;;
let tar_gz = File::open(path)?;
let tar = GzDecoder::new(tar_gz);
let mut archive = Archive::new(tar);
archive.unpack(&quot;.&quot;)?;
Ok(())
}
</code></pre></pre>
<h2><a class="header" href="#compress-a-directory-into-tarball" id="compress-a-directory-into-tarball">Compress a directory into tarball</a></h2>
<p><a href="https://docs.rs/flate2/"><img src="https://badge-cache.kominick.com/crates/v/flate2.svg?label=flate2" alt="flate2-badge" /></a> <a href="https://docs.rs/tar/"><img src="https://badge-cache.kominick.com/crates/v/tar.svg?label=tar" alt="tar-badge" /></a> <a href="https://crates.io/categories/compression"><img src="https://badge-cache.kominick.com/badge/compression--x.svg?style=social" alt="cat-compression-badge" /></a></p>
<p>Compress <code>/var/log</code> directory into <code>archive.tar.gz</code>.</p>
<p>Creates a <a href="https://doc.rust-lang.org/std/fs/struct.File.html"><code>File</code></a> wrapped in <a href="https://docs.rs/flate2/*/flate2/write/struct.GzEncoder.html"><code>GzEncoder</code></a>
and <a href="https://docs.rs/tar/*/tar/struct.Builder.html"><code>tar::Builder</code></a>. </br>Adds contents of <code>/var/log</code> directory recursively into the archive
under <code>backup/logs</code>path with <a href="https://docs.rs/tar/*/tar/struct.Builder.html#method.append_dir_all"><code>Builder::append_dir_all</code></a>.
<a href="https://docs.rs/flate2/*/flate2/write/struct.GzEncoder.html"><code>GzEncoder</code></a> is responsible for transparently compressing the
data prior to writing it into <code>archive.tar.gz</code>.</p>
<pre><pre class="playground"><code class="language-rust edition2018 no_run">
use std::fs::File;
use flate2::Compression;
use flate2::write::GzEncoder;
fn main() -&gt; Result&lt;(), std::io::Error&gt; {
let tar_gz = File::create(&quot;archive.tar.gz&quot;)?;
let enc = GzEncoder::new(tar_gz, Compression::default());
let mut tar = tar::Builder::new(enc);
tar.append_dir_all(&quot;backup/logs&quot;, &quot;/var/log&quot;)?;
Ok(())
}
</code></pre></pre>
<h2><a class="header" href="#decompress-a-tarball-while-removing-a-prefix-from-the-paths" id="decompress-a-tarball-while-removing-a-prefix-from-the-paths">Decompress a tarball while removing a prefix from the paths</a></h2>
<p><a href="https://docs.rs/flate2/"><img src="https://badge-cache.kominick.com/crates/v/flate2.svg?label=flate2" alt="flate2-badge" /></a> <a href="https://docs.rs/tar/"><img src="https://badge-cache.kominick.com/crates/v/tar.svg?label=tar" alt="tar-badge" /></a> <a href="https://crates.io/categories/compression"><img src="https://badge-cache.kominick.com/badge/compression--x.svg?style=social" alt="cat-compression-badge" /></a></p>
<p>Iterate over the <a href="https://docs.rs/tar/*/tar/struct.Archive.html#method.entries"><code>Archive::entries</code></a>. Use <a href="https://doc.rust-lang.org/std/path/struct.Path.html#method.strip_prefix"><code>Path::strip_prefix</code></a> to remove
the specified path prefix (<code>bundle/logs</code>). Finally, extract the <a href="https://docs.rs/tar/*/tar/struct.Entry.html"><code>tar::Entry</code></a>
via <a href="https://docs.rs/tar/*/tar/struct.Entry.html#method.unpack"><code>Entry::unpack</code></a>.</p>
<pre><pre class="playground"><code class="language-rust edition2018 no_run"><span class="boring">use error_chain::error_chain;
</span>use std::fs::File;
use std::path::PathBuf;
use flate2::read::GzDecoder;
use tar::Archive;
<span class="boring">
</span><span class="boring">error_chain! {
</span><span class="boring"> foreign_links {
</span><span class="boring"> Io(std::io::Error);
</span><span class="boring"> StripPrefixError(::std::path::StripPrefixError);
</span><span class="boring"> }
</span><span class="boring">}
</span>
fn main() -&gt; Result&lt;()&gt; {
let file = File::open(&quot;archive.tar.gz&quot;)?;
let mut archive = Archive::new(GzDecoder::new(file));
let prefix = &quot;bundle/logs&quot;;
println!(&quot;Extracted the following files:&quot;);
archive
.entries()?
.filter_map(|e| e.ok())
.map(|mut entry| -&gt; Result&lt;PathBuf&gt; {
let path = entry.path()?.strip_prefix(prefix)?.to_owned();
entry.unpack(&amp;path)?;
Ok(path)
})
.filter_map(|e| e.ok())
.for_each(|x| println!(&quot;&gt; {}&quot;, x.display()));
Ok(())
}
</code></pre></pre>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#concurrency-1" id="concurrency-1">Concurrency</a></h1>
<table><thead><tr><th>Recipe</th><th>Crates</th><th>Categories</th></tr></thead><tbody>
<tr><td><a href="concurrency/threads.html#spawn-a-short-lived-thread">Spawn a short-lived thread</a></td><td><a href="https://docs.rs/crossbeam/"><img src="https://badge-cache.kominick.com/crates/v/crossbeam.svg?label=crossbeam" alt="crossbeam-badge" /></a></td><td><a href="https://crates.io/categories/concurrency"><img src="https://badge-cache.kominick.com/badge/concurrency--x.svg?style=social" alt="cat-concurrency-badge" /></a></td></tr>
<tr><td><a href="concurrency/threads.html#create-a-parallel-pipeline">Create a parallel data pipeline</a></td><td><a href="https://docs.rs/crossbeam/"><img src="https://badge-cache.kominick.com/crates/v/crossbeam.svg?label=crossbeam" alt="crossbeam-badge" /></a></td><td><a href="https://crates.io/categories/concurrency"><img src="https://badge-cache.kominick.com/badge/concurrency--x.svg?style=social" alt="cat-concurrency-badge" /></a></td></tr>
<tr><td><a href="concurrency/threads.html#pass-data-between-two-threads">Pass data between two threads</a></td><td><a href="https://docs.rs/crossbeam/"><img src="https://badge-cache.kominick.com/crates/v/crossbeam.svg?label=crossbeam" alt="crossbeam-badge" /></a></td><td><a href="https://crates.io/categories/concurrency"><img src="https://badge-cache.kominick.com/badge/concurrency--x.svg?style=social" alt="cat-concurrency-badge" /></a></td></tr>
<tr><td><a href="concurrency/threads.html#maintain-global-mutable-state">Maintain global mutable state</a></td><td><a href="https://docs.rs/lazy_static/"><img src="https://badge-cache.kominick.com/crates/v/lazy_static.svg?label=lazy_static" alt="lazy_static-badge" /></a></td><td><a href="https://crates.io/categories/rust-patterns"><img src="https://badge-cache.kominick.com/badge/rust_patterns--x.svg?style=social" alt="cat-rust-patterns-badge" /></a></td></tr>
<tr><td><a href="concurrency/threads.html#calculate-sha256-sum-of-iso-files-concurrently">Calculate SHA1 sum of *.iso files concurrently</a></td><td><a href="https://docs.rs/threadpool/"><img src="https://badge-cache.kominick.com/crates/v/threadpool.svg?label=threadpool" alt="threadpool-badge" /></a> <a href="https://docs.rs/walkdir/"><img src="https://badge-cache.kominick.com/crates/v/walkdir.svg?label=walkdir" alt="walkdir-badge" /></a> <a href="https://docs.rs/num_cpus/"><img src="https://badge-cache.kominick.com/crates/v/num_cpus.svg?label=num_cpus" alt="num_cpus-badge" /></a> <a href="https://briansmith.org/rustdoc/ring/"><img src="https://badge-cache.kominick.com/crates/v/ring.svg?label=ring" alt="ring-badge" /></a></td><td><a href="https://crates.io/categories/concurrency"><img src="https://badge-cache.kominick.com/badge/concurrency--x.svg?style=social" alt="cat-concurrency-badge" /></a><a href="https://crates.io/categories/filesystem"><img src="https://badge-cache.kominick.com/badge/filesystem--x.svg?style=social" alt="cat-filesystem-badge" /></a></td></tr>
<tr><td><a href="concurrency/threads.html#draw-fractal-dispatching-work-to-a-thread-pool">Draw fractal dispatching work to a thread pool</a></td><td><a href="https://docs.rs/threadpool/"><img src="https://badge-cache.kominick.com/crates/v/threadpool.svg?label=threadpool" alt="threadpool-badge" /></a> <a href="https://docs.rs/num/"><img src="https://badge-cache.kominick.com/crates/v/num.svg?label=num" alt="num-badge" /></a> <a href="https://docs.rs/num_cpus/"><img src="https://badge-cache.kominick.com/crates/v/num_cpus.svg?label=num_cpus" alt="num_cpus-badge" /></a> <a href="https://docs.rs/image/"><img src="https://badge-cache.kominick.com/crates/v/image.svg?label=image" alt="image-badge" /></a></td><td><a href="https://crates.io/categories/concurrency"><img src="https://badge-cache.kominick.com/badge/concurrency--x.svg?style=social" alt="cat-concurrency-badge" /></a><a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a><a href="https://crates.io/categories/rendering"><img src="https://badge-cache.kominick.com/badge/rendering--x.svg?style=social" alt="cat-rendering-badge" /></a></td></tr>
<tr><td><a href="concurrency/parallel.html#mutate-the-elements-of-an-array-in-parallel">Mutate the elements of an array in parallel</a></td><td><a href="https://docs.rs/rayon/"><img src="https://badge-cache.kominick.com/crates/v/rayon.svg?label=rayon" alt="rayon-badge" /></a></td><td><a href="https://crates.io/categories/concurrency"><img src="https://badge-cache.kominick.com/badge/concurrency--x.svg?style=social" alt="cat-concurrency-badge" /></a></td></tr>
<tr><td><a href="concurrency/parallel.html#test-in-parallel-if-any-or-all-elements-of-a-collection-match-a-given-predicate">Test in parallel if any or all elements of a collection match a given predicate</a></td><td><a href="https://docs.rs/rayon/"><img src="https://badge-cache.kominick.com/crates/v/rayon.svg?label=rayon" alt="rayon-badge" /></a></td><td><a href="https://crates.io/categories/concurrency"><img src="https://badge-cache.kominick.com/badge/concurrency--x.svg?style=social" alt="cat-concurrency-badge" /></a></td></tr>
<tr><td><a href="concurrency/parallel.html#search-items-using-given-predicate-in-parallel">Search items using given predicate in parallel</a></td><td><a href="https://docs.rs/rayon/"><img src="https://badge-cache.kominick.com/crates/v/rayon.svg?label=rayon" alt="rayon-badge" /></a></td><td><a href="https://crates.io/categories/concurrency"><img src="https://badge-cache.kominick.com/badge/concurrency--x.svg?style=social" alt="cat-concurrency-badge" /></a></td></tr>
<tr><td><a href="concurrency/parallel.html#sort-a-vector-in-parallel">Sort a vector in parallel</a></td><td><a href="https://docs.rs/rayon/"><img src="https://badge-cache.kominick.com/crates/v/rayon.svg?label=rayon" alt="rayon-badge" /></a> <a href="https://docs.rs/rand/"><img src="https://badge-cache.kominick.com/crates/v/rand.svg?label=rand" alt="rand-badge" /></a></td><td><a href="https://crates.io/categories/concurrency"><img src="https://badge-cache.kominick.com/badge/concurrency--x.svg?style=social" alt="cat-concurrency-badge" /></a></td></tr>
<tr><td><a href="concurrency/parallel.html#map-reduce-in-parallel">Map-reduce in parallel</a></td><td><a href="https://docs.rs/rayon/"><img src="https://badge-cache.kominick.com/crates/v/rayon.svg?label=rayon" alt="rayon-badge" /></a></td><td><a href="https://crates.io/categories/concurrency"><img src="https://badge-cache.kominick.com/badge/concurrency--x.svg?style=social" alt="cat-concurrency-badge" /></a></td></tr>
<tr><td><a href="concurrency/parallel.html#generate-jpg-thumbnails-in-parallel">Generate jpg thumbnails in parallel</a></td><td><a href="https://docs.rs/rayon/"><img src="https://badge-cache.kominick.com/crates/v/rayon.svg?label=rayon" alt="rayon-badge" /></a> <a href="https://docs.rs/glob/"><img src="https://badge-cache.kominick.com/crates/v/glob.svg?label=glob" alt="glob-badge" /></a> <a href="https://docs.rs/image/"><img src="https://badge-cache.kominick.com/crates/v/image.svg?label=image" alt="image-badge" /></a></td><td><a href="https://crates.io/categories/concurrency"><img src="https://badge-cache.kominick.com/badge/concurrency--x.svg?style=social" alt="cat-concurrency-badge" /></a><a href="https://crates.io/categories/filesystem"><img src="https://badge-cache.kominick.com/badge/filesystem--x.svg?style=social" alt="cat-filesystem-badge" /></a></td></tr>
</tbody></table>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#threads" id="threads">Threads</a></h1>
<h2><a class="header" href="#spawn-a-short-lived-thread" id="spawn-a-short-lived-thread">Spawn a short-lived thread</a></h2>
<p><a href="https://docs.rs/crossbeam/"><img src="https://badge-cache.kominick.com/crates/v/crossbeam.svg?label=crossbeam" alt="crossbeam-badge" /></a> <a href="https://crates.io/categories/concurrency"><img src="https://badge-cache.kominick.com/badge/concurrency--x.svg?style=social" alt="cat-concurrency-badge" /></a></p>
<p>The example uses the <a href="https://docs.rs/crossbeam/">crossbeam</a> crate, which provides data structures and functions
for concurrent and parallel programming. <a href="https://docs.rs/crossbeam/*/crossbeam/thread/struct.Scope.html#method.spawn"><code>Scope::spawn</code></a> spawns a new scoped thread that is guaranteed
to terminate before returning from the closure that passed into <a href="https://docs.rs/crossbeam/*/crossbeam/fn.scope.html"><code>crossbeam::scope</code></a> function, meaning that
you can reference data from the calling function.</p>
<p>This example splits the array in half and performs the work in separate threads.</p>
<pre><pre class="playground"><code class="language-rust edition2018">fn main() {
let arr = &amp;[1, 25, -4, 10];
let max = find_max(arr);
assert_eq!(max, Some(25));
}
fn find_max(arr: &amp;[i32]) -&gt; Option&lt;i32&gt; {
const THRESHOLD: usize = 2;
if arr.len() &lt;= THRESHOLD {
return arr.iter().cloned().max();
}
let mid = arr.len() / 2;
let (left, right) = arr.split_at(mid);
crossbeam::scope(|s| {
let thread_l = s.spawn(|_| find_max(left));
let thread_r = s.spawn(|_| find_max(right));
let max_l = thread_l.join().unwrap()?;
let max_r = thread_r.join().unwrap()?;
Some(max_l.max(max_r))
}).unwrap()
}
</code></pre></pre>
<h2><a class="header" href="#create-a-parallel-pipeline" id="create-a-parallel-pipeline">Create a parallel pipeline</a></h2>
<p><a href="https://docs.rs/crossbeam/"><img src="https://badge-cache.kominick.com/crates/v/crossbeam.svg?label=crossbeam" alt="crossbeam-badge" /></a> <a href="https://crates.io/categories/concurrency"><img src="https://badge-cache.kominick.com/badge/concurrency--x.svg?style=social" alt="cat-concurrency-badge" /></a></p>
<p>This example uses the <a href="https://docs.rs/crossbeam/">crossbeam</a> and <a href="https://docs.rs/crossbeam-channel/*/crossbeam_channel/index.html">crossbeam-channel</a> crates to create
a parallel pipeline, similar to that described in the ZeroMQ <a href="http://zguide.zeromq.org/page:all#Divide-and-Conquer">guide</a>
There is a data source and a data sink, with data being processed by two worker
threads in parallel on its way from the source to the sink.</p>
<p>We use bounded channels with a capacity of one using
<a href="https://docs.rs/crossbeam-channel/*/crossbeam_channel/fn.bounded.html"><code>crossbeam_channel::bounded</code></a>. The producer must be on its own thread because
it produces messages faster than the workers can process them (since they sleep
for half a second) - this means the producer blocks on the call to
<code>[crossbeam_channel::Sender::send</code>] for half a second until one of the workers
processes the data in the channel. Also note that the data in the channel is
consumed by whichever worker calls receive first, so each message is delivered
to a single worker rather than both workers.</p>
<p>Reading from the channels via the iterator
<a href="https://docs.rs/crossbeam-channel/*/crossbeam_channel/struct.Receiver.html#method.iter"><code>crossbeam_channel::Receiver::iter</code></a> method will block, either waiting
for new messages or until the channel is closed. Because the channels were
created within the <a href="https://docs.rs/crossbeam/*/crossbeam/fn.scope.html"><code>crossbeam::scope</code></a>, we must manually close them via <code>drop</code>
to prevent the entire program from blocking on the worker for-loops. You can
think of the calls to <code>drop</code> as signaling that no more messages will be sent.</p>
<pre><pre class="playground"><code class="language-rust">extern crate crossbeam;
extern crate crossbeam_channel;
use std::thread;
use std::time::Duration;
use crossbeam_channel::bounded;
fn main() {
let (snd1, rcv1) = bounded(1);
let (snd2, rcv2) = bounded(1);
let n_msgs = 4;
let n_workers = 2;
crossbeam::scope(|s| {
// Producer thread
s.spawn(|_| {
for i in 0..n_msgs {
snd1.send(i).unwrap();
println!(&quot;Source sent {}&quot;, i);
}
// Close the channel - this is necessary to exit
// the for-loop in the worker
drop(snd1);
});
// Parallel processing by 2 threads
for _ in 0..n_workers {
// Send to sink, receive from source
let (sendr, recvr) = (snd2.clone(), rcv1.clone());
// Spawn workers in separate threads
s.spawn(move |_| {
thread::sleep(Duration::from_millis(500));
// Receive until channel closes
for msg in recvr.iter() {
println!(&quot;Worker {:?} received {}.&quot;,
thread::current().id(), msg);
sendr.send(msg * 2).unwrap();
}
});
}
// Close the channel, otherwise sink will never
// exit the for-loop
drop(snd2);
// Sink
for msg in rcv2.iter() {
println!(&quot;Sink received {}&quot;, msg);
}
}).unwrap();
}
</code></pre></pre>
<h1><a class="header" href="#pass-data-between-two-threads" id="pass-data-between-two-threads">Pass data between two threads</a></h1>
<p><a href="https://docs.rs/crossbeam/"><img src="https://badge-cache.kominick.com/crates/v/crossbeam.svg?label=crossbeam" alt="crossbeam-badge" /></a> <a href="https://crates.io/categories/concurrency"><img src="https://badge-cache.kominick.com/badge/concurrency--x.svg?style=social" alt="cat-concurrency-badge" /></a></p>
<p>This example demonstrates the use of <a href="https://docs.rs/crossbeam-channel/*/crossbeam_channel/index.html">crossbeam-channel</a> in a single producer, single
consumer (SPSC) setting. We build off the <a href="concurrency/concurrency/threads.html#spawn-a-short-lived-thread">ex-crossbeam-spawn</a> example by using
<a href="https://docs.rs/crossbeam/*/crossbeam/fn.scope.html"><code>crossbeam::scope</code></a> and <a href="https://docs.rs/crossbeam/*/crossbeam/thread/struct.Scope.html#method.spawn"><code>Scope::spawn</code></a> to manage the producer thread. Data is
exchanged between the two threads using a <a href="https://docs.rs/crossbeam-channel/*/crossbeam_channel/fn.unbounded.html"><code>crossbeam_channel::unbounded</code></a>
channel, meaning there is no limit to the number of storeable messages. The
producer thread sleeps for half a second in between messages.</p>
<pre><pre class="playground"><code class="language-rust edition2018">
use std::{thread, time};
use crossbeam_channel::unbounded;
fn main() {
let (snd, rcv) = unbounded();
let n_msgs = 5;
crossbeam::scope(|s| {
s.spawn(|_| {
for i in 0..n_msgs {
snd.send(i).unwrap();
thread::sleep(time::Duration::from_millis(100));
}
});
}).unwrap();
for _ in 0..n_msgs {
let msg = rcv.recv().unwrap();
println!(&quot;Received {}&quot;, msg);
}
}
</code></pre></pre>
<h2><a class="header" href="#maintain-global-mutable-state" id="maintain-global-mutable-state">Maintain global mutable state</a></h2>
<p><a href="https://docs.rs/lazy_static/"><img src="https://badge-cache.kominick.com/crates/v/lazy_static.svg?label=lazy_static" alt="lazy_static-badge" /></a> <a href="https://crates.io/categories/rust-patterns"><img src="https://badge-cache.kominick.com/badge/rust_patterns--x.svg?style=social" alt="cat-rust-patterns-badge" /></a></p>
<p>Declare global state using <a href="https://docs.rs/lazy_static/">lazy_static</a>. <a href="https://docs.rs/lazy_static/">lazy_static</a>
creates a globally available <code>static ref</code> which requires a <a href="https://doc.rust-lang.org/std/sync/struct.Mutex.html"><code>Mutex</code></a>
to allow mutation (also see <a href="https://doc.rust-lang.org/std/sync/struct.RwLock.html"><code>RwLock</code></a>). The <a href="https://doc.rust-lang.org/std/sync/struct.Mutex.html"><code>Mutex</code></a> wrap ensures
the state cannot be simultaneously accessed by multiple threads, preventing
race conditions. A <a href="https://doc.rust-lang.org/std/sync/struct.MutexGuard.html"><code>MutexGuard</code></a> must be acquired to read or mutate the
value stored in a <a href="https://doc.rust-lang.org/std/sync/struct.Mutex.html"><code>Mutex</code></a>.</p>
<pre><pre class="playground"><code class="language-rust edition2018"><span class="boring">use error_chain::error_chain;
</span>use lazy_static::lazy_static;
use std::sync::Mutex;
<span class="boring">
</span><span class="boring">error_chain!{ }
</span>
lazy_static! {
static ref FRUIT: Mutex&lt;Vec&lt;String&gt;&gt; = Mutex::new(Vec::new());
}
fn insert(fruit: &amp;str) -&gt; Result&lt;()&gt; {
let mut db = FRUIT.lock().map_err(|_| &quot;Failed to acquire MutexGuard&quot;)?;
db.push(fruit.to_string());
Ok(())
}
fn main() -&gt; Result&lt;()&gt; {
insert(&quot;apple&quot;)?;
insert(&quot;orange&quot;)?;
insert(&quot;peach&quot;)?;
{
let db = FRUIT.lock().map_err(|_| &quot;Failed to acquire MutexGuard&quot;)?;
db.iter().enumerate().for_each(|(i, item)| println!(&quot;{}: {}&quot;, i, item));
}
insert(&quot;grape&quot;)?;
Ok(())
}
</code></pre></pre>
<h2><a class="header" href="#calculate-sha256-sum-of-iso-files-concurrently" id="calculate-sha256-sum-of-iso-files-concurrently">Calculate SHA256 sum of iso files concurrently</a></h2>
<p><a href="https://docs.rs/threadpool/"><img src="https://badge-cache.kominick.com/crates/v/threadpool.svg?label=threadpool" alt="threadpool-badge" /></a> <a href="https://docs.rs/num_cpus/"><img src="https://badge-cache.kominick.com/crates/v/num_cpus.svg?label=num_cpus" alt="num_cpus-badge" /></a> <a href="https://docs.rs/walkdir/"><img src="https://badge-cache.kominick.com/crates/v/walkdir.svg?label=walkdir" alt="walkdir-badge" /></a> <a href="https://briansmith.org/rustdoc/ring/"><img src="https://badge-cache.kominick.com/crates/v/ring.svg?label=ring" alt="ring-badge" /></a> <a href="https://crates.io/categories/concurrency"><img src="https://badge-cache.kominick.com/badge/concurrency--x.svg?style=social" alt="cat-concurrency-badge" /></a><a href="https://crates.io/categories/filesystem"><img src="https://badge-cache.kominick.com/badge/filesystem--x.svg?style=social" alt="cat-filesystem-badge" /></a></p>
<p>This example calculates the SHA256 for every file with iso extension in the
current directory. A threadpool generates threads equal to the number of cores
present in the system found with <a href="https://docs.rs/num_cpus/*/num_cpus/fn.get.html"><code>num_cpus::get</code></a>. <a href="https://docs.rs/walkdir/*/walkdir/struct.WalkDir.html#method.new"><code>Walkdir::new</code></a> iterates
the current directory and calls <a href="https://docs.rs/threadpool/*/threadpool/struct.ThreadPool.html#method.execute"><code>execute</code></a> to perform the operations of reading
and computing SHA256 hash.</p>
<pre><pre class="playground"><code class="language-rust edition2018 no_run">
use walkdir::WalkDir;
use std::fs::File;
use std::io::{BufReader, Read, Error};
use std::path::Path;
use threadpool::ThreadPool;
use std::sync::mpsc::channel;
use ring::digest::{Context, Digest, SHA256};
<span class="boring">// Verify the iso extension
</span><span class="boring">fn is_iso(entry: &amp;Path) -&gt; bool {
</span><span class="boring"> match entry.extension() {
</span><span class="boring"> Some(e) if e.to_string_lossy().to_lowercase() == &quot;iso&quot; =&gt; true,
</span><span class="boring"> _ =&gt; false,
</span><span class="boring"> }
</span><span class="boring">}
</span>
fn compute_digest&lt;P: AsRef&lt;Path&gt;&gt;(filepath: P) -&gt; Result&lt;(Digest, P), Error&gt; {
let mut buf_reader = BufReader::new(File::open(&amp;filepath)?);
let mut context = Context::new(&amp;SHA256);
let mut buffer = [0; 1024];
loop {
let count = buf_reader.read(&amp;mut buffer)?;
if count == 0 {
break;
}
context.update(&amp;buffer[..count]);
}
Ok((context.finish(), filepath))
}
fn main() -&gt; Result&lt;(), Error&gt; {
let pool = ThreadPool::new(num_cpus::get());
let (tx, rx) = channel();
for entry in WalkDir::new(&quot;/home/user/Downloads&quot;)
.follow_links(true)
.into_iter()
.filter_map(|e| e.ok())
.filter(|e| !e.path().is_dir() &amp;&amp; is_iso(e.path())) {
let path = entry.path().to_owned();
let tx = tx.clone();
pool.execute(move || {
let digest = compute_digest(path);
tx.send(digest).expect(&quot;Could not send data!&quot;);
});
}
drop(tx);
for t in rx.iter() {
let (sha, path) = t?;
println!(&quot;{:?} {:?}&quot;, sha, path);
}
Ok(())
}
</code></pre></pre>
<h2><a class="header" href="#draw-fractal-dispatching-work-to-a-thread-pool" id="draw-fractal-dispatching-work-to-a-thread-pool">Draw fractal dispatching work to a thread pool</a></h2>
<p><a href="https://docs.rs/threadpool/"><img src="https://badge-cache.kominick.com/crates/v/threadpool.svg?label=threadpool" alt="threadpool-badge" /></a> <a href="https://docs.rs/num/"><img src="https://badge-cache.kominick.com/crates/v/num.svg?label=num" alt="num-badge" /></a> <a href="https://docs.rs/num_cpus/"><img src="https://badge-cache.kominick.com/crates/v/num_cpus.svg?label=num_cpus" alt="num_cpus-badge" /></a> <a href="https://docs.rs/image/"><img src="https://badge-cache.kominick.com/crates/v/image.svg?label=image" alt="image-badge" /></a> <a href="https://crates.io/categories/concurrency"><img src="https://badge-cache.kominick.com/badge/concurrency--x.svg?style=social" alt="cat-concurrency-badge" /></a><a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a><a href="https://crates.io/categories/rendering"><img src="https://badge-cache.kominick.com/badge/rendering--x.svg?style=social" alt="cat-rendering-badge" /></a></p>
<p>This example generates an image by drawing a fractal from the <a href="https://en.wikipedia.org/wiki/Julia_set">Julia set</a>
with a thread pool for distributed computation.</p>
<p><a href="https://cloud.githubusercontent.com/assets/221000/26546700/9be34e80-446b-11e7-81dc-dd9871614ea1.png"><img src="https://cloud.githubusercontent.com/assets/221000/26546700/9be34e80-446b-11e7-81dc-dd9871614ea1.png" width="150" /></a></p>
<p>Allocate memory for output image of given width and height with <a href="https://docs.rs/image/*/image/struct.ImageBuffer.html#method.new"><code>ImageBuffer::new</code></a>.
<a href="https://docs.rs/image/*/image/struct.Rgb.html#method.from_channels"><code>Rgb::from_channels</code></a> calculates RGB pixel values.
Create <a href="https://docs.rs/threadpool/*/threadpool/struct.ThreadPool.html"><code>ThreadPool</code></a> with thread count equal to number of cores with <a href="https://docs.rs/num_cpus/*/num_cpus/fn.get.html"><code>num_cpus::get</code></a>.
<a href="https://docs.rs/threadpool/*/threadpool/struct.ThreadPool.html#method.execute"><code>ThreadPool::execute</code></a> receives each pixel as a separate job.</p>
<p><a href="https://doc.rust-lang.org/std/sync/mpsc/fn.channel.html"><code>mpsc::channel</code></a> receives the jobs and <a href="https://doc.rust-lang.org/std/sync/mpsc/struct.Receiver.html#method.recv"><code>Receiver::recv</code></a> retrieves them.
<a href="https://docs.rs/image/*/image/struct.ImageBuffer.html#method.put_pixel"><code>ImageBuffer::put_pixel</code></a> uses the data to set the pixel color.
<a href="https://docs.rs/image/*/image/struct.ImageBuffer.html#method.save"><code>ImageBuffer::save</code></a> writes the image to <code>output.png</code>.</p>
<pre><pre class="playground"><code class="language-rust edition2018 no_run"><span class="boring">use error_chain::error_chain;
</span>use std::sync::mpsc::{channel, RecvError};
use threadpool::ThreadPool;
use num::complex::Complex;
use image::{ImageBuffer, Pixel, Rgb};
<span class="boring">
</span><span class="boring">error_chain! {
</span><span class="boring"> foreign_links {
</span><span class="boring"> MpscRecv(RecvError);
</span><span class="boring"> Io(std::io::Error);
</span><span class="boring"> }
</span><span class="boring">}
</span><span class="boring">
</span><span class="boring">// Function converting intensity values to RGB
</span><span class="boring">// Based on http://www.efg2.com/Lab/ScienceAndEngineering/Spectra.htm
</span><span class="boring">fn wavelength_to_rgb(wavelength: u32) -&gt; Rgb&lt;u8&gt; {
</span><span class="boring"> let wave = wavelength as f32;
</span><span class="boring">
</span><span class="boring"> let (r, g, b) = match wavelength {
</span><span class="boring"> 380..=439 =&gt; ((440. - wave) / (440. - 380.), 0.0, 1.0),
</span><span class="boring"> 440..=489 =&gt; (0.0, (wave - 440.) / (490. - 440.), 1.0),
</span><span class="boring"> 490..=509 =&gt; (0.0, 1.0, (510. - wave) / (510. - 490.)),
</span><span class="boring"> 510..=579 =&gt; ((wave - 510.) / (580. - 510.), 1.0, 0.0),
</span><span class="boring"> 580..=644 =&gt; (1.0, (645. - wave) / (645. - 580.), 0.0),
</span><span class="boring"> 645..=780 =&gt; (1.0, 0.0, 0.0),
</span><span class="boring"> _ =&gt; (0.0, 0.0, 0.0),
</span><span class="boring"> };
</span><span class="boring">
</span><span class="boring"> let factor = match wavelength {
</span><span class="boring"> 380..=419 =&gt; 0.3 + 0.7 * (wave - 380.) / (420. - 380.),
</span><span class="boring"> 701..=780 =&gt; 0.3 + 0.7 * (780. - wave) / (780. - 700.),
</span><span class="boring"> _ =&gt; 1.0,
</span><span class="boring"> };
</span><span class="boring">
</span><span class="boring"> let (r, g, b) = (normalize(r, factor), normalize(g, factor), normalize(b, factor));
</span><span class="boring"> Rgb::from_channels(r, g, b, 0)
</span><span class="boring">}
</span><span class="boring">
</span><span class="boring">// Maps Julia set distance estimation to intensity values
</span><span class="boring">fn julia(c: Complex&lt;f32&gt;, x: u32, y: u32, width: u32, height: u32, max_iter: u32) -&gt; u32 {
</span><span class="boring"> let width = width as f32;
</span><span class="boring"> let height = height as f32;
</span><span class="boring">
</span><span class="boring"> let mut z = Complex {
</span><span class="boring"> // scale and translate the point to image coordinates
</span><span class="boring"> re: 3.0 * (x as f32 - 0.5 * width) / width,
</span><span class="boring"> im: 2.0 * (y as f32 - 0.5 * height) / height,
</span><span class="boring"> };
</span><span class="boring">
</span><span class="boring"> let mut i = 0;
</span><span class="boring"> for t in 0..max_iter {
</span><span class="boring"> if z.norm() &gt;= 2.0 {
</span><span class="boring"> break;
</span><span class="boring"> }
</span><span class="boring"> z = z * z + c;
</span><span class="boring"> i = t;
</span><span class="boring"> }
</span><span class="boring"> i
</span><span class="boring">}
</span><span class="boring">
</span><span class="boring">// Normalizes color intensity values within RGB range
</span><span class="boring">fn normalize(color: f32, factor: f32) -&gt; u8 {
</span><span class="boring"> ((color * factor).powf(0.8) * 255.) as u8
</span><span class="boring">}
</span>
fn main() -&gt; Result&lt;()&gt; {
let (width, height) = (1920, 1080);
let mut img = ImageBuffer::new(width, height);
let iterations = 300;
let c = Complex::new(-0.8, 0.156);
let pool = ThreadPool::new(num_cpus::get());
let (tx, rx) = channel();
for y in 0..height {
let tx = tx.clone();
pool.execute(move || for x in 0..width {
let i = julia(c, x, y, width, height, iterations);
let pixel = wavelength_to_rgb(380 + i * 400 / iterations);
tx.send((x, y, pixel)).expect(&quot;Could not send data!&quot;);
});
}
for _ in 0..(width * height) {
let (x, y, pixel) = rx.recv()?;
img.put_pixel(x, y, pixel);
}
let _ = img.save(&quot;output.png&quot;)?;
Ok(())
}
</code></pre></pre>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#parallel-tasks" id="parallel-tasks">Parallel Tasks</a></h1>
<h2><a class="header" href="#mutate-the-elements-of-an-array-in-parallel" id="mutate-the-elements-of-an-array-in-parallel">Mutate the elements of an array in parallel</a></h2>
<p><a href="https://docs.rs/rayon/"><img src="https://badge-cache.kominick.com/crates/v/rayon.svg?label=rayon" alt="rayon-badge" /></a> <a href="https://crates.io/categories/concurrency"><img src="https://badge-cache.kominick.com/badge/concurrency--x.svg?style=social" alt="cat-concurrency-badge" /></a></p>
<p>The example uses the <code>rayon</code> crate, which is a data parallelism library for Rust.
<code>rayon</code> provides the <a href="https://docs.rs/rayon/*/rayon/iter/trait.IntoParallelRefMutIterator.html#tymethod.par_iter_mut"><code>par_iter_mut</code></a> method for any parallel iterable data type.
This is an iterator-like chain that potentially executes in parallel.</p>
<pre><pre class="playground"><code class="language-rust edition2018">use rayon::prelude::*;
fn main() {
let mut arr = [0, 7, 9, 11];
arr.par_iter_mut().for_each(|p| *p -= 1);
println!(&quot;{:?}&quot;, arr);
}
</code></pre></pre>
<h2><a class="header" href="#test-in-parallel-if-any-or-all-elements-of-a-collection-match-a-given-predicate" id="test-in-parallel-if-any-or-all-elements-of-a-collection-match-a-given-predicate">Test in parallel if any or all elements of a collection match a given predicate</a></h2>
<p><a href="https://docs.rs/rayon/"><img src="https://badge-cache.kominick.com/crates/v/rayon.svg?label=rayon" alt="rayon-badge" /></a> <a href="https://crates.io/categories/concurrency"><img src="https://badge-cache.kominick.com/badge/concurrency--x.svg?style=social" alt="cat-concurrency-badge" /></a></p>
<p>This example demonstrates using the <a href="https://docs.rs/rayon/*/rayon/iter/trait.ParallelIterator.html#method.any"><code>rayon::any</code></a> and <a href="https://docs.rs/rayon/*/rayon/iter/trait.ParallelIterator.html#method.all"><code>rayon::all</code></a> methods, which are parallelized counterparts to <a href="https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.any"><code>std::any</code></a> and <a href="https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.all"><code>std::all</code></a>. <a href="https://docs.rs/rayon/*/rayon/iter/trait.ParallelIterator.html#method.any"><code>rayon::any</code></a> checks in parallel whether any element of the iterator matches the predicate, and returns as soon as one is found. <a href="https://docs.rs/rayon/*/rayon/iter/trait.ParallelIterator.html#method.all"><code>rayon::all</code></a> checks in parallel whether all elements of the iterator match the predicate, and returns as soon as a non-matching element is found.</p>
<pre><pre class="playground"><code class="language-rust edition2018">use rayon::prelude::*;
fn main() {
let mut vec = vec![2, 4, 6, 8];
assert!(!vec.par_iter().any(|n| (*n % 2) != 0));
assert!(vec.par_iter().all(|n| (*n % 2) == 0));
assert!(!vec.par_iter().any(|n| *n &gt; 8 ));
assert!(vec.par_iter().all(|n| *n &lt;= 8 ));
vec.push(9);
assert!(vec.par_iter().any(|n| (*n % 2) != 0));
assert!(!vec.par_iter().all(|n| (*n % 2) == 0));
assert!(vec.par_iter().any(|n| *n &gt; 8 ));
assert!(!vec.par_iter().all(|n| *n &lt;= 8 ));
}
</code></pre></pre>
<h2><a class="header" href="#search-items-using-given-predicate-in-parallel" id="search-items-using-given-predicate-in-parallel">Search items using given predicate in parallel</a></h2>
<p><a href="https://docs.rs/rayon/"><img src="https://badge-cache.kominick.com/crates/v/rayon.svg?label=rayon" alt="rayon-badge" /></a> <a href="https://crates.io/categories/concurrency"><img src="https://badge-cache.kominick.com/badge/concurrency--x.svg?style=social" alt="cat-concurrency-badge" /></a></p>
<p>This example uses <a href="https://docs.rs/rayon/*/rayon/iter/trait.ParallelIterator.html#method.find_any"><code>rayon::find_any</code></a> and <a href="https://docs.rs/rayon/*/rayon/iter/trait.IntoParallelRefIterator.html#tymethod.par_iter"><code>par_iter</code></a> to search a vector in
parallel for an element satisfying the predicate in the given closure.</p>
<p>If there are multiple elements satisfying the predicate defined in the closure
argument of <a href="https://docs.rs/rayon/*/rayon/iter/trait.ParallelIterator.html#method.find_any"><code>rayon::find_any</code></a>, <code>rayon</code> returns the first one found, not
necessarily the first one.</p>
<p>Also note that the argument to the closure is a reference to a reference
(<code>&amp;&amp;x</code>). See the discussion on <a href="https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.find"><code>std::find</code></a> for additional details.</p>
<pre><pre class="playground"><code class="language-rust edition2018">use rayon::prelude::*;
fn main() {
let v = vec![6, 2, 1, 9, 3, 8, 11];
let f1 = v.par_iter().find_any(|&amp;&amp;x| x == 9);
let f2 = v.par_iter().find_any(|&amp;&amp;x| x % 2 == 0 &amp;&amp; x &gt; 6);
let f3 = v.par_iter().find_any(|&amp;&amp;x| x &gt; 8);
assert_eq!(f1, Some(&amp;9));
assert_eq!(f2, Some(&amp;8));
assert!(f3 &gt; Some(&amp;8));
}
</code></pre></pre>
<h2><a class="header" href="#sort-a-vector-in-parallel" id="sort-a-vector-in-parallel">Sort a vector in parallel</a></h2>
<p><a href="https://docs.rs/rayon/"><img src="https://badge-cache.kominick.com/crates/v/rayon.svg?label=rayon" alt="rayon-badge" /></a> <a href="https://docs.rs/rand/"><img src="https://badge-cache.kominick.com/crates/v/rand.svg?label=rand" alt="rand-badge" /></a> <a href="https://crates.io/categories/concurrency"><img src="https://badge-cache.kominick.com/badge/concurrency--x.svg?style=social" alt="cat-concurrency-badge" /></a></p>
<p>This example will sort in parallel a vector of Strings.</p>
<p>Allocate a vector of empty Strings. <code>par_iter_mut().for_each</code> populates random
values in parallel. Although <a href="https://docs.rs/rayon/*/rayon/slice/trait.ParallelSliceMut.html">multiple options</a>
exist to sort an enumerable data type, <a href="https://docs.rs/rayon/*/rayon/slice/trait.ParallelSliceMut.html#method.par_sort_unstable"><code>par_sort_unstable</code></a>
is usually faster than <a href="https://docs.rs/rayon/*/rayon/slice/trait.ParallelSliceMut.html#method.par_sort">stable sorting</a> algorithms.</p>
<pre><pre class="playground"><code class="language-rust edition2018">
use rand::{Rng, thread_rng};
use rand::distributions::Alphanumeric;
use rayon::prelude::*;
fn main() {
let mut vec = vec![String::new(); 100_000];
vec.par_iter_mut().for_each(|p| {
let mut rng = thread_rng();
*p = (0..5).map(|_| rng.sample(&amp;Alphanumeric)).collect()
});
vec.par_sort_unstable();
}
</code></pre></pre>
<h2><a class="header" href="#map-reduce-in-parallel" id="map-reduce-in-parallel">Map-reduce in parallel</a></h2>
<p><a href="https://docs.rs/rayon/"><img src="https://badge-cache.kominick.com/crates/v/rayon.svg?label=rayon" alt="rayon-badge" /></a> <a href="https://crates.io/categories/concurrency"><img src="https://badge-cache.kominick.com/badge/concurrency--x.svg?style=social" alt="cat-concurrency-badge" /></a></p>
<p>This example uses <a href="https://docs.rs/rayon/*/rayon/iter/trait.ParallelIterator.html#method.filter"><code>rayon::filter</code></a>, <a href="https://docs.rs/rayon/*/rayon/iter/trait.ParallelIterator.html#method.map"><code>rayon::map</code></a>, and <a href="https://docs.rs/rayon/*/rayon/iter/trait.ParallelIterator.html#method.reduce"><code>rayon::reduce</code></a>
to calculate the average age of <code>Person</code> objects whose age is over 30.</p>
<p><a href="https://docs.rs/rayon/*/rayon/iter/trait.ParallelIterator.html#method.filter"><code>rayon::filter</code></a> returns elements from a collection that satisfy the given
predicate. <a href="https://docs.rs/rayon/*/rayon/iter/trait.ParallelIterator.html#method.map"><code>rayon::map</code></a> performs an operation on every element, creating a
new iteration, and <a href="https://docs.rs/rayon/*/rayon/iter/trait.ParallelIterator.html#method.reduce"><code>rayon::reduce</code></a> performs an operation given the previous
reduction and the current element. Also shows use of <a href="https://docs.rs/rayon/*/rayon/iter/trait.ParallelIterator.html#method.sum"><code>rayon::sum</code></a>,
which has the same result as the reduce operation in this example.</p>
<pre><pre class="playground"><code class="language-rust edition2018">use rayon::prelude::*;
struct Person {
age: u32,
}
fn main() {
let v: Vec&lt;Person&gt; = vec![
Person { age: 23 },
Person { age: 19 },
Person { age: 42 },
Person { age: 17 },
Person { age: 17 },
Person { age: 31 },
Person { age: 30 },
];
let num_over_30 = v.par_iter().filter(|&amp;x| x.age &gt; 30).count() as f32;
let sum_over_30 = v.par_iter()
.map(|x| x.age)
.filter(|&amp;x| x &gt; 30)
.reduce(|| 0, |x, y| x + y);
let alt_sum_30: u32 = v.par_iter()
.map(|x| x.age)
.filter(|&amp;x| x &gt; 30)
.sum();
let avg_over_30 = sum_over_30 as f32 / num_over_30;
let alt_avg_over_30 = alt_sum_30 as f32/ num_over_30;
assert!((avg_over_30 - alt_avg_over_30).abs() &lt; std::f32::EPSILON);
println!(&quot;The average age of people older than 30 is {}&quot;, avg_over_30);
}
</code></pre></pre>
<h2><a class="header" href="#generate-jpg-thumbnails-in-parallel" id="generate-jpg-thumbnails-in-parallel">Generate jpg thumbnails in parallel</a></h2>
<p><a href="https://docs.rs/rayon/"><img src="https://badge-cache.kominick.com/crates/v/rayon.svg?label=rayon" alt="rayon-badge" /></a> <a href="https://docs.rs/glob/"><img src="https://badge-cache.kominick.com/crates/v/glob.svg?label=glob" alt="glob-badge" /></a> <a href="https://docs.rs/image/"><img src="https://badge-cache.kominick.com/crates/v/image.svg?label=image" alt="image-badge" /></a> <a href="https://crates.io/categories/concurrency"><img src="https://badge-cache.kominick.com/badge/concurrency--x.svg?style=social" alt="cat-concurrency-badge" /></a> <a href="https://crates.io/categories/filesystem"><img src="https://badge-cache.kominick.com/badge/filesystem--x.svg?style=social" alt="cat-filesystem-badge" /></a></p>
<p>This example generates thumbnails for all .jpg files in the current directory
then saves them in a new folder called <code>thumbnails</code>.</p>
<p><a href="https://docs.rs/glob/*/glob/fn.glob_with.html"><code>glob::glob_with</code></a> finds jpeg files in current directory. <code>rayon</code> resizes
images in parallel using <a href="https://docs.rs/rayon/*/rayon/iter/trait.IntoParallelRefIterator.html#tymethod.par_iter"><code>par_iter</code></a> calling <a href="https://docs.rs/image/*/image/enum.DynamicImage.html#method.resize"><code>DynamicImage::resize</code></a>.</p>
<pre><pre class="playground"><code class="language-rust edition2018 no_run"><span class="boring">use error_chain::error_chain;
</span>
use std::path::Path;
use std::fs::create_dir_all;
<span class="boring">use error_chain::ChainedError;
</span>use glob::{glob_with, MatchOptions};
use image::{FilterType, ImageError};
use rayon::prelude::*;
<span class="boring">error_chain! {
</span><span class="boring"> foreign_links {
</span><span class="boring"> Image(ImageError);
</span><span class="boring"> Io(std::io::Error);
</span><span class="boring"> Glob(glob::PatternError);
</span><span class="boring"> }
</span><span class="boring">}
</span>
fn main() -&gt; Result&lt;()&gt; {
let options: MatchOptions = Default::default();
let files: Vec&lt;_&gt; = glob_with(&quot;*.jpg&quot;, options)?
.filter_map(|x| x.ok())
.collect();
if files.len() == 0 {
error_chain::bail!(&quot;No .jpg files found in current directory&quot;);
}
let thumb_dir = &quot;thumbnails&quot;;
create_dir_all(thumb_dir)?;
println!(&quot;Saving {} thumbnails into '{}'...&quot;, files.len(), thumb_dir);
let image_failures: Vec&lt;_&gt; = files
.par_iter()
.map(|path| {
make_thumbnail(path, thumb_dir, 300)
.map_err(|e| e.chain_err(|| path.display().to_string()))
})
.filter_map(|x| x.err())
.collect();
image_failures.iter().for_each(|x| println!(&quot;{}&quot;, x.display_chain()));
println!(&quot;{} thumbnails saved successfully&quot;, files.len() - image_failures.len());
Ok(())
}
fn make_thumbnail&lt;PA, PB&gt;(original: PA, thumb_dir: PB, longest_edge: u32) -&gt; Result&lt;()&gt;
where
PA: AsRef&lt;Path&gt;,
PB: AsRef&lt;Path&gt;,
{
let img = image::open(original.as_ref())?;
let file_path = thumb_dir.as_ref().join(original);
Ok(img.resize(longest_edge, longest_edge, FilterType::Nearest)
.save(file_path)?)
}
</code></pre></pre>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#cryptography-1" id="cryptography-1">Cryptography</a></h1>
<table><thead><tr><th>Recipe</th><th>Crates</th><th>Categories</th></tr></thead><tbody>
<tr><td><a href="cryptography/hashing.html#calculate-the-sha-256-digest-of-a-file">Calculate the SHA-256 digest of a file</a></td><td><a href="https://briansmith.org/rustdoc/ring/"><img src="https://badge-cache.kominick.com/crates/v/ring.svg?label=ring" alt="ring-badge" /></a> <a href="https://docs.rs/data-encoding/"><img src="https://badge-cache.kominick.com/crates/v/data-encoding.svg?label=data-encoding" alt="data-encoding-badge" /></a></td><td><a href="https://crates.io/categories/cryptography"><img src="https://badge-cache.kominick.com/badge/cryptography--x.svg?style=social" alt="cat-cryptography-badge" /></a></td></tr>
<tr><td><a href="cryptography/hashing.html#sign-and-verify-a-message-with-hmac-digest">Sign and verify a message with an HMAC digest</a></td><td><a href="https://briansmith.org/rustdoc/ring/"><img src="https://badge-cache.kominick.com/crates/v/ring.svg?label=ring" alt="ring-badge" /></a></td><td><a href="https://crates.io/categories/cryptography"><img src="https://badge-cache.kominick.com/badge/cryptography--x.svg?style=social" alt="cat-cryptography-badge" /></a></td></tr>
<tr><td><a href="cryptography/encryption.html#salt-and-hash-a-password-with-pbkdf2">Salt and hash a password with PBKDF2</a></td><td><a href="https://briansmith.org/rustdoc/ring/"><img src="https://badge-cache.kominick.com/crates/v/ring.svg?label=ring" alt="ring-badge" /></a> <a href="https://docs.rs/data-encoding/"><img src="https://badge-cache.kominick.com/crates/v/data-encoding.svg?label=data-encoding" alt="data-encoding-badge" /></a></td><td><a href="https://crates.io/categories/cryptography"><img src="https://badge-cache.kominick.com/badge/cryptography--x.svg?style=social" alt="cat-cryptography-badge" /></a></td></tr>
</tbody></table>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#hashing" id="hashing">Hashing</a></h1>
<h2><a class="header" href="#calculate-the-sha-256-digest-of-a-file" id="calculate-the-sha-256-digest-of-a-file">Calculate the SHA-256 digest of a file</a></h2>
<p><a href="https://briansmith.org/rustdoc/ring/"><img src="https://badge-cache.kominick.com/crates/v/ring.svg?label=ring" alt="ring-badge" /></a> <a href="https://docs.rs/data-encoding/"><img src="https://badge-cache.kominick.com/crates/v/data-encoding.svg?label=data-encoding" alt="data-encoding-badge" /></a> <a href="https://crates.io/categories/cryptography"><img src="https://badge-cache.kominick.com/badge/cryptography--x.svg?style=social" alt="cat-cryptography-badge" /></a></p>
<p>Writes some data to a file, then calculates the SHA-256 <a href="https://briansmith.org/rustdoc/ring/digest/struct.Digest.html"><code>digest::Digest</code></a> of
the file's contents using <a href="https://briansmith.org/rustdoc/ring/digest/struct.Context.html"><code>digest::Context</code></a>.</p>
<pre><pre class="playground"><code class="language-rust edition2018"><span class="boring">use error_chain::error_chain;
</span>use data_encoding::HEXUPPER;
use ring::digest::{Context, Digest, SHA256};
use std::fs::File;
use std::io::{BufReader, Read, Write};
<span class="boring">
</span><span class="boring">error_chain! {
</span><span class="boring"> foreign_links {
</span><span class="boring"> Io(std::io::Error);
</span><span class="boring"> Decode(data_encoding::DecodeError);
</span><span class="boring"> }
</span><span class="boring">}
</span>
fn sha256_digest&lt;R: Read&gt;(mut reader: R) -&gt; Result&lt;Digest&gt; {
let mut context = Context::new(&amp;SHA256);
let mut buffer = [0; 1024];
loop {
let count = reader.read(&amp;mut buffer)?;
if count == 0 {
break;
}
context.update(&amp;buffer[..count]);
}
Ok(context.finish())
}
fn main() -&gt; Result&lt;()&gt; {
let path = &quot;file.txt&quot;;
let mut output = File::create(path)?;
write!(output, &quot;We will generate a digest of this text&quot;)?;
let input = File::open(path)?;
let reader = BufReader::new(input);
let digest = sha256_digest(reader)?;
println!(&quot;SHA-256 digest is {}&quot;, HEXUPPER.encode(digest.as_ref()));
Ok(())
}
</code></pre></pre>
<h2><a class="header" href="#sign-and-verify-a-message-with-hmac-digest" id="sign-and-verify-a-message-with-hmac-digest">Sign and verify a message with HMAC digest</a></h2>
<p><a href="https://briansmith.org/rustdoc/ring/"><img src="https://badge-cache.kominick.com/crates/v/ring.svg?label=ring" alt="ring-badge" /></a> <a href="https://crates.io/categories/cryptography"><img src="https://badge-cache.kominick.com/badge/cryptography--x.svg?style=social" alt="cat-cryptography-badge" /></a></p>
<p>Uses <a href="https://briansmith.org/rustdoc/ring/hmac/"><code>ring::hmac</code></a> to creates a <a href="https://briansmith.org/rustdoc/ring/hmac/struct.Signature.html"><code>hmac::Signature</code></a> of a string then verifies the signature is correct.</p>
<pre><pre class="playground"><code class="language-rust edition2018">use ring::{hmac, rand};
use ring::rand::SecureRandom;
use ring::error::Unspecified;
fn main() -&gt; Result&lt;(), Unspecified&gt; {
let mut key_value = [0u8; 48];
let rng = rand::SystemRandom::new();
rng.fill(&amp;mut key_value)?;
let key = hmac::Key::new(hmac::HMAC_SHA256, &amp;key_value);
let message = &quot;Legitimate and important message.&quot;;
let signature = hmac::sign(&amp;key, message.as_bytes());
hmac::verify(&amp;key, message.as_bytes(), signature.as_ref())?;
Ok(())
}
</code></pre></pre>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#encryption" id="encryption">Encryption</a></h1>
<p><a name="ex-pbkdf2"></a></p>
<h2><a class="header" href="#salt-and-hash-a-password-with-pbkdf2" id="salt-and-hash-a-password-with-pbkdf2">Salt and hash a password with PBKDF2</a></h2>
<p><a href="https://briansmith.org/rustdoc/ring/"><img src="https://badge-cache.kominick.com/crates/v/ring.svg?label=ring" alt="ring-badge" /></a> <a href="https://docs.rs/data-encoding/"><img src="https://badge-cache.kominick.com/crates/v/data-encoding.svg?label=data-encoding" alt="data-encoding-badge" /></a> <a href="https://crates.io/categories/cryptography"><img src="https://badge-cache.kominick.com/badge/cryptography--x.svg?style=social" alt="cat-cryptography-badge" /></a></p>
<p>Uses <a href="https://briansmith.org/rustdoc/ring/pbkdf2/index.html"><code>ring::pbkdf2</code></a> to hash a salted password using the PBKDF2 key derivation
function <a href="https://briansmith.org/rustdoc/ring/pbkdf2/fn.derive.html"><code>pbkdf2::derive</code></a>. Verifies the hash is correct with
<a href="https://briansmith.org/rustdoc/ring/pbkdf2/fn.verify.html"><code>pbkdf2::verify</code></a>. The salt is generated using
<a href="https://briansmith.org/rustdoc/ring/rand/trait.SecureRandom.html#tymethod.fill"><code>SecureRandom::fill</code></a>, which fills the salt byte array with
securely generated random numbers.</p>
<pre><pre class="playground"><code class="language-rust edition2018">
use data_encoding::HEXUPPER;
use ring::error::Unspecified;
use ring::rand::SecureRandom;
use ring::{digest, pbkdf2, rand};
use std::num::NonZeroU32;
fn main() -&gt; Result&lt;(), Unspecified&gt; {
const CREDENTIAL_LEN: usize = digest::SHA512_OUTPUT_LEN;
let n_iter = NonZeroU32::new(100_000).unwrap();
let rng = rand::SystemRandom::new();
let mut salt = [0u8; CREDENTIAL_LEN];
rng.fill(&amp;mut salt)?;
let password = &quot;Guess Me If You Can!&quot;;
let mut pbkdf2_hash = [0u8; CREDENTIAL_LEN];
pbkdf2::derive(
pbkdf2::PBKDF2_HMAC_SHA512,
n_iter,
&amp;salt,
password.as_bytes(),
&amp;mut pbkdf2_hash,
);
println!(&quot;Salt: {}&quot;, HEXUPPER.encode(&amp;salt));
println!(&quot;PBKDF2 hash: {}&quot;, HEXUPPER.encode(&amp;pbkdf2_hash));
let should_succeed = pbkdf2::verify(
pbkdf2::PBKDF2_HMAC_SHA512,
n_iter,
&amp;salt,
password.as_bytes(),
&amp;pbkdf2_hash,
);
let wrong_password = &quot;Definitely not the correct password&quot;;
let should_fail = pbkdf2::verify(
pbkdf2::PBKDF2_HMAC_SHA512,
n_iter,
&amp;salt,
wrong_password.as_bytes(),
&amp;pbkdf2_hash,
);
assert!(should_succeed.is_ok());
assert!(!should_fail.is_ok());
Ok(())
}
</code></pre></pre>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#data-structures-1" id="data-structures-1">Data Structures</a></h1>
<table><thead><tr><th>Recipe</th><th>Crates</th><th>Categories</th></tr></thead><tbody>
<tr><td><a href="data_structures/bitfield.html#define-and-operate-on-a-type-represented-as-a-bitfield">Define and operate on a type represented as a bitfield</a></td><td><a href="https://docs.rs/bitflags/"><img src="https://badge-cache.kominick.com/crates/v/bitflags.svg?label=bitflags" alt="bitflags-badge" /></a></td><td><a href="https://crates.io/categories/no-std"><img src="https://badge-cache.kominick.com/badge/no_std--x.svg?style=social" alt="cat-no-std-badge" /></a></td></tr>
</tbody></table>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#custom" id="custom">Custom</a></h1>
<h2><a class="header" href="#define-and-operate-on-a-type-represented-as-a-bitfield" id="define-and-operate-on-a-type-represented-as-a-bitfield">Define and operate on a type represented as a bitfield</a></h2>
<p><a href="https://docs.rs/bitflags/"><img src="https://badge-cache.kominick.com/crates/v/bitflags.svg?label=bitflags" alt="bitflags-badge" /></a> <a href="https://crates.io/categories/no-std"><img src="https://badge-cache.kominick.com/badge/no_std--x.svg?style=social" alt="cat-no-std-badge" /></a></p>
<p>Creates type safe bitfield type <code>MyFlags</code> with help of <a href="https://docs.rs/bitflags/*/bitflags/macro.bitflags.html"><code>bitflags!</code></a> macro
and implements elementary <code>clear</code> operation as well as <a href="https://doc.rust-lang.org/std/fmt/trait.Display.html"><code>Display</code></a> trait for it.
Subsequently, shows basic bitwise operations and formatting.</p>
<pre><pre class="playground"><code class="language-rust edition2018">use bitflags::bitflags;
use std::fmt;
bitflags! {
struct MyFlags: u32 {
const FLAG_A = 0b00000001;
const FLAG_B = 0b00000010;
const FLAG_C = 0b00000100;
const FLAG_ABC = Self::FLAG_A.bits
| Self::FLAG_B.bits
| Self::FLAG_C.bits;
}
}
impl MyFlags {
pub fn clear(&amp;mut self) -&gt; &amp;mut MyFlags {
self.bits = 0;
self
}
}
impl fmt::Display for MyFlags {
fn fmt(&amp;self, f: &amp;mut fmt::Formatter) -&gt; fmt::Result {
write!(f, &quot;{:032b}&quot;, self.bits)
}
}
fn main() {
let e1 = MyFlags::FLAG_A | MyFlags::FLAG_C;
let e2 = MyFlags::FLAG_B | MyFlags::FLAG_C;
assert_eq!((e1 | e2), MyFlags::FLAG_ABC);
assert_eq!((e1 &amp; e2), MyFlags::FLAG_C);
assert_eq!((e1 - e2), MyFlags::FLAG_A);
assert_eq!(!e2, MyFlags::FLAG_A);
let mut flags = MyFlags::FLAG_ABC;
assert_eq!(format!(&quot;{}&quot;, flags), &quot;00000000000000000000000000000111&quot;);
assert_eq!(format!(&quot;{}&quot;, flags.clear()), &quot;00000000000000000000000000000000&quot;);
assert_eq!(format!(&quot;{:?}&quot;, MyFlags::FLAG_B), &quot;FLAG_B&quot;);
assert_eq!(format!(&quot;{:?}&quot;, MyFlags::FLAG_A | MyFlags::FLAG_B), &quot;FLAG_A | FLAG_B&quot;);
}
</code></pre></pre>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#database-1" id="database-1">Database</a></h1>
<table><thead><tr><th>Recipe</th><th>Crates</th><th>Categories</th></tr></thead><tbody>
<tr><td><a href="database/sqlite.html#create-a-sqlite-database">Create a SQLite database</a></td><td><a href="https://crates.io/crates/rusqlite/"><img src="https://badge-cache.kominick.com/crates/v/rusqlite.svg?label=rusqlite" alt="rusqlite-badge" /></a></td><td><a href="https://crates.io/categories/database"><img src="https://badge-cache.kominick.com/badge/database--x.svg?style=social" alt="cat-database-badge" /></a></td></tr>
<tr><td><a href="database/sqlite.html#insert-and-select-data">Insert and Query data</a></td><td><a href="https://crates.io/crates/rusqlite/"><img src="https://badge-cache.kominick.com/crates/v/rusqlite.svg?label=rusqlite" alt="rusqlite-badge" /></a></td><td><a href="https://crates.io/categories/database"><img src="https://badge-cache.kominick.com/badge/database--x.svg?style=social" alt="cat-database-badge" /></a></td></tr>
<tr><td><a href="database/postgres.html#create-tables-in-a-postgres-database">Create tables in a Postgres database</a></td><td><a href="https://docs.rs/postgres/0.15.2/postgres/"><img src="https://badge-cache.kominick.com/crates/v/postgres.svg?label=postgres" alt="postgres-badge" /></a></td><td><a href="https://crates.io/categories/database"><img src="https://badge-cache.kominick.com/badge/database--x.svg?style=social" alt="cat-database-badge" /></a></td></tr>
<tr><td><a href="database/postgres.html#insert-and-query-data">Insert and Query data</a></td><td><a href="https://docs.rs/postgres/0.15.2/postgres/"><img src="https://badge-cache.kominick.com/crates/v/postgres.svg?label=postgres" alt="postgres-badge" /></a></td><td><a href="https://crates.io/categories/database"><img src="https://badge-cache.kominick.com/badge/database--x.svg?style=social" alt="cat-database-badge" /></a></td></tr>
<tr><td><a href="database/postgres.html#aggregate-data">Aggregate data</a></td><td><a href="https://docs.rs/postgres/0.15.2/postgres/"><img src="https://badge-cache.kominick.com/crates/v/postgres.svg?label=postgres" alt="postgres-badge" /></a></td><td><a href="https://crates.io/categories/database"><img src="https://badge-cache.kominick.com/badge/database--x.svg?style=social" alt="cat-database-badge" /></a></td></tr>
</tbody></table>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#sqlite" id="sqlite">SQLite</a></h1>
<h2><a class="header" href="#create-a-sqlite-database" id="create-a-sqlite-database">Create a SQLite database</a></h2>
<p><a href="https://crates.io/crates/rusqlite/"><img src="https://badge-cache.kominick.com/crates/v/rusqlite.svg?label=rusqlite" alt="rusqlite-badge" /></a> <a href="https://crates.io/categories/database"><img src="https://badge-cache.kominick.com/badge/database--x.svg?style=social" alt="cat-database-badge" /></a></p>
<p>Use the <code>rusqlite</code> crate to open SQLite databases. See
<a href="https://github.com/jgallagher/rusqlite#user-content-notes-on-building-rusqlite-and-libsqlite3-sys">crate</a> for compiling on Windows.</p>
<p><a href="https://docs.rs/rusqlite/*/rusqlite/struct.Connection.html#method.open"><code>Connection::open</code></a> will create the database if it doesn't already exist.</p>
<pre><pre class="playground"><code class="language-rust edition2018 no_run">use rusqlite::{Connection, Result};
use rusqlite::NO_PARAMS;
fn main() -&gt; Result&lt;()&gt; {
let conn = Connection::open(&quot;cats.db&quot;)?;
conn.execute(
&quot;create table if not exists cat_colors (
id integer primary key,
name text not null unique
)&quot;,
NO_PARAMS,
)?;
conn.execute(
&quot;create table if not exists cats (
id integer primary key,
name text not null,
color_id integer not null references cat_colors(id)
)&quot;,
NO_PARAMS,
)?;
Ok(())
}
</code></pre></pre>
<h2><a class="header" href="#insert-and-select-data" id="insert-and-select-data">Insert and Select data</a></h2>
<p><a href="https://crates.io/crates/rusqlite/"><img src="https://badge-cache.kominick.com/crates/v/rusqlite.svg?label=rusqlite" alt="rusqlite-badge" /></a> <a href="https://crates.io/categories/database"><img src="https://badge-cache.kominick.com/badge/database--x.svg?style=social" alt="cat-database-badge" /></a></p>
<p><a href="https://docs.rs/rusqlite/*/rusqlite/struct.Connection.html#method.open"><code>Connection::open</code></a> will open the database <code>cats</code> created in the earlier recipe.
This recipe inserts data into <code>cat_colors</code> and <code>cats</code> tables using the <a href="https://docs.rs/rusqlite/*/rusqlite/struct.Connection.html#method.execute"><code>execute</code></a> method of <code>Connection</code>. First, the data is inserted into the <code>cat_colors</code> table. After a record for a color is inserted, <a href="https://docs.rs/rusqlite/*/rusqlite/struct.Connection.html#method.last_insert_rowid"><code>last_insert_rowid</code></a> method of <code>Connection</code> is used to get <code>id</code> of the last color inserted. This <code>id</code> is used while inserting data into the <code>cats</code> table. Then, the select query is prepared using the <a href="https://docs.rs/rusqlite/*/rusqlite/struct.Connection.html#method.prepare"><code>prepare</code></a> method which gives a <a href="https://docs.rs/rusqlite/*/rusqlite/struct.Statement.html"><code>statement</code></a> struct. Then, query is executed using <a href="https://docs.rs/rusqlite/*/rusqlite/struct.Statement.html#method.query_map"><code>query_map</code></a> method of <a href="https://docs.rs/rusqlite/*/rusqlite/struct.Statement.html"><code>statement</code></a>.</p>
<pre><pre class="playground"><code class="language-rust no_run">
use rusqlite::NO_PARAMS;
use rusqlite::{Connection, Result};
use std::collections::HashMap;
#[derive(Debug)]
struct Cat {
name: String,
color: String,
}
fn main() -&gt; Result&lt;()&gt; {
let conn = Connection::open(&quot;cats.db&quot;)?;
let mut cat_colors = HashMap::new();
cat_colors.insert(String::from(&quot;Blue&quot;), vec![&quot;Tigger&quot;, &quot;Sammy&quot;]);
cat_colors.insert(String::from(&quot;Black&quot;), vec![&quot;Oreo&quot;, &quot;Biscuit&quot;]);
for (color, catnames) in &amp;cat_colors {
conn.execute(
&quot;INSERT INTO cat_colors (name) values (?1)&quot;,
&amp;[&amp;color.to_string()],
)?;
let last_id: String = conn.last_insert_rowid().to_string();
for cat in catnames {
conn.execute(
&quot;INSERT INTO cats (name, color_id) values (?1, ?2)&quot;,
&amp;[&amp;cat.to_string(), &amp;last_id],
)?;
}
}
let mut stmt = conn.prepare(
&quot;SELECT c.name, cc.name from cats c
INNER JOIN cat_colors cc
ON cc.id = c.color_id;&quot;,
)?;
let cats = stmt.query_map(NO_PARAMS, |row| {
Ok(Cat {
name: row.get(0)?,
color: row.get(1)?,
})
})?;
for cat in cats {
println!(&quot;Found cat {:?}&quot;, cat);
}
Ok(())
}
</code></pre></pre>
<h2><a class="header" href="#using-transactions" id="using-transactions">Using transactions</a></h2>
<p><a href="https://crates.io/crates/rusqlite/"><img src="https://badge-cache.kominick.com/crates/v/rusqlite.svg?label=rusqlite" alt="rusqlite-badge" /></a> <a href="https://crates.io/categories/database"><img src="https://badge-cache.kominick.com/badge/database--x.svg?style=social" alt="cat-database-badge" /></a></p>
<p><a href="https://docs.rs/rusqlite/*/rusqlite/struct.Connection.html#method.open"><code>Connection::open</code></a> will open the <code>cats.db</code> database from the top recipe.</p>
<p>Begin a transaction with <a href="https://docs.rs/rusqlite/*/rusqlite/struct.Connection.html#method.transaction"><code>Connection::transaction</code></a>. Transactions will
roll back unless committed explicitly with <a href="https://docs.rs/rusqlite/*/rusqlite/struct.Transaction.html#method.commit"><code>Transaction::commit</code></a>.</p>
<p>In the following example, colors add to a table having
a unique constraint on the color name. When an attempt to insert
a duplicate color is made, the transaction rolls back.</p>
<pre><pre class="playground"><code class="language-rust edition2018 no_run">use rusqlite::{Connection, Result, NO_PARAMS};
fn main() -&gt; Result&lt;()&gt; {
let mut conn = Connection::open(&quot;cats.db&quot;)?;
successful_tx(&amp;mut conn)?;
let res = rolled_back_tx(&amp;mut conn);
assert!(res.is_err());
Ok(())
}
fn successful_tx(conn: &amp;mut Connection) -&gt; Result&lt;()&gt; {
let tx = conn.transaction()?;
tx.execute(&quot;delete from cat_colors&quot;, NO_PARAMS)?;
tx.execute(&quot;insert into cat_colors (name) values (?1)&quot;, &amp;[&amp;&quot;lavender&quot;])?;
tx.execute(&quot;insert into cat_colors (name) values (?1)&quot;, &amp;[&amp;&quot;blue&quot;])?;
tx.commit()
}
fn rolled_back_tx(conn: &amp;mut Connection) -&gt; Result&lt;()&gt; {
let tx = conn.transaction()?;
tx.execute(&quot;delete from cat_colors&quot;, NO_PARAMS)?;
tx.execute(&quot;insert into cat_colors (name) values (?1)&quot;, &amp;[&amp;&quot;lavender&quot;])?;
tx.execute(&quot;insert into cat_colors (name) values (?1)&quot;, &amp;[&amp;&quot;blue&quot;])?;
tx.execute(&quot;insert into cat_colors (name) values (?1)&quot;, &amp;[&amp;&quot;lavender&quot;])?;
tx.commit()
}
</code></pre></pre>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#working-with-postgres" id="working-with-postgres">Working with Postgres</a></h1>
<h2><a class="header" href="#create-tables-in-a-postgres-database" id="create-tables-in-a-postgres-database">Create tables in a Postgres database</a></h2>
<p><a href="https://docs.rs/postgres/0.15.2/postgres/"><img src="https://badge-cache.kominick.com/crates/v/postgres.svg?label=postgres" alt="postgres-badge" /></a> <a href="https://crates.io/categories/database"><img src="https://badge-cache.kominick.com/badge/database--x.svg?style=social" alt="cat-database-badge" /></a></p>
<p>Use the <a href="https://docs.rs/postgres/0.17.2/postgres/"><code>postgres</code></a> crate to create tables in a Postgres database.</p>
<p><a href="https://docs.rs/postgres/0.17.2/postgres/struct.Client.html#method.connect"><code>Client::connect</code></a> helps in connecting to an existing database. The recipe uses a URL string format with <code>Client::connect</code>. It assumes an existing database named <code>library</code>, the username is <code>postgres</code> and the password is <code>postgres</code>.</p>
<pre><pre class="playground"><code class="language-rust edition2018 no_run">use postgres::{Client, NoTls, Error};
fn main() -&gt; Result&lt;(), Error&gt; {
let mut client = Client::connect(&quot;postgresql://postgres:postgres@localhost/library&quot;, NoTls)?;
client.batch_execute(&quot;
CREATE TABLE IF NOT EXISTS author (
id SERIAL PRIMARY KEY,
name VARCHAR NOT NULL,
country VARCHAR NOT NULL
)
&quot;)?;
client.batch_execute(&quot;
CREATE TABLE IF NOT EXISTS book (
id SERIAL PRIMARY KEY,
title VARCHAR NOT NULL,
author_id INTEGER NOT NULL REFERENCES author
)
&quot;)?;
Ok(())
}
</code></pre></pre>
<h2><a class="header" href="#insert-and-query-data" id="insert-and-query-data">Insert and Query data</a></h2>
<p><a href="https://docs.rs/postgres/0.15.2/postgres/"><img src="https://badge-cache.kominick.com/crates/v/postgres.svg?label=postgres" alt="postgres-badge" /></a> <a href="https://crates.io/categories/database"><img src="https://badge-cache.kominick.com/badge/database--x.svg?style=social" alt="cat-database-badge" /></a></p>
<p>The recipe inserts data into the <code>author</code> table using <a href="https://docs.rs/postgres/0.17.2/postgres/struct.Client.html#method.execute"><code>execute</code></a> method of <code>Client</code>. Then, displays the data from the <code>author</code> table using <a href="https://docs.rs/postgres/0.17.2/postgres/struct.Client.html#method.query"><code>query</code></a> method of <code>Client</code>.</p>
<pre><pre class="playground"><code class="language-rust edition2018 no_run">use postgres::{Client, NoTls, Error};
use std::collections::HashMap;
struct Author {
_id: i32,
name: String,
country: String
}
fn main() -&gt; Result&lt;(), Error&gt; {
let mut client = Client::connect(&quot;postgresql://postgres:postgres@localhost/library&quot;,
NoTls)?;
let mut authors = HashMap::new();
authors.insert(String::from(&quot;Chinua Achebe&quot;), &quot;Nigeria&quot;);
authors.insert(String::from(&quot;Rabindranath Tagore&quot;), &quot;India&quot;);
authors.insert(String::from(&quot;Anita Nair&quot;), &quot;India&quot;);
for (key, value) in &amp;authors {
let author = Author {
_id: 0,
name: key.to_string(),
country: value.to_string()
};
client.execute(
&quot;INSERT INTO author (name, country) VALUES ($1, $2)&quot;,
&amp;[&amp;author.name, &amp;author.country],
)?;
}
for row in client.query(&quot;SELECT id, name, country FROM author&quot;, &amp;[])? {
let author = Author {
_id: row.get(0),
name: row.get(1),
country: row.get(2),
};
println!(&quot;Author {} is from {}&quot;, author.name, author.country);
}
Ok(())
}
</code></pre></pre>
<h2><a class="header" href="#aggregate-data" id="aggregate-data">Aggregate data</a></h2>
<p><a href="https://docs.rs/postgres/0.15.2/postgres/"><img src="https://badge-cache.kominick.com/crates/v/postgres.svg?label=postgres" alt="postgres-badge" /></a> <a href="https://crates.io/categories/database"><img src="https://badge-cache.kominick.com/badge/database--x.svg?style=social" alt="cat-database-badge" /></a></p>
<p>This recipe lists the nationalities of the first 7999 artists in the database of the <a href="https://github.com/MuseumofModernArt/collection/blob/master/Artists.csv"><code>Museum of Modern Art</code></a> in descending order.</p>
<pre><pre class="playground"><code class="language-rust edition2018 no_run">use postgres::{Client, Error, NoTls};
struct Nation {
nationality: String,
count: i64,
}
fn main() -&gt; Result&lt;(), Error&gt; {
let mut client = Client::connect(
&quot;postgresql://postgres:postgres@127.0.0.1/moma&quot;,
NoTls,
)?;
for row in client.query
(&quot;SELECT nationality, COUNT(nationality) AS count
FROM artists GROUP BY nationality ORDER BY count DESC&quot;, &amp;[])? {
let (nationality, count) : (Option&lt;String&gt;, Option&lt;i64&gt;)
= (row.get (0), row.get (1));
if nationality.is_some () &amp;&amp; count.is_some () {
let nation = Nation{
nationality: nationality.unwrap(),
count: count.unwrap(),
};
println!(&quot;{} {}&quot;, nation.nationality, nation.count);
}
}
Ok(())
}
</code></pre></pre>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#date-and-time-1" id="date-and-time-1">Date and Time</a></h1>
<table><thead><tr><th>Recipe</th><th>Crates</th><th>Categories</th></tr></thead><tbody>
<tr><td><a href="datetime/duration.html#measure-the-elapsed-time-between-two-code-sections">Measure elapsed time</a></td><td><a href="https://doc.rust-lang.org/std"><img src="https://badge-cache.kominick.com/badge/std-1.29.1-blue.svg" alt="std-badge" /></a></td><td><a href="https://crates.io/categories/date-and-time"><img src="https://badge-cache.kominick.com/badge/time--x.svg?style=social" alt="cat-time-badge" /></a></td></tr>
<tr><td><a href="datetime/duration.html#perform-checked-date-and-time-calculations">Perform checked date and time calculations</a></td><td><a href="https://docs.rs/chrono/"><img src="https://badge-cache.kominick.com/crates/v/chrono.svg?label=chrono" alt="chrono-badge" /></a></td><td><a href="https://crates.io/categories/date-and-time"><img src="https://badge-cache.kominick.com/badge/date_and_time--x.svg?style=social" alt="cat-date-and-time-badge" /></a></td></tr>
<tr><td><a href="datetime/duration.html#convert-a-local-time-to-another-timezone">Convert a local time to another timezone</a></td><td><a href="https://docs.rs/chrono/"><img src="https://badge-cache.kominick.com/crates/v/chrono.svg?label=chrono" alt="chrono-badge" /></a></td><td><a href="https://crates.io/categories/date-and-time"><img src="https://badge-cache.kominick.com/badge/date_and_time--x.svg?style=social" alt="cat-date-and-time-badge" /></a></td></tr>
<tr><td><a href="datetime/parse.html#examine-the-date-and-time">Examine the date and time</a></td><td><a href="https://docs.rs/chrono/"><img src="https://badge-cache.kominick.com/crates/v/chrono.svg?label=chrono" alt="chrono-badge" /></a></td><td><a href="https://crates.io/categories/date-and-time"><img src="https://badge-cache.kominick.com/badge/date_and_time--x.svg?style=social" alt="cat-date-and-time-badge" /></a></td></tr>
<tr><td><a href="datetime/parse.html#convert-date-to-unix-timestamp-and-vice-versa">Convert date to UNIX timestamp and vice versa</a></td><td><a href="https://docs.rs/chrono/"><img src="https://badge-cache.kominick.com/crates/v/chrono.svg?label=chrono" alt="chrono-badge" /></a></td><td><a href="https://crates.io/categories/date-and-time"><img src="https://badge-cache.kominick.com/badge/date_and_time--x.svg?style=social" alt="cat-date-and-time-badge" /></a></td></tr>
<tr><td><a href="datetime/parse.html#display-formatted-date-and-time">Display formatted date and time</a></td><td><a href="https://docs.rs/chrono/"><img src="https://badge-cache.kominick.com/crates/v/chrono.svg?label=chrono" alt="chrono-badge" /></a></td><td><a href="https://crates.io/categories/date-and-time"><img src="https://badge-cache.kominick.com/badge/date_and_time--x.svg?style=social" alt="cat-date-and-time-badge" /></a></td></tr>
<tr><td><a href="datetime/parse.html#parse-string-into-datetime-struct">Parse string into DateTime struct</a></td><td><a href="https://docs.rs/chrono/"><img src="https://badge-cache.kominick.com/crates/v/chrono.svg?label=chrono" alt="chrono-badge" /></a></td><td><a href="https://crates.io/categories/date-and-time"><img src="https://badge-cache.kominick.com/badge/date_and_time--x.svg?style=social" alt="cat-date-and-time-badge" /></a></td></tr>
</tbody></table>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#duration-and-calculation" id="duration-and-calculation">Duration and Calculation</a></h1>
<h2><a class="header" href="#measure-the-elapsed-time-between-two-code-sections" id="measure-the-elapsed-time-between-two-code-sections">Measure the elapsed time between two code sections</a></h2>
<p><a href="https://doc.rust-lang.org/std"><img src="https://badge-cache.kominick.com/badge/std-1.29.1-blue.svg" alt="std-badge" /></a> <a href="https://crates.io/categories/date-and-time"><img src="https://badge-cache.kominick.com/badge/time--x.svg?style=social" alt="cat-time-badge" /></a></p>
<p>Measures <a href="https://doc.rust-lang.org/std/time/struct.Instant.html#method.elapsed"><code>time::Instant::elapsed</code></a> since <a href="https://doc.rust-lang.org/std/time/struct.Instant.html#method.now"><code>time::Instant::now</code></a>.</p>
<p>Calling <a href="https://doc.rust-lang.org/std/time/struct.Instant.html#method.elapsed"><code>time::Instant::elapsed</code></a> returns a <a href="https://doc.rust-lang.org/std/time/struct.Duration.html"><code>time::Duration</code></a> that we print at the end of the example.
This method will not mutate or reset the <a href="https://doc.rust-lang.org/std/time/struct.Instant.html"><code>time::Instant</code></a> object.</p>
<pre><pre class="playground"><code class="language-rust edition2018">use std::time::{Duration, Instant};
<span class="boring">use std::thread;
</span><span class="boring">
</span><span class="boring">fn expensive_function() {
</span><span class="boring"> thread::sleep(Duration::from_secs(1));
</span><span class="boring">}
</span>
fn main() {
let start = Instant::now();
expensive_function();
let duration = start.elapsed();
println!(&quot;Time elapsed in expensive_function() is: {:?}&quot;, duration);
}
</code></pre></pre>
<h2><a class="header" href="#perform-checked-date-and-time-calculations" id="perform-checked-date-and-time-calculations">Perform checked date and time calculations</a></h2>
<p><a href="https://docs.rs/chrono/"><img src="https://badge-cache.kominick.com/crates/v/chrono.svg?label=chrono" alt="chrono-badge" /></a> <a href="https://crates.io/categories/date-and-time"><img src="https://badge-cache.kominick.com/badge/date_and_time--x.svg?style=social" alt="cat-date-and-time-badge" /></a></p>
<p>Calculates and displays the date and time two weeks from now using
<a href="https://docs.rs/chrono/*/chrono/struct.Date.html#method.checked_add_signed"><code>DateTime::checked_add_signed</code></a> and the date of the day before that using
<a href="https://docs.rs/chrono/*/chrono/struct.Date.html#method.checked_sub_signed"><code>DateTime::checked_sub_signed</code></a>. The methods return None if the date and time
cannot be calculated.</p>
<p>Escape sequences that are available for the
<a href="https://docs.rs/chrono/*/chrono/struct.DateTime.html#method.format"><code>DateTime::format</code></a> can be found at <a href="https://docs.rs/chrono/*/chrono/format/strftime/index.html"><code>chrono::format::strftime</code></a>.</p>
<pre><pre class="playground"><code class="language-rust edition2018">use chrono::{DateTime, Duration, Utc};
fn day_earlier(date_time: DateTime&lt;Utc&gt;) -&gt; Option&lt;DateTime&lt;Utc&gt;&gt; {
date_time.checked_sub_signed(Duration::days(1))
}
fn main() {
let now = Utc::now();
println!(&quot;{}&quot;, now);
let almost_three_weeks_from_now = now.checked_add_signed(Duration::weeks(2))
.and_then(|in_2weeks| in_2weeks.checked_add_signed(Duration::weeks(1)))
.and_then(day_earlier);
match almost_three_weeks_from_now {
Some(x) =&gt; println!(&quot;{}&quot;, x),
None =&gt; eprintln!(&quot;Almost three weeks from now overflows!&quot;),
}
match now.checked_add_signed(Duration::max_value()) {
Some(x) =&gt; println!(&quot;{}&quot;, x),
None =&gt; eprintln!(&quot;We can't use chrono to tell the time for the Solar System to complete more than one full orbit around the galactic center.&quot;),
}
}
</code></pre></pre>
<h2><a class="header" href="#convert-a-local-time-to-another-timezone" id="convert-a-local-time-to-another-timezone">Convert a local time to another timezone</a></h2>
<p><a href="https://docs.rs/chrono/"><img src="https://badge-cache.kominick.com/crates/v/chrono.svg?label=chrono" alt="chrono-badge" /></a> <a href="https://crates.io/categories/date-and-time"><img src="https://badge-cache.kominick.com/badge/date_and_time--x.svg?style=social" alt="cat-date-and-time-badge" /></a></p>
<p>Gets the local time and displays it using <a href="https://docs.rs/chrono/*/chrono/offset/struct.Local.html#method.now"><code>offset::Local::now</code></a> and then converts it to the UTC standard using the <a href="https://docs.rs/chrono/*/chrono/struct.DateTime.html#method.from_utc"><code>DateTime::from_utc</code></a> struct method. A time is then converted using the <a href="https://docs.rs/chrono/*/chrono/offset/struct.FixedOffset.html"><code>offset::FixedOffset</code></a> struct and the UTC time is then converted to UTC+8 and UTC-2.</p>
<pre><pre class="playground"><code class="language-rust edition2018">
use chrono::{DateTime, FixedOffset, Local, Utc};
fn main() {
let local_time = Local::now();
let utc_time = DateTime::&lt;Utc&gt;::from_utc(local_time.naive_utc(), Utc);
let china_timezone = FixedOffset::east(8 * 3600);
let rio_timezone = FixedOffset::west(2 * 3600);
println!(&quot;Local time now is {}&quot;, local_time);
println!(&quot;UTC time now is {}&quot;, utc_time);
println!(
&quot;Time in Hong Kong now is {}&quot;,
utc_time.with_timezone(&amp;china_timezone)
);
println!(&quot;Time in Rio de Janeiro now is {}&quot;, utc_time.with_timezone(&amp;rio_timezone));
}
</code></pre></pre>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#parsing-and-displaying" id="parsing-and-displaying">Parsing and Displaying</a></h1>
<h2><a class="header" href="#examine-the-date-and-time" id="examine-the-date-and-time">Examine the date and time</a></h2>
<p><a href="https://docs.rs/chrono/"><img src="https://badge-cache.kominick.com/crates/v/chrono.svg?label=chrono" alt="chrono-badge" /></a> <a href="https://crates.io/categories/date-and-time"><img src="https://badge-cache.kominick.com/badge/date_and_time--x.svg?style=social" alt="cat-date-and-time-badge" /></a></p>
<p>Gets the current UTC <a href="https://docs.rs/chrono/*/chrono/struct.DateTime.html"><code>DateTime</code></a> and its hour/minute/second via <a href="https://docs.rs/chrono/*/chrono/trait.Timelike.html"><code>Timelike</code></a>
and its year/month/day/weekday via <a href="https://docs.rs/chrono/*/chrono/trait.Datelike.html"><code>Datelike</code></a>.</p>
<pre><pre class="playground"><code class="language-rust edition2018">use chrono::{Datelike, Timelike, Utc};
fn main() {
let now = Utc::now();
let (is_pm, hour) = now.hour12();
println!(
&quot;The current UTC time is {:02}:{:02}:{:02} {}&quot;,
hour,
now.minute(),
now.second(),
if is_pm { &quot;PM&quot; } else { &quot;AM&quot; }
);
println!(
&quot;And there have been {} seconds since midnight&quot;,
now.num_seconds_from_midnight()
);
let (is_common_era, year) = now.year_ce();
println!(
&quot;The current UTC date is {}-{:02}-{:02} {:?} ({})&quot;,
year,
now.month(),
now.day(),
now.weekday(),
if is_common_era { &quot;CE&quot; } else { &quot;BCE&quot; }
);
println!(
&quot;And the Common Era began {} days ago&quot;,
now.num_days_from_ce()
);
}
</code></pre></pre>
<h2><a class="header" href="#convert-date-to-unix-timestamp-and-vice-versa" id="convert-date-to-unix-timestamp-and-vice-versa">Convert date to UNIX timestamp and vice versa</a></h2>
<p><a href="https://docs.rs/chrono/"><img src="https://badge-cache.kominick.com/crates/v/chrono.svg?label=chrono" alt="chrono-badge" /></a> <a href="https://crates.io/categories/date-and-time"><img src="https://badge-cache.kominick.com/badge/date_and_time--x.svg?style=social" alt="cat-date-and-time-badge" /></a></p>
<p>Converts a date given by <a href="https://docs.rs/chrono/*/chrono/naive/struct.NaiveDate.html#method.from_ymd"><code>NaiveDate::from_ymd</code></a> and <a href="https://docs.rs/chrono/*/chrono/naive/struct.NaiveTime.html#method.from_hms"><code>NaiveTime::from_hms</code></a>
to <a href="https://en.wikipedia.org/wiki/Unix_time">UNIX timestamp</a> using <a href="https://docs.rs/chrono/*/chrono/naive/struct.NaiveDateTime.html#method.timestamp"><code>NaiveDateTime::timestamp</code></a>.
Then it calculates what was the date after one billion seconds
since January 1, 1970 0:00:00 UTC, using <a href="https://docs.rs/chrono/*/chrono/naive/struct.NaiveDateTime.html#method.from_timestamp"><code>NaiveDateTime::from_timestamp</code></a>.</p>
<pre><pre class="playground"><code class="language-rust edition2018">
use chrono::{NaiveDate, NaiveDateTime};
fn main() {
let date_time: NaiveDateTime = NaiveDate::from_ymd(2017, 11, 12).and_hms(17, 33, 44);
println!(
&quot;Number of seconds between 1970-01-01 00:00:00 and {} is {}.&quot;,
date_time, date_time.timestamp());
let date_time_after_a_billion_seconds = NaiveDateTime::from_timestamp(1_000_000_000, 0);
println!(
&quot;Date after a billion seconds since 1970-01-01 00:00:00 was {}.&quot;,
date_time_after_a_billion_seconds);
}
</code></pre></pre>
<h2><a class="header" href="#display-formatted-date-and-time" id="display-formatted-date-and-time">Display formatted date and time</a></h2>
<p><a href="https://docs.rs/chrono/"><img src="https://badge-cache.kominick.com/crates/v/chrono.svg?label=chrono" alt="chrono-badge" /></a> <a href="https://crates.io/categories/date-and-time"><img src="https://badge-cache.kominick.com/badge/date_and_time--x.svg?style=social" alt="cat-date-and-time-badge" /></a></p>
<p>Gets and displays the current time in UTC using <a href="https://docs.rs/chrono/*/chrono/offset/struct.Utc.html#method.now"><code>Utc::now</code></a>. Formats the
current time in the well-known formats <a href="https://www.ietf.org/rfc/rfc2822.txt">RFC 2822</a> using <a href="https://docs.rs/chrono/*/chrono/struct.DateTime.html#method.to_rfc2822"><code>DateTime::to_rfc2822</code></a>
and <a href="https://www.ietf.org/rfc/rfc3339.txt">RFC 3339</a> using <a href="https://docs.rs/chrono/*/chrono/struct.DateTime.html#method.to_rfc3339"><code>DateTime::to_rfc3339</code></a>, and in a custom format using
<a href="https://docs.rs/chrono/*/chrono/struct.DateTime.html#method.format"><code>DateTime::format</code></a>.</p>
<pre><pre class="playground"><code class="language-rust edition2018">use chrono::{DateTime, Utc};
fn main() {
let now: DateTime&lt;Utc&gt; = Utc::now();
println!(&quot;UTC now is: {}&quot;, now);
println!(&quot;UTC now in RFC 2822 is: {}&quot;, now.to_rfc2822());
println!(&quot;UTC now in RFC 3339 is: {}&quot;, now.to_rfc3339());
println!(&quot;UTC now in a custom format is: {}&quot;, now.format(&quot;%a %b %e %T %Y&quot;));
}
</code></pre></pre>
<h2><a class="header" href="#parse-string-into-datetime-struct" id="parse-string-into-datetime-struct">Parse string into DateTime struct</a></h2>
<p><a href="https://docs.rs/chrono/"><img src="https://badge-cache.kominick.com/crates/v/chrono.svg?label=chrono" alt="chrono-badge" /></a> <a href="https://crates.io/categories/date-and-time"><img src="https://badge-cache.kominick.com/badge/date_and_time--x.svg?style=social" alt="cat-date-and-time-badge" /></a></p>
<p>Parses a <a href="https://docs.rs/chrono/*/chrono/struct.DateTime.html"><code>DateTime</code></a> struct from strings representing the well-known formats
<a href="https://www.ietf.org/rfc/rfc2822.txt">RFC 2822</a>, <a href="https://www.ietf.org/rfc/rfc3339.txt">RFC 3339</a>, and a custom format, using
<a href="https://docs.rs/chrono/*/chrono/struct.DateTime.html#method.parse_from_rfc2822"><code>DateTime::parse_from_rfc2822</code></a>, <a href="https://docs.rs/chrono/*/chrono/struct.DateTime.html#method.parse_from_rfc3339"><code>DateTime::parse_from_rfc3339</code></a>, and
<a href="https://docs.rs/chrono/*/chrono/struct.DateTime.html#method.parse_from_str"><code>DateTime::parse_from_str</code></a> respectively.</p>
<p>Escape sequences that are available for the <a href="https://docs.rs/chrono/*/chrono/struct.DateTime.html#method.parse_from_str"><code>DateTime::parse_from_str</code></a> can be
found at <a href="https://docs.rs/chrono/*/chrono/format/strftime/index.html"><code>chrono::format::strftime</code></a>. Note that the <a href="https://docs.rs/chrono/*/chrono/struct.DateTime.html#method.parse_from_str"><code>DateTime::parse_from_str</code></a>
requires that such a DateTime struct must be creatable that it uniquely
identifies a date and a time. For parsing dates and times without timezones use
<a href="https://docs.rs/chrono/*/chrono/naive/struct.NaiveDate.html"><code>NaiveDate</code></a>, <a href="https://docs.rs/chrono/*/chrono/naive/struct.NaiveTime.html"><code>NaiveTime</code></a>, and <a href="https://docs.rs/chrono/*/chrono/naive/struct.NaiveDateTime.html"><code>NaiveDateTime</code></a>.</p>
<pre><pre class="playground"><code class="language-rust edition2018">use chrono::{DateTime, NaiveDate, NaiveDateTime, NaiveTime};
use chrono::format::ParseError;
fn main() -&gt; Result&lt;(), ParseError&gt; {
let rfc2822 = DateTime::parse_from_rfc2822(&quot;Tue, 1 Jul 2003 10:52:37 +0200&quot;)?;
println!(&quot;{}&quot;, rfc2822);
let rfc3339 = DateTime::parse_from_rfc3339(&quot;1996-12-19T16:39:57-08:00&quot;)?;
println!(&quot;{}&quot;, rfc3339);
let custom = DateTime::parse_from_str(&quot;5.8.1994 8:00 am +0000&quot;, &quot;%d.%m.%Y %H:%M %P %z&quot;)?;
println!(&quot;{}&quot;, custom);
let time_only = NaiveTime::parse_from_str(&quot;23:56:04&quot;, &quot;%H:%M:%S&quot;)?;
println!(&quot;{}&quot;, time_only);
let date_only = NaiveDate::parse_from_str(&quot;2015-09-05&quot;, &quot;%Y-%m-%d&quot;)?;
println!(&quot;{}&quot;, date_only);
let no_timezone = NaiveDateTime::parse_from_str(&quot;2015-09-05 23:56:04&quot;, &quot;%Y-%m-%d %H:%M:%S&quot;)?;
println!(&quot;{}&quot;, no_timezone);
Ok(())
}
</code></pre></pre>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#development-tools-1" id="development-tools-1">Development Tools</a></h1>
<h2><a class="header" href="#debugging-1" id="debugging-1">Debugging</a></h2>
<table><thead><tr><th>Recipe</th><th>Crates</th><th>Categories</th></tr></thead><tbody>
<tr><td><a href="development_tools/debugging/log.html#log-a-debug-message-to-the-console">Log a debug message to the console</a></td><td><a href="https://docs.rs/log/"><img src="https://badge-cache.kominick.com/crates/v/log.svg?label=log" alt="log-badge" /></a> <a href="https://docs.rs/env_logger/"><img src="https://badge-cache.kominick.com/crates/v/env_logger.svg?label=env_logger" alt="env_logger-badge" /></a></td><td><a href="https://crates.io/categories/debugging"><img src="https://badge-cache.kominick.com/badge/debugging--x.svg?style=social" alt="cat-debugging-badge" /></a></td></tr>
<tr><td><a href="development_tools/debugging/log.html#log-an-error-message-to-the-console">Log an error message to the console</a></td><td><a href="https://docs.rs/log/"><img src="https://badge-cache.kominick.com/crates/v/log.svg?label=log" alt="log-badge" /></a> <a href="https://docs.rs/env_logger/"><img src="https://badge-cache.kominick.com/crates/v/env_logger.svg?label=env_logger" alt="env_logger-badge" /></a></td><td><a href="https://crates.io/categories/debugging"><img src="https://badge-cache.kominick.com/badge/debugging--x.svg?style=social" alt="cat-debugging-badge" /></a></td></tr>
<tr><td><a href="development_tools/debugging/log.html#log-to-stdout-instead-of-stderr">Log to stdout instead of stderr</a></td><td><a href="https://docs.rs/log/"><img src="https://badge-cache.kominick.com/crates/v/log.svg?label=log" alt="log-badge" /></a> <a href="https://docs.rs/env_logger/"><img src="https://badge-cache.kominick.com/crates/v/env_logger.svg?label=env_logger" alt="env_logger-badge" /></a></td><td><a href="https://crates.io/categories/debugging"><img src="https://badge-cache.kominick.com/badge/debugging--x.svg?style=social" alt="cat-debugging-badge" /></a></td></tr>
<tr><td><a href="development_tools/debugging/log.html#log-messages-with-a-custom-logger">Log messages with a custom logger</a></td><td><a href="https://docs.rs/log/"><img src="https://badge-cache.kominick.com/crates/v/log.svg?label=log" alt="log-badge" /></a></td><td><a href="https://crates.io/categories/debugging"><img src="https://badge-cache.kominick.com/badge/debugging--x.svg?style=social" alt="cat-debugging-badge" /></a></td></tr>
<tr><td><a href="development_tools/debugging/log.html#log-to-the-unix-syslog">Log to the Unix syslog</a></td><td><a href="https://docs.rs/log/"><img src="https://badge-cache.kominick.com/crates/v/log.svg?label=log" alt="log-badge" /></a> <a href="https://docs.rs/syslog/"><img src="https://badge-cache.kominick.com/crates/v/syslog.svg?label=syslog" alt="syslog-badge" /></a></td><td><a href="https://crates.io/categories/debugging"><img src="https://badge-cache.kominick.com/badge/debugging--x.svg?style=social" alt="cat-debugging-badge" /></a></td></tr>
<tr><td><a href="development_tools/debugging/config_log.html#enable-log-levels-per-module">Enable log levels per module</a></td><td><a href="https://docs.rs/log/"><img src="https://badge-cache.kominick.com/crates/v/log.svg?label=log" alt="log-badge" /></a> <a href="https://docs.rs/env_logger/"><img src="https://badge-cache.kominick.com/crates/v/env_logger.svg?label=env_logger" alt="env_logger-badge" /></a></td><td><a href="https://crates.io/categories/debugging"><img src="https://badge-cache.kominick.com/badge/debugging--x.svg?style=social" alt="cat-debugging-badge" /></a></td></tr>
<tr><td><a href="development_tools/debugging/config_log.html#use-a-custom-environment-variable-to-set-up-logging">Use a custom environment variable to set up logging</a></td><td><a href="https://docs.rs/log/"><img src="https://badge-cache.kominick.com/crates/v/log.svg?label=log" alt="log-badge" /></a> <a href="https://docs.rs/env_logger/"><img src="https://badge-cache.kominick.com/crates/v/env_logger.svg?label=env_logger" alt="env_logger-badge" /></a></td><td><a href="https://crates.io/categories/debugging"><img src="https://badge-cache.kominick.com/badge/debugging--x.svg?style=social" alt="cat-debugging-badge" /></a></td></tr>
<tr><td><a href="development_tools/debugging/config_log.html#include-timestamp-in-log-messages">Include timestamp in log messages</a></td><td><a href="https://docs.rs/log/"><img src="https://badge-cache.kominick.com/crates/v/log.svg?label=log" alt="log-badge" /></a> <a href="https://docs.rs/env_logger/"><img src="https://badge-cache.kominick.com/crates/v/env_logger.svg?label=env_logger" alt="env_logger-badge" /></a> <a href="https://docs.rs/chrono/"><img src="https://badge-cache.kominick.com/crates/v/chrono.svg?label=chrono" alt="chrono-badge" /></a></td><td><a href="https://crates.io/categories/debugging"><img src="https://badge-cache.kominick.com/badge/debugging--x.svg?style=social" alt="cat-debugging-badge" /></a></td></tr>
<tr><td><a href="development_tools/debugging/config_log.html#log-messages-to-a-custom-location">Log messages to a custom location</a></td><td><a href="https://docs.rs/log/"><img src="https://badge-cache.kominick.com/crates/v/log.svg?label=log" alt="log-badge" /></a> <a href="https://docs.rs/log4rs/"><img src="https://badge-cache.kominick.com/crates/v/log4rs.svg?label=log4rs" alt="log4rs-badge" /></a></td><td><a href="https://crates.io/categories/debugging"><img src="https://badge-cache.kominick.com/badge/debugging--x.svg?style=social" alt="cat-debugging-badge" /></a></td></tr>
</tbody></table>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h2><a class="header" href="#versioning-1" id="versioning-1">Versioning</a></h2>
<table><thead><tr><th>Recipe</th><th>Crates</th><th>Categories</th></tr></thead><tbody>
<tr><td><a href="development_tools/versioning.html#parse-and-increment-a-version-string">Parse and increment a version string</a></td><td><a href="https://docs.rs/semver/"><img src="https://badge-cache.kominick.com/crates/v/semver.svg?label=semver" alt="semver-badge" /></a></td><td><a href="https://crates.io/categories/config"><img src="https://badge-cache.kominick.com/badge/config--x.svg?style=social" alt="cat-config-badge" /></a></td></tr>
<tr><td><a href="development_tools/versioning.html#parse-a-complex-version-string">Parse a complex version string</a></td><td><a href="https://docs.rs/semver/"><img src="https://badge-cache.kominick.com/crates/v/semver.svg?label=semver" alt="semver-badge" /></a></td><td><a href="https://crates.io/categories/config"><img src="https://badge-cache.kominick.com/badge/config--x.svg?style=social" alt="cat-config-badge" /></a></td></tr>
<tr><td><a href="development_tools/versioning.html#check-if-given-version-is-pre-release">Check if given version is pre-release</a></td><td><a href="https://docs.rs/semver/"><img src="https://badge-cache.kominick.com/crates/v/semver.svg?label=semver" alt="semver-badge" /></a></td><td><a href="https://crates.io/categories/config"><img src="https://badge-cache.kominick.com/badge/config--x.svg?style=social" alt="cat-config-badge" /></a></td></tr>
<tr><td><a href="development_tools/versioning.html#find-the-latest-version-satisfying-given-range">Find the latest version satisfying given range</a></td><td><a href="https://docs.rs/semver/"><img src="https://badge-cache.kominick.com/crates/v/semver.svg?label=semver" alt="semver-badge" /></a></td><td><a href="https://crates.io/categories/config"><img src="https://badge-cache.kominick.com/badge/config--x.svg?style=social" alt="cat-config-badge" /></a></td></tr>
<tr><td><a href="development_tools/versioning.html#check-external-command-version-for-compatibility">Check external command version for compatibility</a></td><td><a href="https://docs.rs/semver/"><img src="https://badge-cache.kominick.com/crates/v/semver.svg?label=semver" alt="semver-badge" /></a></td><td><a href="https://crates.io/categories/text-processing"><img src="https://badge-cache.kominick.com/badge/text_processing--x.svg?style=social" alt="cat-text-processing-badge" /></a> <a href="https://crates.io/categories/os"><img src="https://badge-cache.kominick.com/badge/OS--x.svg?style=social" alt="cat-os-badge" /></a></td></tr>
</tbody></table>
<h2><a class="header" href="#build-time-1" id="build-time-1">Build Time</a></h2>
<table><thead><tr><th>Recipe</th><th>Crates</th><th>Categories</th></tr></thead><tbody>
<tr><td><a href="development_tools/build_tools.html#compile-and-link-statically-to-a-bundled-c-library">Compile and link statically to a bundled C library</a></td><td><a href="https://docs.rs/cc"><img src="https://badge-cache.kominick.com/crates/v/cc.svg?label=cc" alt="cc-badge" /></a></td><td><a href="https://crates.io/categories/development-tools"><img src="https://badge-cache.kominick.com/badge/development_tools--x.svg?style=social" alt="cat-development-tools-badge" /></a></td></tr>
<tr><td><a href="development_tools/build_tools.html#compile-and-link-statically-to-a-bundled-c-library-1">Compile and link statically to a bundled C++ library</a></td><td><a href="https://docs.rs/cc"><img src="https://badge-cache.kominick.com/crates/v/cc.svg?label=cc" alt="cc-badge" /></a></td><td><a href="https://crates.io/categories/development-tools"><img src="https://badge-cache.kominick.com/badge/development_tools--x.svg?style=social" alt="cat-development-tools-badge" /></a></td></tr>
<tr><td><a href="development_tools/build_tools.html#compile-a-c-library-while-setting-custom-defines">Compile a C library while setting custom defines</a></td><td><a href="https://docs.rs/cc"><img src="https://badge-cache.kominick.com/crates/v/cc.svg?label=cc" alt="cc-badge" /></a></td><td><a href="https://crates.io/categories/development-tools"><img src="https://badge-cache.kominick.com/badge/development_tools--x.svg?style=social" alt="cat-development-tools-badge" /></a></td></tr>
</tbody></table>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h2><a class="header" href="#debugging-2" id="debugging-2">Debugging</a></h2>
<table><thead><tr><th>Recipe</th><th>Crates</th><th>Categories</th></tr></thead><tbody>
<tr><td><a href="development_tools/development_tools/debugging/log.html#log-a-debug-message-to-the-console">Log a debug message to the console</a></td><td><a href="https://docs.rs/log/"><img src="https://badge-cache.kominick.com/crates/v/log.svg?label=log" alt="log-badge" /></a> <a href="https://docs.rs/env_logger/"><img src="https://badge-cache.kominick.com/crates/v/env_logger.svg?label=env_logger" alt="env_logger-badge" /></a></td><td><a href="https://crates.io/categories/debugging"><img src="https://badge-cache.kominick.com/badge/debugging--x.svg?style=social" alt="cat-debugging-badge" /></a></td></tr>
<tr><td><a href="development_tools/development_tools/debugging/log.html#log-an-error-message-to-the-console">Log an error message to the console</a></td><td><a href="https://docs.rs/log/"><img src="https://badge-cache.kominick.com/crates/v/log.svg?label=log" alt="log-badge" /></a> <a href="https://docs.rs/env_logger/"><img src="https://badge-cache.kominick.com/crates/v/env_logger.svg?label=env_logger" alt="env_logger-badge" /></a></td><td><a href="https://crates.io/categories/debugging"><img src="https://badge-cache.kominick.com/badge/debugging--x.svg?style=social" alt="cat-debugging-badge" /></a></td></tr>
<tr><td><a href="development_tools/development_tools/debugging/log.html#log-to-stdout-instead-of-stderr">Log to stdout instead of stderr</a></td><td><a href="https://docs.rs/log/"><img src="https://badge-cache.kominick.com/crates/v/log.svg?label=log" alt="log-badge" /></a> <a href="https://docs.rs/env_logger/"><img src="https://badge-cache.kominick.com/crates/v/env_logger.svg?label=env_logger" alt="env_logger-badge" /></a></td><td><a href="https://crates.io/categories/debugging"><img src="https://badge-cache.kominick.com/badge/debugging--x.svg?style=social" alt="cat-debugging-badge" /></a></td></tr>
<tr><td><a href="development_tools/development_tools/debugging/log.html#log-messages-with-a-custom-logger">Log messages with a custom logger</a></td><td><a href="https://docs.rs/log/"><img src="https://badge-cache.kominick.com/crates/v/log.svg?label=log" alt="log-badge" /></a></td><td><a href="https://crates.io/categories/debugging"><img src="https://badge-cache.kominick.com/badge/debugging--x.svg?style=social" alt="cat-debugging-badge" /></a></td></tr>
<tr><td><a href="development_tools/development_tools/debugging/log.html#log-to-the-unix-syslog">Log to the Unix syslog</a></td><td><a href="https://docs.rs/log/"><img src="https://badge-cache.kominick.com/crates/v/log.svg?label=log" alt="log-badge" /></a> <a href="https://docs.rs/syslog/"><img src="https://badge-cache.kominick.com/crates/v/syslog.svg?label=syslog" alt="syslog-badge" /></a></td><td><a href="https://crates.io/categories/debugging"><img src="https://badge-cache.kominick.com/badge/debugging--x.svg?style=social" alt="cat-debugging-badge" /></a></td></tr>
<tr><td><a href="development_tools/development_tools/debugging/config_log.html#enable-log-levels-per-module">Enable log levels per module</a></td><td><a href="https://docs.rs/log/"><img src="https://badge-cache.kominick.com/crates/v/log.svg?label=log" alt="log-badge" /></a> <a href="https://docs.rs/env_logger/"><img src="https://badge-cache.kominick.com/crates/v/env_logger.svg?label=env_logger" alt="env_logger-badge" /></a></td><td><a href="https://crates.io/categories/debugging"><img src="https://badge-cache.kominick.com/badge/debugging--x.svg?style=social" alt="cat-debugging-badge" /></a></td></tr>
<tr><td><a href="development_tools/development_tools/debugging/config_log.html#use-a-custom-environment-variable-to-set-up-logging">Use a custom environment variable to set up logging</a></td><td><a href="https://docs.rs/log/"><img src="https://badge-cache.kominick.com/crates/v/log.svg?label=log" alt="log-badge" /></a> <a href="https://docs.rs/env_logger/"><img src="https://badge-cache.kominick.com/crates/v/env_logger.svg?label=env_logger" alt="env_logger-badge" /></a></td><td><a href="https://crates.io/categories/debugging"><img src="https://badge-cache.kominick.com/badge/debugging--x.svg?style=social" alt="cat-debugging-badge" /></a></td></tr>
<tr><td><a href="development_tools/development_tools/debugging/config_log.html#include-timestamp-in-log-messages">Include timestamp in log messages</a></td><td><a href="https://docs.rs/log/"><img src="https://badge-cache.kominick.com/crates/v/log.svg?label=log" alt="log-badge" /></a> <a href="https://docs.rs/env_logger/"><img src="https://badge-cache.kominick.com/crates/v/env_logger.svg?label=env_logger" alt="env_logger-badge" /></a> <a href="https://docs.rs/chrono/"><img src="https://badge-cache.kominick.com/crates/v/chrono.svg?label=chrono" alt="chrono-badge" /></a></td><td><a href="https://crates.io/categories/debugging"><img src="https://badge-cache.kominick.com/badge/debugging--x.svg?style=social" alt="cat-debugging-badge" /></a></td></tr>
<tr><td><a href="development_tools/development_tools/debugging/config_log.html#log-messages-to-a-custom-location">Log messages to a custom location</a></td><td><a href="https://docs.rs/log/"><img src="https://badge-cache.kominick.com/crates/v/log.svg?label=log" alt="log-badge" /></a> <a href="https://docs.rs/log4rs/"><img src="https://badge-cache.kominick.com/crates/v/log4rs.svg?label=log4rs" alt="log4rs-badge" /></a></td><td><a href="https://crates.io/categories/debugging"><img src="https://badge-cache.kominick.com/badge/debugging--x.svg?style=social" alt="cat-debugging-badge" /></a></td></tr>
</tbody></table>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#log-messages" id="log-messages">Log Messages</a></h1>
<h2><a class="header" href="#log-a-debug-message-to-the-console" id="log-a-debug-message-to-the-console">Log a debug message to the console</a></h2>
<p><a href="https://docs.rs/log/"><img src="https://badge-cache.kominick.com/crates/v/log.svg?label=log" alt="log-badge" /></a> <a href="https://docs.rs/env_logger/"><img src="https://badge-cache.kominick.com/crates/v/env_logger.svg?label=env_logger" alt="env_logger-badge" /></a> <a href="https://crates.io/categories/debugging"><img src="https://badge-cache.kominick.com/badge/debugging--x.svg?style=social" alt="cat-debugging-badge" /></a></p>
<p>The <code>log</code> crate provides logging utilities. The <code>env_logger</code> crate configures
logging via an environment variable. The <a href="https://docs.rs/log/*/log/macro.debug.html"><code>log::debug!</code></a> macro works like other
<a href="https://doc.rust-lang.org/std/fmt/"><code>std::fmt</code></a> formatted strings.</p>
<pre><pre class="playground"><code class="language-rust edition2018">
fn execute_query(query: &amp;str) {
log::debug!(&quot;Executing query: {}&quot;, query);
}
fn main() {
env_logger::init();
execute_query(&quot;DROP TABLE students&quot;);
}
</code></pre></pre>
<p>No output prints when running this code. By default, the
log level is <code>error</code>, and any lower levels are dropped.</p>
<p>Set the <code>RUST_LOG</code> environment variable to print the message:</p>
<pre><code>$ RUST_LOG=debug cargo run
</code></pre>
<p>Cargo prints debugging information then the
following line at the very end of the output:</p>
<pre><code>DEBUG:main: Executing query: DROP TABLE students
</code></pre>
<h2><a class="header" href="#log-an-error-message-to-the-console" id="log-an-error-message-to-the-console">Log an error message to the console</a></h2>
<p><a href="https://docs.rs/log/"><img src="https://badge-cache.kominick.com/crates/v/log.svg?label=log" alt="log-badge" /></a> <a href="https://docs.rs/env_logger/"><img src="https://badge-cache.kominick.com/crates/v/env_logger.svg?label=env_logger" alt="env_logger-badge" /></a> <a href="https://crates.io/categories/debugging"><img src="https://badge-cache.kominick.com/badge/debugging--x.svg?style=social" alt="cat-debugging-badge" /></a></p>
<p>Proper error handling considers exceptions exceptional. Here, an error logs
to stderr with <code>log</code>'s convenience macro <a href="https://docs.rs/log/*/log/macro.error.html"><code>log::error!</code></a>.</p>
<pre><pre class="playground"><code class="language-rust edition2018">
fn execute_query(_query: &amp;str) -&gt; Result&lt;(), &amp;'static str&gt; {
Err(&quot;I'm afraid I can't do that&quot;)
}
fn main() {
env_logger::init();
let response = execute_query(&quot;DROP TABLE students&quot;);
if let Err(err) = response {
log::error!(&quot;Failed to execute query: {}&quot;, err);
}
}
</code></pre></pre>
<h2><a class="header" href="#log-to-stdout-instead-of-stderr" id="log-to-stdout-instead-of-stderr">Log to stdout instead of stderr</a></h2>
<p><a href="https://docs.rs/log/"><img src="https://badge-cache.kominick.com/crates/v/log.svg?label=log" alt="log-badge" /></a> <a href="https://docs.rs/env_logger/"><img src="https://badge-cache.kominick.com/crates/v/env_logger.svg?label=env_logger" alt="env_logger-badge" /></a> <a href="https://crates.io/categories/debugging"><img src="https://badge-cache.kominick.com/badge/debugging--x.svg?style=social" alt="cat-debugging-badge" /></a></p>
<p>Creates a custom logger configuration using the <a href="https://docs.rs/env_logger/*/env_logger/struct.Builder.html#method.target"><code>Builder::target</code></a> to set the target of the log output to <a href="https://docs.rs/env_logger/*/env_logger/fmt/enum.Target.html"><code>Target::Stdout</code></a>.</p>
<pre><pre class="playground"><code class="language-rust edition2018">
use env_logger::{Builder, Target};
fn main() {
Builder::new()
.target(Target::Stdout)
.init();
log::error!(&quot;This error has been printed to Stdout&quot;);
}
</code></pre></pre>
<h2><a class="header" href="#log-messages-with-a-custom-logger" id="log-messages-with-a-custom-logger">Log messages with a custom logger</a></h2>
<p><a href="https://docs.rs/log/"><img src="https://badge-cache.kominick.com/crates/v/log.svg?label=log" alt="log-badge" /></a> <a href="https://crates.io/categories/debugging"><img src="https://badge-cache.kominick.com/badge/debugging--x.svg?style=social" alt="cat-debugging-badge" /></a></p>
<p>Implements a custom logger <code>ConsoleLogger</code> which prints to stdout.
In order to use the logging macros, <code>ConsoleLogger</code> implements
the <a href="https://docs.rs/log/*/log/trait.Log.html"><code>log::Log</code></a> trait and <a href="https://docs.rs/log/*/log/fn.set_logger.html"><code>log::set_logger</code></a> installs it.</p>
<pre><pre class="playground"><code class="language-rust edition2018">use log::{Record, Level, Metadata, LevelFilter, SetLoggerError};
static CONSOLE_LOGGER: ConsoleLogger = ConsoleLogger;
struct ConsoleLogger;
impl log::Log for ConsoleLogger {
fn enabled(&amp;self, metadata: &amp;Metadata) -&gt; bool {
metadata.level() &lt;= Level::Info
}
fn log(&amp;self, record: &amp;Record) {
if self.enabled(record.metadata()) {
println!(&quot;Rust says: {} - {}&quot;, record.level(), record.args());
}
}
fn flush(&amp;self) {}
}
fn main() -&gt; Result&lt;(), SetLoggerError&gt; {
log::set_logger(&amp;CONSOLE_LOGGER)?;
log::set_max_level(LevelFilter::Info);
log::info!(&quot;hello log&quot;);
log::warn!(&quot;warning&quot;);
log::error!(&quot;oops&quot;);
Ok(())
}
</code></pre></pre>
<h2><a class="header" href="#log-to-the-unix-syslog" id="log-to-the-unix-syslog">Log to the Unix syslog</a></h2>
<p><a href="https://docs.rs/log/"><img src="https://badge-cache.kominick.com/crates/v/log.svg?label=log" alt="log-badge" /></a> <a href="https://docs.rs/syslog/"><img src="https://badge-cache.kominick.com/crates/v/syslog.svg?label=syslog" alt="syslog-badge" /></a> <a href="https://crates.io/categories/debugging"><img src="https://badge-cache.kominick.com/badge/debugging--x.svg?style=social" alt="cat-debugging-badge" /></a></p>
<p>Logs messages to <a href="https://www.gnu.org/software/libc/manual/html_node/Overview-of-Syslog.html">UNIX syslog</a>. Initializes logger backend
with <a href="https://docs.rs/syslog/*/syslog/fn.init.html"><code>syslog::init</code></a>. <a href="https://docs.rs/syslog/*/syslog/enum.Facility.html"><code>syslog::Facility</code></a> records the program submitting
the log entry's classification, <a href="https://docs.rs/log/*/log/enum.LevelFilter.html"><code>log::LevelFilter</code></a> denotes allowed log verbosity
and <code>Option&lt;&amp;str&gt;</code> holds optional application name.</p>
<pre><pre class="playground"><code class="language-rust edition2018"><span class="boring">#[cfg(target_os = &quot;linux&quot;)]
</span><span class="boring">#[cfg(target_os = &quot;linux&quot;)]
</span>use syslog::{Facility, Error};
<span class="boring">#[cfg(target_os = &quot;linux&quot;)]
</span>fn main() -&gt; Result&lt;(), Error&gt; {
syslog::init(Facility::LOG_USER,
log::LevelFilter::Debug,
Some(&quot;My app name&quot;))?;
log::debug!(&quot;this is a debug {}&quot;, &quot;message&quot;);
log::error!(&quot;this is an error!&quot;);
Ok(())
}
<span class="boring">#[cfg(not(target_os = &quot;linux&quot;))]
</span><span class="boring">fn main() {
</span><span class="boring"> println!(&quot;So far, only Linux systems are supported.&quot;);
</span><span class="boring">}
</span></code></pre></pre>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#configure-logging" id="configure-logging">Configure Logging</a></h1>
<h2><a class="header" href="#enable-log-levels-per-module" id="enable-log-levels-per-module">Enable log levels per module</a></h2>
<p><a href="https://docs.rs/log/"><img src="https://badge-cache.kominick.com/crates/v/log.svg?label=log" alt="log-badge" /></a> <a href="https://docs.rs/env_logger/"><img src="https://badge-cache.kominick.com/crates/v/env_logger.svg?label=env_logger" alt="env_logger-badge" /></a> <a href="https://crates.io/categories/debugging"><img src="https://badge-cache.kominick.com/badge/debugging--x.svg?style=social" alt="cat-debugging-badge" /></a></p>
<p>Creates two modules <code>foo</code> and nested <code>foo::bar</code> with logging directives
controlled separately with <a href="https://docs.rs/env_logger/*/env_logger/#enabling-logging"><code>RUST_LOG</code></a> environmental variable.</p>
<pre><pre class="playground"><code class="language-rust edition2018">
mod foo {
mod bar {
pub fn run() {
log::warn!(&quot;[bar] warn&quot;);
log::info!(&quot;[bar] info&quot;);
log::debug!(&quot;[bar] debug&quot;);
}
}
pub fn run() {
log::warn!(&quot;[foo] warn&quot;);
log::info!(&quot;[foo] info&quot;);
log::debug!(&quot;[foo] debug&quot;);
bar::run();
}
}
fn main() {
env_logger::init();
log::warn!(&quot;[root] warn&quot;);
log::info!(&quot;[root] info&quot;);
log::debug!(&quot;[root] debug&quot;);
foo::run();
}
</code></pre></pre>
<p><a href="https://docs.rs/env_logger/*/env_logger/#enabling-logging"><code>RUST_LOG</code></a> environment variable controls <a href="https://docs.rs/env_logger/"><code>env_logger</code></a> output.
Module declarations take comma separated entries formatted like
<code>path::to::module=log_level</code>. Run the <code>test</code> application as follows:</p>
<pre><code class="language-bash">RUST_LOG=&quot;warn,test::foo=info,test::foo::bar=debug&quot; ./test
</code></pre>
<p>Sets the default <a href="https://docs.rs/log/*/log/enum.Level.html"><code>log::Level</code></a> to <code>warn</code>, module <code>foo</code> and module <code>foo::bar</code>
to <code>info</code> and <code>debug</code>.</p>
<pre><code class="language-bash">WARN:test: [root] warn
WARN:test::foo: [foo] warn
INFO:test::foo: [foo] info
WARN:test::foo::bar: [bar] warn
INFO:test::foo::bar: [bar] info
DEBUG:test::foo::bar: [bar] debug
</code></pre>
<h2><a class="header" href="#use-a-custom-environment-variable-to-set-up-logging" id="use-a-custom-environment-variable-to-set-up-logging">Use a custom environment variable to set up logging</a></h2>
<p><a href="https://docs.rs/log/"><img src="https://badge-cache.kominick.com/crates/v/log.svg?label=log" alt="log-badge" /></a> <a href="https://docs.rs/env_logger/"><img src="https://badge-cache.kominick.com/crates/v/env_logger.svg?label=env_logger" alt="env_logger-badge" /></a> <a href="https://crates.io/categories/debugging"><img src="https://badge-cache.kominick.com/badge/debugging--x.svg?style=social" alt="cat-debugging-badge" /></a></p>
<p><a href="https://docs.rs/env_logger/*/env_logger/struct.Builder.html"><code>Builder</code></a> configures logging.</p>
<p><a href="https://docs.rs/env_logger/*/env_logger/struct.Builder.html#method.parse"><code>Builder::parse</code></a> parses <code>MY_APP_LOG</code>
environment variable contents in the form of <a href="https://docs.rs/env_logger/*/env_logger/#enabling-logging"><code>RUST_LOG</code></a> syntax.
Then, <a href="https://docs.rs/env_logger/*/env_logger/struct.Builder.html#method.init"><code>Builder::init</code></a> initializes the logger.
All these steps are normally done internally by <a href="https://docs.rs/env_logger/*/env_logger/fn.init.html"><code>env_logger::init</code></a>.</p>
<pre><pre class="playground"><code class="language-rust edition2018">
use std::env;
use env_logger::Builder;
fn main() {
Builder::new()
.parse(&amp;env::var(&quot;MY_APP_LOG&quot;).unwrap_or_default())
.init();
log::info!(&quot;informational message&quot;);
log::warn!(&quot;warning message&quot;);
log::error!(&quot;this is an error {}&quot;, &quot;message&quot;);
}
</code></pre></pre>
<h2><a class="header" href="#include-timestamp-in-log-messages" id="include-timestamp-in-log-messages">Include timestamp in log messages</a></h2>
<p><a href="https://docs.rs/log/"><img src="https://badge-cache.kominick.com/crates/v/log.svg?label=log" alt="log-badge" /></a> <a href="https://docs.rs/env_logger/"><img src="https://badge-cache.kominick.com/crates/v/env_logger.svg?label=env_logger" alt="env_logger-badge" /></a> <a href="https://docs.rs/chrono/"><img src="https://badge-cache.kominick.com/crates/v/chrono.svg?label=chrono" alt="chrono-badge" /></a> <a href="https://crates.io/categories/debugging"><img src="https://badge-cache.kominick.com/badge/debugging--x.svg?style=social" alt="cat-debugging-badge" /></a></p>
<p>Creates a custom logger configuration with <a href="https://docs.rs/env_logger/*/env_logger/struct.Builder.html"><code>Builder</code></a>.
Each log entry calls <a href="https://docs.rs/chrono/*/chrono/offset/struct.Local.html#method.now"><code>Local::now</code></a> to get the current <a href="https://docs.rs/chrono/*/chrono/datetime/struct.DateTime.html"><code>DateTime</code></a> in local
timezone and uses <a href="https://docs.rs/chrono/*/chrono/struct.DateTime.html#method.format"><code>DateTime::format</code></a> with <a href="https://docs.rs/chrono/*/chrono/format/strftime/index.html#specifiers"><code>strftime::specifiers</code></a> to format
a timestamp used in the final log.</p>
<p>The example calls <a href="https://docs.rs/env_logger/*/env_logger/struct.Builder.html#method.format"><code>Builder::format</code></a> to set a closure which formats each
message text with timestamp, <a href="https://docs.rs/log/*/log/struct.Record.html#method.level"><code>Record::level</code></a> and body (<a href="https://docs.rs/log/*/log/struct.Record.html#method.args"><code>Record::args</code></a>).</p>
<pre><pre class="playground"><code class="language-rust edition2018">use std::io::Write;
use chrono::Local;
use env_logger::Builder;
use log::LevelFilter;
fn main() {
Builder::new()
.format(|buf, record| {
writeln!(buf,
&quot;{} [{}] - {}&quot;,
Local::now().format(&quot;%Y-%m-%dT%H:%M:%S&quot;),
record.level(),
record.args()
)
})
.filter(None, LevelFilter::Info)
.init();
log::warn!(&quot;warn&quot;);
log::info!(&quot;info&quot;);
log::debug!(&quot;debug&quot;);
}
</code></pre></pre>
<p>stderr output will contain</p>
<pre><code>2017-05-22T21:57:06 [WARN] - warn
2017-05-22T21:57:06 [INFO] - info
</code></pre>
<h2><a class="header" href="#log-messages-to-a-custom-location" id="log-messages-to-a-custom-location">Log messages to a custom location</a></h2>
<p><a href="https://docs.rs/log/"><img src="https://badge-cache.kominick.com/crates/v/log.svg?label=log" alt="log-badge" /></a> <a href="https://docs.rs/log4rs/"><img src="https://badge-cache.kominick.com/crates/v/log4rs.svg?label=log4rs" alt="log4rs-badge" /></a> <a href="https://crates.io/categories/debugging"><img src="https://badge-cache.kominick.com/badge/debugging--x.svg?style=social" alt="cat-debugging-badge" /></a></p>
<p><a href="https://docs.rs/log4rs/">log4rs</a> configures log output to a custom location. <a href="https://docs.rs/log4rs/">log4rs</a> can use either an
external YAML file or a builder configuration.</p>
<p>Create the log configuration with <a href="https://docs.rs/log4rs/*/log4rs/append/file/struct.FileAppender.html"><code>log4rs::append::file::FileAppender</code></a>. An
appender defines the logging destination. The configuration continues with
encoding using a custom pattern from <a href="https://docs.rs/log4rs/*/log4rs/encode/pattern/index.html"><code>log4rs::encode::pattern</code></a>.
Assigns the configuration to <a href="https://docs.rs/log4rs/*/log4rs/config/struct.Config.html"><code>log4rs::config::Config</code></a> and sets the default
<a href="https://docs.rs/log/*/log/enum.LevelFilter.html"><code>log::LevelFilter</code></a>.</p>
<pre><pre class="playground"><code class="language-rust edition2018 no_run"><span class="boring">use error_chain::error_chain;
</span>
use log::LevelFilter;
use log4rs::append::file::FileAppender;
use log4rs::encode::pattern::PatternEncoder;
use log4rs::config::{Appender, Config, Root};
<span class="boring">
</span><span class="boring">error_chain! {
</span><span class="boring"> foreign_links {
</span><span class="boring"> Io(std::io::Error);
</span><span class="boring"> LogConfig(log4rs::config::Errors);
</span><span class="boring"> SetLogger(log::SetLoggerError);
</span><span class="boring"> }
</span><span class="boring">}
</span>
fn main() -&gt; Result&lt;()&gt; {
let logfile = FileAppender::builder()
.encoder(Box::new(PatternEncoder::new(&quot;{l} - {m}\n&quot;)))
.build(&quot;log/output.log&quot;)?;
let config = Config::builder()
.appender(Appender::builder().build(&quot;logfile&quot;, Box::new(logfile)))
.build(Root::builder()
.appender(&quot;logfile&quot;)
.build(LevelFilter::Info))?;
log4rs::init_config(config)?;
log::info!(&quot;Hello, world!&quot;);
Ok(())
}
</code></pre></pre>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#versioning-2" id="versioning-2">Versioning</a></h1>
<h2><a class="header" href="#parse-and-increment-a-version-string" id="parse-and-increment-a-version-string">Parse and increment a version string.</a></h2>
<p><a href="https://docs.rs/semver/"><img src="https://badge-cache.kominick.com/crates/v/semver.svg?label=semver" alt="semver-badge" /></a> <a href="https://crates.io/categories/config"><img src="https://badge-cache.kominick.com/badge/config--x.svg?style=social" alt="cat-config-badge" /></a></p>
<p>Constructs a <a href="https://docs.rs/semver/*/semver/struct.Version.html"><code>semver::Version</code></a> from a string literal using <a href="https://docs.rs/semver/*/semver/struct.Version.html#method.parse"><code>Version::parse</code></a>,
then increments it by patch, minor, and major version number one by one.</p>
<p>Note that in accordance with the <a href="http://semver.org/">Semantic Versioning Specification</a>,
incrementing the minor version number resets the patch version number to 0 and
incrementing the major version number resets both the minor and patch version
numbers to 0.</p>
<pre><pre class="playground"><code class="language-rust edition2018">use semver::{Version, SemVerError};
fn main() -&gt; Result&lt;(), SemVerError&gt; {
let mut parsed_version = Version::parse(&quot;0.2.6&quot;)?;
assert_eq!(
parsed_version,
Version {
major: 0,
minor: 2,
patch: 6,
pre: vec![],
build: vec![],
}
);
parsed_version.increment_patch();
assert_eq!(parsed_version.to_string(), &quot;0.2.7&quot;);
println!(&quot;New patch release: v{}&quot;, parsed_version);
parsed_version.increment_minor();
assert_eq!(parsed_version.to_string(), &quot;0.3.0&quot;);
println!(&quot;New minor release: v{}&quot;, parsed_version);
parsed_version.increment_major();
assert_eq!(parsed_version.to_string(), &quot;1.0.0&quot;);
println!(&quot;New major release: v{}&quot;, parsed_version);
Ok(())
}
</code></pre></pre>
<h2><a class="header" href="#parse-a-complex-version-string" id="parse-a-complex-version-string">Parse a complex version string.</a></h2>
<p><a href="https://docs.rs/semver/"><img src="https://badge-cache.kominick.com/crates/v/semver.svg?label=semver" alt="semver-badge" /></a> <a href="https://crates.io/categories/config"><img src="https://badge-cache.kominick.com/badge/config--x.svg?style=social" alt="cat-config-badge" /></a></p>
<p>Constructs a <a href="https://docs.rs/semver/*/semver/struct.Version.html"><code>semver::Version</code></a> from a complex version string using <a href="https://docs.rs/semver/*/semver/struct.Version.html#method.parse"><code>Version::parse</code></a>. The string
contains pre-release and build metadata as defined in the <a href="http://semver.org/">Semantic Versioning Specification</a>.</p>
<p>Note that, in accordance with the Specification, build metadata is parsed but not considered when
comparing versions. In other words, two versions may be equal even if their build strings differ.</p>
<pre><pre class="playground"><code class="language-rust edition2018">use semver::{Identifier, Version, SemVerError};
fn main() -&gt; Result&lt;(), SemVerError&gt; {
let version_str = &quot;1.0.49-125+g72ee7853&quot;;
let parsed_version = Version::parse(version_str)?;
assert_eq!(
parsed_version,
Version {
major: 1,
minor: 0,
patch: 49,
pre: vec![Identifier::Numeric(125)],
build: vec![],
}
);
assert_eq!(
parsed_version.build,
vec![Identifier::AlphaNumeric(String::from(&quot;g72ee7853&quot;))]
);
let serialized_version = parsed_version.to_string();
assert_eq!(&amp;serialized_version, version_str);
Ok(())
}
</code></pre></pre>
<h2><a class="header" href="#check-if-given-version-is-pre-release" id="check-if-given-version-is-pre-release">Check if given version is pre-release.</a></h2>
<p><a href="https://docs.rs/semver/"><img src="https://badge-cache.kominick.com/crates/v/semver.svg?label=semver" alt="semver-badge" /></a> <a href="https://crates.io/categories/config"><img src="https://badge-cache.kominick.com/badge/config--x.svg?style=social" alt="cat-config-badge" /></a></p>
<p>Given two versions, <a href="https://docs.rs/semver/*/semver/struct.Version.html#method.is_prerelease"><code>is_prerelease</code></a> asserts that one is pre-release and the other is not.</p>
<pre><pre class="playground"><code class="language-rust edition2018">use semver::{Version, SemVerError};
fn main() -&gt; Result&lt;(), SemVerError&gt; {
let version_1 = Version::parse(&quot;1.0.0-alpha&quot;)?;
let version_2 = Version::parse(&quot;1.0.0&quot;)?;
assert!(version_1.is_prerelease());
assert!(!version_2.is_prerelease());
Ok(())
}
</code></pre></pre>
<h2><a class="header" href="#find-the-latest-version-satisfying-given-range" id="find-the-latest-version-satisfying-given-range">Find the latest version satisfying given range</a></h2>
<p><a href="https://docs.rs/semver/"><img src="https://badge-cache.kominick.com/crates/v/semver.svg?label=semver" alt="semver-badge" /></a> <a href="https://crates.io/categories/config"><img src="https://badge-cache.kominick.com/badge/config--x.svg?style=social" alt="cat-config-badge" /></a></p>
<p>Given a list of version &amp;strs, finds the latest <a href="https://docs.rs/semver/*/semver/struct.Version.html"><code>semver::Version</code></a>.
<a href="https://docs.rs/semver/*/semver/struct.VersionReq.html"><code>semver::VersionReq</code></a> filters the list with <a href="https://docs.rs/semver/*/semver/struct.VersionReq.html#method.matches"><code>VersionReq::matches</code></a>.
Also demonstrates <code>semver</code> pre-release preferences.</p>
<pre><pre class="playground"><code class="language-rust edition2018"><span class="boring">use error_chain::error_chain;
</span>
use semver::{Version, VersionReq};
<span class="boring">
</span><span class="boring">error_chain! {
</span><span class="boring"> foreign_links {
</span><span class="boring"> SemVer(semver::SemVerError);
</span><span class="boring"> SemVerReq(semver::ReqParseError);
</span><span class="boring"> }
</span><span class="boring">}
</span>
fn find_max_matching_version&lt;'a, I&gt;(version_req_str: &amp;str, iterable: I) -&gt; Result&lt;Option&lt;Version&gt;&gt;
where
I: IntoIterator&lt;Item = &amp;'a str&gt;,
{
let vreq = VersionReq::parse(version_req_str)?;
Ok(
iterable
.into_iter()
.filter_map(|s| Version::parse(s).ok())
.filter(|s| vreq.matches(s))
.max(),
)
}
fn main() -&gt; Result&lt;()&gt; {
assert_eq!(
find_max_matching_version(&quot;&lt;= 1.0.0&quot;, vec![&quot;0.9.0&quot;, &quot;1.0.0&quot;, &quot;1.0.1&quot;])?,
Some(Version::parse(&quot;1.0.0&quot;)?)
);
assert_eq!(
find_max_matching_version(
&quot;&gt;1.2.3-alpha.3&quot;,
vec![
&quot;1.2.3-alpha.3&quot;,
&quot;1.2.3-alpha.4&quot;,
&quot;1.2.3-alpha.10&quot;,
&quot;1.2.3-beta.4&quot;,
&quot;3.4.5-alpha.9&quot;,
]
)?,
Some(Version::parse(&quot;1.2.3-beta.4&quot;)?)
);
Ok(())
}
</code></pre></pre>
<h2><a class="header" href="#check-external-command-version-for-compatibility" id="check-external-command-version-for-compatibility">Check external command version for compatibility</a></h2>
<p><a href="https://docs.rs/semver/"><img src="https://badge-cache.kominick.com/crates/v/semver.svg?label=semver" alt="semver-badge" /></a> <a href="https://crates.io/categories/text-processing"><img src="https://badge-cache.kominick.com/badge/text_processing--x.svg?style=social" alt="cat-text-processing-badge" /></a> <a href="https://crates.io/categories/os"><img src="https://badge-cache.kominick.com/badge/OS--x.svg?style=social" alt="cat-os-badge" /></a></p>
<p>Runs <code>git --version</code> using <a href="https://doc.rust-lang.org/std/process/struct.Command.html"><code>Command</code></a>, then parses the version number into a
<a href="https://docs.rs/semver/*/semver/struct.Version.html"><code>semver::Version</code></a> using <a href="https://docs.rs/semver/*/semver/struct.Version.html#method.parse"><code>Version::parse</code></a>. <a href="https://docs.rs/semver/*/semver/struct.VersionReq.html#method.matches"><code>VersionReq::matches</code></a> compares
<a href="https://docs.rs/semver/*/semver/struct.VersionReq.html"><code>semver::VersionReq</code></a> to the parsed version. The command output resembles
&quot;git version x.y.z&quot;.</p>
<pre><pre class="playground"><code class="language-rust edition2018 no_run"><span class="boring">use error_chain::error_chain;
</span>
use std::process::Command;
use semver::{Version, VersionReq};
<span class="boring">
</span><span class="boring">error_chain! {
</span><span class="boring"> foreign_links {
</span><span class="boring"> Io(std::io::Error);
</span><span class="boring"> Utf8(std::string::FromUtf8Error);
</span><span class="boring"> SemVer(semver::SemVerError);
</span><span class="boring"> SemVerReq(semver::ReqParseError);
</span><span class="boring"> }
</span><span class="boring">}
</span>
fn main() -&gt; Result&lt;()&gt; {
let version_constraint = &quot;&gt; 1.12.0&quot;;
let version_test = VersionReq::parse(version_constraint)?;
let output = Command::new(&quot;git&quot;).arg(&quot;--version&quot;).output()?;
if !output.status.success() {
error_chain::bail!(&quot;Command executed with failing error code&quot;);
}
let stdout = String::from_utf8(output.stdout)?;
let version = stdout.split(&quot; &quot;).last().ok_or_else(|| {
&quot;Invalid command output&quot;
})?;
let parsed_version = Version::parse(version)?;
if !version_test.matches(&amp;parsed_version) {
error_chain::bail!(&quot;Command version lower than minimum supported version (found {}, need {})&quot;,
parsed_version, version_constraint);
}
Ok(())
}
</code></pre></pre>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#build-time-tooling" id="build-time-tooling">Build Time Tooling</a></h1>
<p>This section covers &quot;build-time&quot; tooling, or code that is run prior to compiling a crate's source code.
Conventionally, build-time code lives in a <strong>build.rs</strong> file and is commonly referred to as a &quot;build script&quot;.
Common use cases include rust code generation and compilation of bundled C/C++/asm code.
See crates.io's <a href="http://doc.crates.io/build-script.html">documentation on the matter</a> for more information.</p>
<h2><a class="header" href="#compile-and-link-statically-to-a-bundled-c-library" id="compile-and-link-statically-to-a-bundled-c-library">Compile and link statically to a bundled C library</a></h2>
<p><a href="https://docs.rs/cc"><img src="https://badge-cache.kominick.com/crates/v/cc.svg?label=cc" alt="cc-badge" /></a> <a href="https://crates.io/categories/development-tools"><img src="https://badge-cache.kominick.com/badge/development_tools--x.svg?style=social" alt="cat-development-tools-badge" /></a></p>
<p>To accommodate scenarios where additional C, C++, or assembly is required in a project, the <a href="https://docs.rs/cc"><strong>cc</strong></a> crate
offers a simple api for compiling bundled C/C++/asm code into static libraries (<strong>.a</strong>) that can be statically linked to by <strong>rustc</strong>.</p>
<p>The following example has some bundled C code (<strong>src/hello.c</strong>) that will be used from rust.
Before compiling rust source code, the &quot;build&quot; file (<strong>build.rs</strong>) specified in <strong>Cargo.toml</strong> runs.
Using the <a href="https://docs.rs/cc"><strong>cc</strong></a> crate, a static library file will be produced (in this case, <strong>libhello.a</strong>, see
<a href="https://docs.rs/cc/*/cc/struct.Build.html#method.compile"><code>compile</code> docs</a>) which can then be used from rust by declaring the external function signatures in an <code>extern</code> block.</p>
<p>Since the bundled C is very simple, only a single source file needs to be passed to <a href="https://docs.rs/cc/*/cc/struct.Build.html"><code>cc::Build</code></a>.
For more complex build requirements, <a href="https://docs.rs/cc/*/cc/struct.Build.html"><code>cc::Build</code></a> offers a full suite of builder methods for specifying
<a href="https://docs.rs/cc/*/cc/struct.Build.html#method.include"><code>include</code></a> paths and extra compiler <a href="https://docs.rs/cc/*/cc/struct.Build.html#method.flag"><code>flag</code></a>s.</p>
<h3><a class="header" href="#cargotoml" id="cargotoml"><code>Cargo.toml</code></a></h3>
<pre><code class="language-toml">[package]
...
build = &quot;build.rs&quot;
[build-dependencies]
cc = &quot;1&quot;
[dependencies]
error-chain = &quot;0.11&quot;
</code></pre>
<h3><a class="header" href="#buildrs" id="buildrs"><code>build.rs</code></a></h3>
<pre><pre class="playground"><code class="language-rust edition2018 no_run">fn main() {
cc::Build::new()
.file(&quot;src/hello.c&quot;)
.compile(&quot;hello&quot;); // outputs `libhello.a`
}
</code></pre></pre>
<h3><a class="header" href="#srchelloc" id="srchelloc"><code>src/hello.c</code></a></h3>
<pre><code class="language-c">#include &lt;stdio.h&gt;
void hello() {
printf(&quot;Hello from C!\n&quot;);
}
void greet(const char* name) {
printf(&quot;Hello, %s!\n&quot;, name);
}
</code></pre>
<h3><a class="header" href="#srcmainrs" id="srcmainrs"><code>src/main.rs</code></a></h3>
<pre><code class="language-rust edition2018 ignore">use error_chain::error_chain;
use std::ffi::CString;
use std::os::raw::c_char;
error_chain! {
foreign_links {
NulError(::std::ffi::NulError);
Io(::std::io::Error);
}
}
fn prompt(s: &amp;str) -&gt; Result&lt;String&gt; {
use std::io::Write;
print!(&quot;{}&quot;, s);
std::io::stdout().flush()?;
let mut input = String::new();
std::io::stdin().read_line(&amp;mut input)?;
Ok(input.trim().to_string())
}
extern {
fn hello();
fn greet(name: *const c_char);
}
fn main() -&gt; Result&lt;()&gt; {
unsafe { hello() }
let name = prompt(&quot;What's your name? &quot;)?;
let c_name = CString::new(name)?;
unsafe { greet(c_name.as_ptr()) }
Ok(())
}
</code></pre>
<h2><a class="header" href="#compile-and-link-statically-to-a-bundled-c-library-1" id="compile-and-link-statically-to-a-bundled-c-library-1">Compile and link statically to a bundled C++ library</a></h2>
<p><a href="https://docs.rs/cc"><img src="https://badge-cache.kominick.com/crates/v/cc.svg?label=cc" alt="cc-badge" /></a> <a href="https://crates.io/categories/development-tools"><img src="https://badge-cache.kominick.com/badge/development_tools--x.svg?style=social" alt="cat-development-tools-badge" /></a></p>
<p>Linking a bundled C++ library is very similar to linking a bundled C library. The two core differences when compiling and statically linking a bundled C++ library are specifying a C++ compiler via the builder method <a href="https://docs.rs/cc/*/cc/struct.Build.html#method.cpp"><code>cpp(true)</code></a> and preventing name mangling by the C++ compiler by adding the <code>extern &quot;C&quot;</code> section at the top of our C++ source file.</p>
<h3><a class="header" href="#cargotoml-1" id="cargotoml-1"><code>Cargo.toml</code></a></h3>
<pre><code class="language-toml">[package]
...
build = &quot;build.rs&quot;
[build-dependencies]
cc = &quot;1&quot;
</code></pre>
<h3><a class="header" href="#buildrs-1" id="buildrs-1"><code>build.rs</code></a></h3>
<pre><pre class="playground"><code class="language-rust edition2018 no_run">fn main() {
cc::Build::new()
.cpp(true)
.file(&quot;src/foo.cpp&quot;)
.compile(&quot;foo&quot;);
}
</code></pre></pre>
<h3><a class="header" href="#srcfoocpp" id="srcfoocpp"><code>src/foo.cpp</code></a></h3>
<pre><code class="language-cpp">extern &quot;C&quot; {
int multiply(int x, int y);
}
int multiply(int x, int y) {
return x*y;
}
</code></pre>
<h3><a class="header" href="#srcmainrs-1" id="srcmainrs-1"><code>src/main.rs</code></a></h3>
<pre><code class="language-rust edition2018 ignore">extern {
fn multiply(x : i32, y : i32) -&gt; i32;
}
fn main(){
unsafe {
println!(&quot;{}&quot;, multiply(5,7));
}
}
</code></pre>
<h2><a class="header" href="#compile-a-c-library-while-setting-custom-defines" id="compile-a-c-library-while-setting-custom-defines">Compile a C library while setting custom defines</a></h2>
<p><a href="https://docs.rs/cc"><img src="https://badge-cache.kominick.com/crates/v/cc.svg?label=cc" alt="cc-badge" /></a> <a href="https://crates.io/categories/development-tools"><img src="https://badge-cache.kominick.com/badge/development_tools--x.svg?style=social" alt="cat-development-tools-badge" /></a></p>
<p>It is simple to build bundled C code with custom defines using <a href="https://docs.rs/cc/*/cc/struct.Build.html#method.define"><code>cc::Build::define</code></a>.
The method takes an <a href="https://doc.rust-lang.org/std/option/enum.Option.html"><code>Option</code></a> value, so it is possible to create defines such as <code>#define APP_NAME &quot;foo&quot;</code>
as well as <code>#define WELCOME</code> (pass <code>None</code> as the value for a value-less define). This example builds
a bundled C file with dynamic defines set in <code>build.rs</code> and prints &quot;<strong>Welcome to foo - version 1.0.2</strong>&quot;
when run. Cargo sets some <a href="https://doc.rust-lang.org/cargo/reference/environment-variables.html">environment variables</a> which may be useful for some custom defines.</p>
<h3><a class="header" href="#cargotoml-2" id="cargotoml-2"><code>Cargo.toml</code></a></h3>
<pre><code class="language-toml">[package]
...
version = &quot;1.0.2&quot;
build = &quot;build.rs&quot;
[build-dependencies]
cc = &quot;1&quot;
</code></pre>
<h3><a class="header" href="#buildrs-2" id="buildrs-2"><code>build.rs</code></a></h3>
<pre><pre class="playground"><code class="language-rust edition2018 no_run">fn main() {
cc::Build::new()
.define(&quot;APP_NAME&quot;, &quot;\&quot;foo\&quot;&quot;)
.define(&quot;VERSION&quot;, format!(&quot;\&quot;{}\&quot;&quot;, env!(&quot;CARGO_PKG_VERSION&quot;)).as_str())
.define(&quot;WELCOME&quot;, None)
.file(&quot;src/foo.c&quot;)
.compile(&quot;foo&quot;);
}
</code></pre></pre>
<h3><a class="header" href="#srcfooc" id="srcfooc"><code>src/foo.c</code></a></h3>
<pre><code class="language-c">#include &lt;stdio.h&gt;
void print_app_info() {
#ifdef WELCOME
printf(&quot;Welcome to &quot;);
#endif
printf(&quot;%s - version %s\n&quot;, APP_NAME, VERSION);
}
</code></pre>
<h3><a class="header" href="#srcmainrs-2" id="srcmainrs-2"><code>src/main.rs</code></a></h3>
<pre><code class="language-rust edition2018 ignore">extern {
fn print_app_info();
}
fn main(){
unsafe {
print_app_info();
}
}
</code></pre>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#encoding-1" id="encoding-1">Encoding</a></h1>
<table><thead><tr><th>Recipe</th><th>Crates</th><th>Categories</th></tr></thead><tbody>
<tr><td><a href="encoding/strings.html#percent-encode-a-string">Percent-encode a string</a></td><td><a href="https://docs.rs/url/"><img src="https://badge-cache.kominick.com/crates/v/percent-encoding.svg?label=percent-encoding" alt="percent-encoding-badge" /></a></td><td><a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></td></tr>
<tr><td><a href="encoding/strings.html#encode-a-string-as-applicationx-www-form-urlencoded">Encode a string as application/x-www-form-urlencoded</a></td><td><a href="https://docs.rs/url/"><img src="https://badge-cache.kominick.com/crates/v/url.svg?label=url" alt="url-badge" /></a></td><td><a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></td></tr>
<tr><td><a href="encoding/strings.html#encode-and-decode-hex">Encode and decode hex</a></td><td><a href="https://docs.rs/data-encoding/"><img src="https://badge-cache.kominick.com/crates/v/data-encoding.svg?label=data-encoding" alt="data-encoding-badge" /></a></td><td><a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></td></tr>
<tr><td><a href="encoding/strings.html#encode-and-decode-base64">Encode and decode base64</a></td><td><a href="https://docs.rs/base64/"><img src="https://badge-cache.kominick.com/crates/v/base64.svg?label=base64" alt="base64-badge" /></a></td><td><a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></td></tr>
<tr><td><a href="encoding/csv.html#read-csv-records">Read CSV records</a></td><td><a href="https://docs.rs/csv/"><img src="https://badge-cache.kominick.com/crates/v/csv.svg?label=csv" alt="csv-badge" /></a></td><td><a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></td></tr>
<tr><td><a href="encoding/csv.html#read-csv-records-with-different-delimiter">Read CSV records with different delimiter</a></td><td><a href="https://docs.rs/csv/"><img src="https://badge-cache.kominick.com/crates/v/csv.svg?label=csv" alt="csv-badge" /></a></td><td><a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></td></tr>
<tr><td><a href="encoding/csv.html#filter-csv-records-matching-a-predicate">Filter CSV records matching a predicate</a></td><td><a href="https://docs.rs/csv/"><img src="https://badge-cache.kominick.com/crates/v/csv.svg?label=csv" alt="csv-badge" /></a></td><td><a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></td></tr>
<tr><td><a href="encoding/csv.html#handle-invalid-csv-data-with-serde">Handle invalid CSV data with Serde</a></td><td><a href="https://docs.rs/csv/"><img src="https://badge-cache.kominick.com/crates/v/csv.svg?label=csv" alt="csv-badge" /></a> <a href="https://docs.rs/serde/"><img src="https://badge-cache.kominick.com/crates/v/serde.svg?label=serde" alt="serde-badge" /></a></td><td><a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></td></tr>
<tr><td><a href="encoding/csv.html#serialize-records-to-csv">Serialize records to CSV</a></td><td><a href="https://docs.rs/csv/"><img src="https://badge-cache.kominick.com/crates/v/csv.svg?label=csv" alt="csv-badge" /></a></td><td><a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></td></tr>
<tr><td><a href="encoding/csv.html#serialize-records-to-csv-using-serde">Serialize records to CSV using Serde</a></td><td><a href="https://docs.rs/csv/"><img src="https://badge-cache.kominick.com/crates/v/csv.svg?label=csv" alt="csv-badge" /></a> <a href="https://docs.rs/serde/"><img src="https://badge-cache.kominick.com/crates/v/serde.svg?label=serde" alt="serde-badge" /></a></td><td><a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></td></tr>
<tr><td><a href="encoding/csv.html#transform-csv-column">Transform one column of a CSV file</a></td><td><a href="https://docs.rs/csv/"><img src="https://badge-cache.kominick.com/crates/v/csv.svg?label=csv" alt="csv-badge" /></a> <a href="https://docs.rs/serde/"><img src="https://badge-cache.kominick.com/crates/v/serde.svg?label=serde" alt="serde-badge" /></a></td><td><a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></td></tr>
<tr><td><a href="encoding/complex.html#serialize-and-deserialize-unstructured-json">Serialize and deserialize unstructured JSON</a></td><td><a href="https://docs.rs/serde_json/*/serde_json/"><img src="https://badge-cache.kominick.com/crates/v/serde_json.svg?label=serde_json" alt="serde-json-badge" /></a></td><td><a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></td></tr>
<tr><td><a href="encoding/complex.html#deserialize-a-toml-configuration-file">Deserialize a TOML configuration file</a></td><td><a href="https://docs.rs/toml/"><img src="https://badge-cache.kominick.com/crates/v/toml.svg?label=toml" alt="toml-badge" /></a></td><td><a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></td></tr>
<tr><td><a href="encoding/complex.html#read-and-write-integers-in-little-endian-byte-order">Read and write integers in little-endian byte order</a></td><td><a href="https://docs.rs/byteorder/"><img src="https://badge-cache.kominick.com/crates/v/byteorder.svg?label=byteorder" alt="byteorder-badge" /></a></td><td><a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></td></tr>
</tbody></table>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#character-sets" id="character-sets">Character Sets</a></h1>
<h2><a class="header" href="#percent-encode-a-string" id="percent-encode-a-string">Percent-encode a string</a></h2>
<p><a href="https://en.wikipedia.org/wiki/Percent-encoding"><img src="https://badge-cache.kominick.com/crates/v/percent-encoding.svg?label=percent-encoding" alt="percent-encoding-badge" /></a> <a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></p>
<p>Encode an input string with <a href="https://en.wikipedia.org/wiki/Percent-encoding">percent-encoding</a> using the <a href="https://docs.rs/percent-encoding/*/percent_encoding/fn.utf8_percent_encode.html"><code>utf8_percent_encode</code></a>
function from the <code>percent-encoding</code> crate. Then decode using the <a href="https://docs.rs/percent-encoding/*/percent_encoding/fn.percent_decode.html"><code>percent_decode</code></a>
function.</p>
<pre><pre class="playground"><code class="language-rust edition2018">use percent_encoding::{utf8_percent_encode, percent_decode, AsciiSet, CONTROLS};
use std::str::Utf8Error;
/// https://url.spec.whatwg.org/#fragment-percent-encode-set
const FRAGMENT: &amp;AsciiSet = &amp;CONTROLS.add(b' ').add(b'&quot;').add(b'&lt;').add(b'&gt;').add(b'`');
fn main() -&gt; Result&lt;(), Utf8Error&gt; {
let input = &quot;confident, productive systems programming&quot;;
let iter = utf8_percent_encode(input, FRAGMENT);
let encoded: String = iter.collect();
assert_eq!(encoded, &quot;confident,%20productive%20systems%20programming&quot;);
let iter = percent_decode(encoded.as_bytes());
let decoded = iter.decode_utf8()?;
assert_eq!(decoded, &quot;confident, productive systems programming&quot;);
Ok(())
}
</code></pre></pre>
<p>The encode set defines which bytes (in addition to non-ASCII and controls) need
to be percent-encoded. The choice of this set depends on context. For example,
<code>url</code> encodes <code>?</code> in a URL path but not in a query string.</p>
<p>The return value of encoding is an iterator of <code>&amp;str</code> slices which collect into
a <code>String</code>.</p>
<h2><a class="header" href="#encode-a-string-as-applicationx-www-form-urlencoded" id="encode-a-string-as-applicationx-www-form-urlencoded">Encode a string as application/x-www-form-urlencoded</a></h2>
<p><a href="https://docs.rs/url/"><img src="https://badge-cache.kominick.com/crates/v/url.svg?label=url" alt="url-badge" /></a> <a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></p>
<p>Encodes a string into <a href="https://url.spec.whatwg.org/#application/x-www-form-urlencoded">application/x-www-form-urlencoded</a> syntax
using the <a href="https://docs.rs/url/*/url/form_urlencoded/fn.byte_serialize.html"><code>form_urlencoded::byte_serialize</code></a> and subsequently
decodes it with <a href="https://docs.rs/url/*/url/form_urlencoded/fn.parse.html"><code>form_urlencoded::parse</code></a>. Both functions return iterators
that collect into a <code>String</code>.</p>
<pre><pre class="playground"><code class="language-rust edition2018">use url::form_urlencoded::{byte_serialize, parse};
fn main() {
let urlencoded: String = byte_serialize(&quot;What is ❤?&quot;.as_bytes()).collect();
assert_eq!(urlencoded, &quot;What+is+%E2%9D%A4%3F&quot;);
println!(&quot;urlencoded:'{}'&quot;, urlencoded);
let decoded: String = parse(urlencoded.as_bytes())
.map(|(key, val)| [key, val].concat())
.collect();
assert_eq!(decoded, &quot;What is ❤?&quot;);
println!(&quot;decoded:'{}'&quot;, decoded);
}
</code></pre></pre>
<h2><a class="header" href="#encode-and-decode-hex" id="encode-and-decode-hex">Encode and decode hex</a></h2>
<p><a href="https://docs.rs/data-encoding/"><img src="https://badge-cache.kominick.com/crates/v/data-encoding.svg?label=data-encoding" alt="data-encoding-badge" /></a> <a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></p>
<p>The <a href="https://docs.rs/data-encoding/*/data_encoding/"><code>data_encoding</code></a> crate provides a <code>HEXUPPER::encode</code> method which
takes a <code>&amp;[u8]</code> and returns a <code>String</code> containing the hexadecimal
representation of the data.</p>
<p>Similarly, a <code>HEXUPPER::decode</code> method is provided which takes a <code>&amp;[u8]</code> and
returns a <code>Vec&lt;u8&gt;</code> if the input data is successfully decoded.</p>
<p>The example below coverts <code>&amp;[u8]</code> data to hexadecimal equivalent. Compares this
value to the expected value.</p>
<pre><pre class="playground"><code class="language-rust edition2018">use data_encoding::{HEXUPPER, DecodeError};
fn main() -&gt; Result&lt;(), DecodeError&gt; {
let original = b&quot;The quick brown fox jumps over the lazy dog.&quot;;
let expected = &quot;54686520717569636B2062726F776E20666F78206A756D7073206F76\
657220746865206C617A7920646F672E&quot;;
let encoded = HEXUPPER.encode(original);
assert_eq!(encoded, expected);
let decoded = HEXUPPER.decode(&amp;encoded.into_bytes())?;
assert_eq!(&amp;decoded[..], &amp;original[..]);
Ok(())
}
</code></pre></pre>
<h2><a class="header" href="#encode-and-decode-base64" id="encode-and-decode-base64">Encode and decode base64</a></h2>
<p><a href="https://docs.rs/base64/"><img src="https://badge-cache.kominick.com/crates/v/base64.svg?label=base64" alt="base64-badge" /></a> <a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></p>
<p>Encodes byte slice into <code>base64</code> String using <a href="https://docs.rs/base64/*/base64/fn.encode.html"><code>encode</code></a>
and decodes it with <a href="https://docs.rs/base64/*/base64/fn.decode.html"><code>decode</code></a>.</p>
<pre><pre class="playground"><code class="language-rust edition2018"><span class="boring">use error_chain::error_chain;
</span>
use std::str;
use base64::{encode, decode};
<span class="boring">
</span><span class="boring">error_chain! {
</span><span class="boring"> foreign_links {
</span><span class="boring"> Base64(base64::DecodeError);
</span><span class="boring"> Utf8Error(str::Utf8Error);
</span><span class="boring"> }
</span><span class="boring">}
</span>
fn main() -&gt; Result&lt;()&gt; {
let hello = b&quot;hello rustaceans&quot;;
let encoded = encode(hello);
let decoded = decode(&amp;encoded)?;
println!(&quot;origin: {}&quot;, str::from_utf8(hello)?);
println!(&quot;base64 encoded: {}&quot;, encoded);
println!(&quot;back to origin: {}&quot;, str::from_utf8(&amp;decoded)?);
Ok(())
}
</code></pre></pre>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#csv-processing" id="csv-processing">CSV processing</a></h1>
<h2><a class="header" href="#read-csv-records" id="read-csv-records">Read CSV records</a></h2>
<p><a href="https://docs.rs/csv/"><img src="https://badge-cache.kominick.com/crates/v/csv.svg?label=csv" alt="csv-badge" /></a> <a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></p>
<p>Reads standard CSV records into <a href="https://docs.rs/csv/*/csv/struct.StringRecord.html"><code>csv::StringRecord</code></a> — a weakly typed
data representation which expects valid UTF-8 rows. Alternatively,
<a href="https://docs.rs/csv/*/csv/struct.ByteRecord.html"><code>csv::ByteRecord</code></a> makes no assumptions about UTF-8.</p>
<pre><pre class="playground"><code class="language-rust edition2018">use csv::Error;
fn main() -&gt; Result&lt;(), Error&gt; {
let csv = &quot;year,make,model,description
1948,Porsche,356,Luxury sports car
1967,Ford,Mustang fastback 1967,American car&quot;;
let mut reader = csv::Reader::from_reader(csv.as_bytes());
for record in reader.records() {
let record = record?;
println!(
&quot;In {}, {} built the {} model. It is a {}.&quot;,
&amp;record[0],
&amp;record[1],
&amp;record[2],
&amp;record[3]
);
}
Ok(())
}
</code></pre></pre>
<p>Serde deserializes data into strongly type structures. See the
<a href="https://docs.rs/csv/*/csv/struct.Reader.html#method.deserialize"><code>csv::Reader::deserialize</code></a> method.</p>
<pre><pre class="playground"><code class="language-rust edition2018">use serde::Deserialize;
#[derive(Deserialize)]
struct Record {
year: u16,
make: String,
model: String,
description: String,
}
fn main() -&gt; Result&lt;(), csv::Error&gt; {
let csv = &quot;year,make,model,description
1948,Porsche,356,Luxury sports car
1967,Ford,Mustang fastback 1967,American car&quot;;
let mut reader = csv::Reader::from_reader(csv.as_bytes());
for record in reader.deserialize() {
let record: Record = record?;
println!(
&quot;In {}, {} built the {} model. It is a {}.&quot;,
record.year,
record.make,
record.model,
record.description
);
}
Ok(())
}
</code></pre></pre>
<h2><a class="header" href="#read-csv-records-with-different-delimiter" id="read-csv-records-with-different-delimiter">Read CSV records with different delimiter</a></h2>
<p><a href="https://docs.rs/csv/"><img src="https://badge-cache.kominick.com/crates/v/csv.svg?label=csv" alt="csv-badge" /></a> <a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></p>
<p>Reads CSV records with a tab <a href="https://docs.rs/csv/1.0.0-beta.3/csv/struct.ReaderBuilder.html#method.delimiter"><code>delimiter</code></a>.</p>
<pre><pre class="playground"><code class="language-rust edition2018">use csv::Error;
use serde::Deserialize;
#[derive(Debug, Deserialize)]
struct Record {
name: String,
place: String,
#[serde(deserialize_with = &quot;csv::invalid_option&quot;)]
id: Option&lt;u64&gt;,
}
use csv::ReaderBuilder;
fn main() -&gt; Result&lt;(), Error&gt; {
let data = &quot;name\tplace\tid
Mark\tMelbourne\t46
Ashley\tZurich\t92&quot;;
let mut reader = ReaderBuilder::new().delimiter(b'\t').from_reader(data.as_bytes());
for result in reader.deserialize::&lt;Record&gt;() {
println!(&quot;{:?}&quot;, result?);
}
Ok(())
}
</code></pre></pre>
<h2><a class="header" href="#filter-csv-records-matching-a-predicate" id="filter-csv-records-matching-a-predicate">Filter CSV records matching a predicate</a></h2>
<p><a href="https://docs.rs/csv/"><img src="https://badge-cache.kominick.com/crates/v/csv.svg?label=csv" alt="csv-badge" /></a> <a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></p>
<p>Returns <em>only</em> the rows from <code>data</code> with a field that matches <code>query</code>.</p>
<pre><pre class="playground"><code class="language-rust edition2018"><span class="boring">use error_chain::error_chain;
</span>
use std::io;
<span class="boring">
</span><span class="boring">error_chain!{
</span><span class="boring"> foreign_links {
</span><span class="boring"> Io(std::io::Error);
</span><span class="boring"> CsvError(csv::Error);
</span><span class="boring"> }
</span><span class="boring">}
</span>
fn main() -&gt; Result&lt;()&gt; {
let query = &quot;CA&quot;;
let data = &quot;\
City,State,Population,Latitude,Longitude
Kenai,AK,7610,60.5544444,-151.2583333
Oakman,AL,,33.7133333,-87.3886111
Sandfort,AL,,32.3380556,-85.2233333
West Hollywood,CA,37031,34.0900000,-118.3608333&quot;;
let mut rdr = csv::ReaderBuilder::new().from_reader(data.as_bytes());
let mut wtr = csv::Writer::from_writer(io::stdout());
wtr.write_record(rdr.headers()?)?;
for result in rdr.records() {
let record = result?;
if record.iter().any(|field| field == query) {
wtr.write_record(&amp;record)?;
}
}
wtr.flush()?;
Ok(())
}
</code></pre></pre>
<p><em>Disclaimer: this example has been adapted from <a href="https://docs.rs/csv/*/csv/tutorial/index.html#filter-by-search">the csv crate tutorial</a></em>.</p>
<h2><a class="header" href="#handle-invalid-csv-data-with-serde" id="handle-invalid-csv-data-with-serde">Handle invalid CSV data with Serde</a></h2>
<p><a href="https://docs.rs/csv/"><img src="https://badge-cache.kominick.com/crates/v/csv.svg?label=csv" alt="csv-badge" /></a> <a href="https://docs.rs/serde/"><img src="https://badge-cache.kominick.com/crates/v/serde.svg?label=serde" alt="serde-badge" /></a> <a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></p>
<p>CSV files often contain invalid data. For these cases, the <code>csv</code> crate
provides a custom deserializer, <a href="https://docs.rs/csv/*/csv/fn.invalid_option.html"><code>csv::invalid_option</code></a>, which automatically
converts invalid data to None values.</p>
<pre><pre class="playground"><code class="language-rust edition2018">use csv::Error;
use serde::Deserialize;
#[derive(Debug, Deserialize)]
struct Record {
name: String,
place: String,
#[serde(deserialize_with = &quot;csv::invalid_option&quot;)]
id: Option&lt;u64&gt;,
}
fn main() -&gt; Result&lt;(), Error&gt; {
let data = &quot;name,place,id
mark,sydney,46.5
ashley,zurich,92
akshat,delhi,37
alisha,colombo,xyz&quot;;
let mut rdr = csv::Reader::from_reader(data.as_bytes());
for result in rdr.deserialize() {
let record: Record = result?;
println!(&quot;{:?}&quot;, record);
}
Ok(())
}
</code></pre></pre>
<h2><a class="header" href="#serialize-records-to-csv" id="serialize-records-to-csv">Serialize records to CSV</a></h2>
<p><a href="https://docs.rs/csv/"><img src="https://badge-cache.kominick.com/crates/v/csv.svg?label=csv" alt="csv-badge" /></a> <a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></p>
<p>This example shows how to serialize a Rust tuple. <a href="https://docs.rs/csv/*/csv/struct.Writer.html"><code>csv::writer</code></a> supports automatic
serialization from Rust types into CSV records. <a href="https://docs.rs/csv/*/csv/struct.Writer.html#method.write_record"><code>write_record</code></a> writes
a simple record containing string data only. Data with more complex values
such as numbers, floats, and options use <a href="https://docs.rs/csv/*/csv/struct.Writer.html#method.serialize"><code>serialize</code></a>. Since CSV
writer uses internal buffer, always explicitly <a href="https://docs.rs/csv/*/csv/struct.Writer.html#method.flush"><code>flush</code></a> when done.</p>
<pre><pre class="playground"><code class="language-rust edition2018"><span class="boring">use error_chain::error_chain;
</span>
use std::io;
<span class="boring">
</span><span class="boring">error_chain! {
</span><span class="boring"> foreign_links {
</span><span class="boring"> CSVError(csv::Error);
</span><span class="boring"> IOError(std::io::Error);
</span><span class="boring"> }
</span><span class="boring">}
</span>
fn main() -&gt; Result&lt;()&gt; {
let mut wtr = csv::Writer::from_writer(io::stdout());
wtr.write_record(&amp;[&quot;Name&quot;, &quot;Place&quot;, &quot;ID&quot;])?;
wtr.serialize((&quot;Mark&quot;, &quot;Sydney&quot;, 87))?;
wtr.serialize((&quot;Ashley&quot;, &quot;Dublin&quot;, 32))?;
wtr.serialize((&quot;Akshat&quot;, &quot;Delhi&quot;, 11))?;
wtr.flush()?;
Ok(())
}
</code></pre></pre>
<h2><a class="header" href="#serialize-records-to-csv-using-serde" id="serialize-records-to-csv-using-serde">Serialize records to CSV using Serde</a></h2>
<p><a href="https://docs.rs/csv/"><img src="https://badge-cache.kominick.com/crates/v/csv.svg?label=csv" alt="csv-badge" /></a> <a href="https://docs.rs/serde/"><img src="https://badge-cache.kominick.com/crates/v/serde.svg?label=serde" alt="serde-badge" /></a> <a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></p>
<p>The following example shows how to serialize custom structs as CSV records using
the <a href="https://docs.rs/serde/">serde</a> crate.</p>
<pre><pre class="playground"><code class="language-rust edition2018"><span class="boring">use error_chain::error_chain;
</span>use serde::Serialize;
use std::io;
<span class="boring">
</span><span class="boring">error_chain! {
</span><span class="boring"> foreign_links {
</span><span class="boring"> IOError(std::io::Error);
</span><span class="boring"> CSVError(csv::Error);
</span><span class="boring"> }
</span><span class="boring">}
</span>
#[derive(Serialize)]
struct Record&lt;'a&gt; {
name: &amp;'a str,
place: &amp;'a str,
id: u64,
}
fn main() -&gt; Result&lt;()&gt; {
let mut wtr = csv::Writer::from_writer(io::stdout());
let rec1 = Record { name: &quot;Mark&quot;, place: &quot;Melbourne&quot;, id: 56};
let rec2 = Record { name: &quot;Ashley&quot;, place: &quot;Sydney&quot;, id: 64};
let rec3 = Record { name: &quot;Akshat&quot;, place: &quot;Delhi&quot;, id: 98};
wtr.serialize(rec1)?;
wtr.serialize(rec2)?;
wtr.serialize(rec3)?;
wtr.flush()?;
Ok(())
}
</code></pre></pre>
<h2><a class="header" href="#transform-csv-column" id="transform-csv-column">Transform CSV column</a></h2>
<p><a href="https://docs.rs/csv/"><img src="https://badge-cache.kominick.com/crates/v/csv.svg?label=csv" alt="csv-badge" /></a> <a href="https://docs.rs/serde/"><img src="https://badge-cache.kominick.com/crates/v/serde.svg?label=serde" alt="serde-badge" /></a> <a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></p>
<p>Transform a CSV file containing a color name and a hex color into one with a
color name and an rgb color. Utilizes the <a href="https://docs.rs/csv/">csv</a> crate to read and write the
csv file, and <a href="https://docs.rs/serde/">serde</a> to deserialize and serialize the rows to and from bytes.</p>
<p>See <a href="https://docs.rs/csv/*/csv/struct.Reader.html#method.deserialize"><code>csv::Reader::deserialize</code></a>, <a href="https://docs.rs/serde/*/serde/trait.Deserialize.html"><code>serde::Deserialize</code></a>, and <a href="https://doc.rust-lang.org/std/str/trait.FromStr.html"><code>std::str::FromStr</code></a></p>
<pre><pre class="playground"><code class="language-rust edition2018"><span class="boring">use error_chain::error_chain;
</span>use csv::{Reader, Writer};
use serde::{de, Deserialize, Deserializer};
use std::str::FromStr;
<span class="boring">
</span><span class="boring">error_chain! {
</span><span class="boring"> foreign_links {
</span><span class="boring"> CsvError(csv::Error);
</span><span class="boring"> ParseInt(std::num::ParseIntError);
</span><span class="boring"> CsvInnerError(csv::IntoInnerError&lt;Writer&lt;Vec&lt;u8&gt;&gt;&gt;);
</span><span class="boring"> IO(std::fmt::Error);
</span><span class="boring"> UTF8(std::string::FromUtf8Error);
</span><span class="boring"> }
</span><span class="boring">}
</span>
#[derive(Debug)]
struct HexColor {
red: u8,
green: u8,
blue: u8,
}
#[derive(Debug, Deserialize)]
struct Row {
color_name: String,
color: HexColor,
}
impl FromStr for HexColor {
type Err = Error;
fn from_str(hex_color: &amp;str) -&gt; std::result::Result&lt;Self, Self::Err&gt; {
let trimmed = hex_color.trim_matches('#');
if trimmed.len() != 6 {
Err(&quot;Invalid length of hex string&quot;.into())
} else {
Ok(HexColor {
red: u8::from_str_radix(&amp;trimmed[..2], 16)?,
green: u8::from_str_radix(&amp;trimmed[2..4], 16)?,
blue: u8::from_str_radix(&amp;trimmed[4..6], 16)?,
})
}
}
}
impl&lt;'de&gt; Deserialize&lt;'de&gt; for HexColor {
fn deserialize&lt;D&gt;(deserializer: D) -&gt; std::result::Result&lt;Self, D::Error&gt;
where
D: Deserializer&lt;'de&gt;,
{
let s = String::deserialize(deserializer)?;
FromStr::from_str(&amp;s).map_err(de::Error::custom)
}
}
fn main() -&gt; Result&lt;()&gt; {
let data = &quot;color_name,color
red,#ff0000
green,#00ff00
blue,#0000FF
periwinkle,#ccccff
magenta,#ff00ff&quot;
.to_owned();
let mut out = Writer::from_writer(vec![]);
let mut reader = Reader::from_reader(data.as_bytes());
for result in reader.deserialize::&lt;Row&gt;() {
let res = result?;
out.serialize((
res.color_name,
res.color.red,
res.color.green,
res.color.blue,
))?;
}
let written = String::from_utf8(out.into_inner()?)?;
assert_eq!(Some(&quot;magenta,255,0,255&quot;), written.lines().last());
println!(&quot;{}&quot;, written);
Ok(())
}
</code></pre></pre>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#structured-data" id="structured-data">Structured Data</a></h1>
<h2><a class="header" href="#serialize-and-deserialize-unstructured-json" id="serialize-and-deserialize-unstructured-json">Serialize and deserialize unstructured JSON</a></h2>
<p><a href="https://docs.rs/serde_json/*/serde_json/"><img src="https://badge-cache.kominick.com/crates/v/serde_json.svg?label=serde_json" alt="serde-json-badge" /></a> <a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></p>
<p>The <a href="https://docs.serde.rs/serde_json/"><code>serde_json</code></a> crate provides a <a href="https://docs.serde.rs/serde_json/fn.from_str.html"><code>from_str</code></a> function to parse a <code>&amp;str</code> of
JSON.</p>
<p>Unstructured JSON can be parsed into a universal <a href="https://docs.serde.rs/serde_json/enum.Value.html"><code>serde_json::Value</code></a> type that
is able to represent any valid JSON data.</p>
<p>The example below shows a <code>&amp;str</code> of JSON being parsed. The expected value is declared using the <a href="https://docs.serde.rs/serde_json/macro.json.html"><code>json!</code></a> macro.</p>
<pre><pre class="playground"><code class="language-rust edition2018"> use serde_json::json;
use serde_json::{Value, Error};
fn main() -&gt; Result&lt;(), Error&gt; {
let j = r#&quot;{
&quot;userid&quot;: 103609,
&quot;verified&quot;: true,
&quot;access_privileges&quot;: [
&quot;user&quot;,
&quot;admin&quot;
]
}&quot;#;
let parsed: Value = serde_json::from_str(j)?;
let expected = json!({
&quot;userid&quot;: 103609,
&quot;verified&quot;: true,
&quot;access_privileges&quot;: [
&quot;user&quot;,
&quot;admin&quot;
]
});
assert_eq!(parsed, expected);
Ok(())
}
</code></pre></pre>
<h2><a class="header" href="#deserialize-a-toml-configuration-file" id="deserialize-a-toml-configuration-file">Deserialize a TOML configuration file</a></h2>
<p><a href="https://docs.rs/toml/"><img src="https://badge-cache.kominick.com/crates/v/toml.svg?label=toml" alt="toml-badge" /></a> <a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></p>
<p>Parse some TOML into a universal <code>toml::Value</code> that is able to represent any
valid TOML data.</p>
<pre><pre class="playground"><code class="language-rust edition2018">use toml::{Value, de::Error};
fn main() -&gt; Result&lt;(), Error&gt; {
let toml_content = r#&quot;
[package]
name = &quot;your_package&quot;
version = &quot;0.1.0&quot;
authors = [&quot;You! &lt;you@example.org&gt;&quot;]
[dependencies]
serde = &quot;1.0&quot;
&quot;#;
let package_info: Value = toml::from_str(toml_content)?;
assert_eq!(package_info[&quot;dependencies&quot;][&quot;serde&quot;].as_str(), Some(&quot;1.0&quot;));
assert_eq!(package_info[&quot;package&quot;][&quot;name&quot;].as_str(),
Some(&quot;your_package&quot;));
Ok(())
}
</code></pre></pre>
<p>Parse TOML into your own structs using <a href="https://docs.rs/serde/">Serde</a>.</p>
<pre><pre class="playground"><code class="language-rust edition2018">use serde::Deserialize;
use toml::de::Error;
use std::collections::HashMap;
#[derive(Deserialize)]
struct Config {
package: Package,
dependencies: HashMap&lt;String, String&gt;,
}
#[derive(Deserialize)]
struct Package {
name: String,
version: String,
authors: Vec&lt;String&gt;,
}
fn main() -&gt; Result&lt;(), Error&gt; {
let toml_content = r#&quot;
[package]
name = &quot;your_package&quot;
version = &quot;0.1.0&quot;
authors = [&quot;You! &lt;you@example.org&gt;&quot;]
[dependencies]
serde = &quot;1.0&quot;
&quot;#;
let package_info: Config = toml::from_str(toml_content)?;
assert_eq!(package_info.package.name, &quot;your_package&quot;);
assert_eq!(package_info.package.version, &quot;0.1.0&quot;);
assert_eq!(package_info.package.authors, vec![&quot;You! &lt;you@example.org&gt;&quot;]);
assert_eq!(package_info.dependencies[&quot;serde&quot;], &quot;1.0&quot;);
Ok(())
}
</code></pre></pre>
<h2><a class="header" href="#read-and-write-integers-in-little-endian-byte-order" id="read-and-write-integers-in-little-endian-byte-order">Read and write integers in little-endian byte order</a></h2>
<p><a href="https://docs.rs/byteorder/"><img src="https://badge-cache.kominick.com/crates/v/byteorder.svg?label=byteorder" alt="byteorder-badge" /></a> <a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></p>
<p><code>byteorder</code> can reverse the significant bytes of structured data. This may
be necessary when receiving information over the network, such that bytes
received are from another system.</p>
<pre><pre class="playground"><code class="language-rust edition2018">
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use std::io::Error;
#[derive(Default, PartialEq, Debug)]
struct Payload {
kind: u8,
value: u16,
}
fn main() -&gt; Result&lt;(), Error&gt; {
let original_payload = Payload::default();
let encoded_bytes = encode(&amp;original_payload)?;
let decoded_payload = decode(&amp;encoded_bytes)?;
assert_eq!(original_payload, decoded_payload);
Ok(())
}
fn encode(payload: &amp;Payload) -&gt; Result&lt;Vec&lt;u8&gt;, Error&gt; {
let mut bytes = vec![];
bytes.write_u8(payload.kind)?;
bytes.write_u16::&lt;LittleEndian&gt;(payload.value)?;
Ok(bytes)
}
fn decode(mut bytes: &amp;[u8]) -&gt; Result&lt;Payload, Error&gt; {
let payload = Payload {
kind: bytes.read_u8()?,
value: bytes.read_u16::&lt;LittleEndian&gt;()?,
};
Ok(payload)
}
</code></pre></pre>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#error-handling" id="error-handling">Error Handling</a></h1>
<table><thead><tr><th>Recipe</th><th>Crates</th><th>Categories</th></tr></thead><tbody>
<tr><td><a href="errors/handle.html#handle-errors-correctly-in-main">Handle errors correctly in main</a></td><td><a href="https://docs.rs/error-chain/"><img src="https://badge-cache.kominick.com/crates/v/error-chain.svg?label=error-chain" alt="error-chain-badge" /></a></td><td><a href="https://crates.io/categories/rust-patterns"><img src="https://badge-cache.kominick.com/badge/rust_patterns--x.svg?style=social" alt="cat-rust-patterns-badge" /></a></td></tr>
<tr><td><a href="errors/handle.html#avoid-discarding-errors-during-error-conversions">Avoid discarding errors during error conversions</a></td><td><a href="https://docs.rs/error-chain/"><img src="https://badge-cache.kominick.com/crates/v/error-chain.svg?label=error-chain" alt="error-chain-badge" /></a></td><td><a href="https://crates.io/categories/rust-patterns"><img src="https://badge-cache.kominick.com/badge/rust_patterns--x.svg?style=social" alt="cat-rust-patterns-badge" /></a></td></tr>
<tr><td><a href="errors/handle.html#obtain-backtrace-of-complex-error-scenarios">Obtain backtrace of complex error scenarios</a></td><td><a href="https://docs.rs/error-chain/"><img src="https://badge-cache.kominick.com/crates/v/error-chain.svg?label=error-chain" alt="error-chain-badge" /></a></td><td><a href="https://crates.io/categories/rust-patterns"><img src="https://badge-cache.kominick.com/badge/rust_patterns--x.svg?style=social" alt="cat-rust-patterns-badge" /></a></td></tr>
</tbody></table>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#error-handling-1" id="error-handling-1">Error Handling</a></h1>
<h2><a class="header" href="#handle-errors-correctly-in-main" id="handle-errors-correctly-in-main">Handle errors correctly in main</a></h2>
<p><a href="https://docs.rs/error-chain/"><img src="https://badge-cache.kominick.com/crates/v/error-chain.svg?label=error-chain" alt="error-chain-badge" /></a> <a href="https://crates.io/categories/rust-patterns"><img src="https://badge-cache.kominick.com/badge/rust_patterns--x.svg?style=social" alt="cat-rust-patterns-badge" /></a></p>
<p>Handles error that occur when trying to open a file that does not
exist. It is achieved by using <a href="https://docs.rs/error-chain/">error-chain</a>, a library that takes
care of a lot of boilerplate code needed in order to <a href="https://doc.rust-lang.org/book/second-edition/ch09-00-error-handling.html">handle errors in Rust</a>.</p>
<p><code>Io(std::io::Error)</code> inside <a href="https://docs.rs/error-chain/*/error_chain/#foreign-links"><code>foreign_links</code></a> allows automatic
conversion from <a href="https://doc.rust-lang.org/std/io/struct.Error.html"><code>std::io::Error</code></a> into <a href="https://docs.rs/error-chain/*/error_chain/macro.error_chain.html"><code>error_chain!</code></a> defined type
implementing the <a href="https://doc.rust-lang.org/std/error/trait.Error.html"><code>Error</code></a> trait.</p>
<p>The below recipe will tell how long the system has been running by
opening the Unix file <code>/proc/uptime</code> and parse the content to get the
first number. Returns uptime unless there is an error.</p>
<p>Other recipes in this book will hide the <a href="https://docs.rs/error-chain/">error-chain</a> boilerplate, and can be
seen by expanding the code with the ⤢ button.</p>
<pre><pre class="playground"><code class="language-rust edition2018">use error_chain::error_chain;
use std::fs::File;
use std::io::Read;
error_chain!{
foreign_links {
Io(std::io::Error);
ParseInt(::std::num::ParseIntError);
}
}
fn read_uptime() -&gt; Result&lt;u64&gt; {
let mut uptime = String::new();
File::open(&quot;/proc/uptime&quot;)?.read_to_string(&amp;mut uptime)?;
Ok(uptime
.split('.')
.next()
.ok_or(&quot;Cannot parse uptime data&quot;)?
.parse()?)
}
fn main() {
match read_uptime() {
Ok(uptime) =&gt; println!(&quot;uptime: {} seconds&quot;, uptime),
Err(err) =&gt; eprintln!(&quot;error: {}&quot;, err),
};
}
</code></pre></pre>
<h2><a class="header" href="#avoid-discarding-errors-during-error-conversions" id="avoid-discarding-errors-during-error-conversions">Avoid discarding errors during error conversions</a></h2>
<p><a href="https://docs.rs/error-chain/"><img src="https://badge-cache.kominick.com/crates/v/error-chain.svg?label=error-chain" alt="error-chain-badge" /></a> <a href="https://crates.io/categories/rust-patterns"><img src="https://badge-cache.kominick.com/badge/rust_patterns--x.svg?style=social" alt="cat-rust-patterns-badge" /></a></p>
<p>The <a href="https://docs.rs/error-chain/">error-chain</a> crate makes <a href="https://docs.rs/error-chain/*/error_chain/#matching-errors">matching</a> on different error types returned by
a function possible and relatively compact. <a href="https://docs.rs/error-chain/*/error_chain/example_generated/enum.ErrorKind.html"><code>ErrorKind</code></a> determines the error
type.</p>
<p>Uses <a href="https://docs.rs/reqwest/">reqwest</a>::<a href="https://docs.rs/reqwest/*/reqwest/blocking/index.html">blocking</a> to query a random integer generator web service. Converts
the string response into an integer. The Rust standard library,
<a href="https://docs.rs/reqwest/">reqwest</a>, and the web service can all generate errors. Well defined Rust errors
use <a href="https://docs.rs/error-chain/*/error_chain/#foreign-links"><code>foreign_links</code></a>. An additional <a href="https://docs.rs/error-chain/*/error_chain/example_generated/enum.ErrorKind.html"><code>ErrorKind</code></a> variant for the web service
error uses <code>errors</code> block of the <code>error_chain!</code> macro.</p>
<pre><pre class="playground"><code class="language-rust edition2018">use error_chain::error_chain;
error_chain! {
foreign_links {
Io(std::io::Error);
Reqwest(reqwest::Error);
ParseIntError(std::num::ParseIntError);
}
errors { RandomResponseError(t: String) }
}
fn parse_response(response: reqwest::blocking::Response) -&gt; Result&lt;u32&gt; {
let mut body = response.text()?;
body.pop();
body
.parse::&lt;u32&gt;()
.chain_err(|| ErrorKind::RandomResponseError(body))
}
fn run() -&gt; Result&lt;()&gt; {
let url =
format!(&quot;https://www.random.org/integers/?num=1&amp;min=0&amp;max=10&amp;col=1&amp;base=10&amp;format=plain&quot;);
let response = reqwest::blocking::get(&amp;url)?;
let random_value: u32 = parse_response(response)?;
println!(&quot;a random number between 0 and 10: {}&quot;, random_value);
Ok(())
}
fn main() {
if let Err(error) = run() {
match *error.kind() {
ErrorKind::Io(_) =&gt; println!(&quot;Standard IO error: {:?}&quot;, error),
ErrorKind::Reqwest(_) =&gt; println!(&quot;Reqwest error: {:?}&quot;, error),
ErrorKind::ParseIntError(_) =&gt; println!(&quot;Standard parse int error: {:?}&quot;, error),
ErrorKind::RandomResponseError(_) =&gt; println!(&quot;User defined error: {:?}&quot;, error),
_ =&gt; println!(&quot;Other error: {:?}&quot;, error),
}
}
}
</code></pre></pre>
<h2><a class="header" href="#obtain-backtrace-of-complex-error-scenarios" id="obtain-backtrace-of-complex-error-scenarios">Obtain backtrace of complex error scenarios</a></h2>
<p><a href="https://docs.rs/error-chain/"><img src="https://badge-cache.kominick.com/crates/v/error-chain.svg?label=error-chain" alt="error-chain-badge" /></a> <a href="https://crates.io/categories/rust-patterns"><img src="https://badge-cache.kominick.com/badge/rust_patterns--x.svg?style=social" alt="cat-rust-patterns-badge" /></a></p>
<p>This recipe shows how to handle a complex error scenario and then
print a backtrace. It relies on <a href="https://docs.rs/error-chain/*/error_chain/index.html#chaining-errors"><code>chain_err</code></a> to extend errors by
appending new errors. The error stack can be unwound, thus providing
a better context to understand why an error was raised.</p>
<p>The below recipes attempts to deserialize the value <code>256</code> into a
<code>u8</code>. An error will bubble up from Serde then csv and finally up to the
user code.</p>
<pre><pre class="playground"><code class="language-rust edition2018">use error_chain::error_chain;
<span class="boring">use serde::Deserialize;
</span><span class="boring">
</span><span class="boring">use std::fmt;
</span><span class="boring">
</span><span class="boring">error_chain! {
</span><span class="boring"> foreign_links {
</span><span class="boring"> Reader(csv::Error);
</span><span class="boring"> }
</span><span class="boring">}
</span>
#[derive(Debug, Deserialize)]
struct Rgb {
red: u8,
blue: u8,
green: u8,
}
impl Rgb {
fn from_reader(csv_data: &amp;[u8]) -&gt; Result&lt;Rgb&gt; {
let color: Rgb = csv::Reader::from_reader(csv_data)
.deserialize()
.nth(0)
.ok_or(&quot;Cannot deserialize the first CSV record&quot;)?
.chain_err(|| &quot;Cannot deserialize RGB color&quot;)?;
Ok(color)
}
}
<span class="boring">impl fmt::UpperHex for Rgb {
</span><span class="boring"> fn fmt(&amp;self, f: &amp;mut fmt::Formatter) -&gt; fmt::Result {
</span><span class="boring"> let hexa = u32::from(self.red) &lt;&lt; 16 | u32::from(self.blue) &lt;&lt; 8 | u32::from(self.green);
</span><span class="boring"> write!(f, &quot;{:X}&quot;, hexa)
</span><span class="boring"> }
</span><span class="boring">}
</span><span class="boring">
</span>fn run() -&gt; Result&lt;()&gt; {
let csv = &quot;red,blue,green
102,256,204&quot;;
let rgb = Rgb::from_reader(csv.as_bytes()).chain_err(|| &quot;Cannot read CSV data&quot;)?;
println!(&quot;{:?} to hexadecimal #{:X}&quot;, rgb, rgb);
Ok(())
}
fn main() {
if let Err(ref errors) = run() {
eprintln!(&quot;Error level - description&quot;);
errors
.iter()
.enumerate()
.for_each(|(index, error)| eprintln!(&quot;&gt; {} - {}&quot;, index, error));
if let Some(backtrace) = errors.backtrace() {
eprintln!(&quot;{:?}&quot;, backtrace);
}
<span class="boring">
</span><span class="boring"> // In a real use case, errors should handled. For example:
</span><span class="boring"> // ::std::process::exit(1);
</span> }
}
</code></pre></pre>
<p>Backtrace error rendered:</p>
<pre><code class="language-text">Error level - description
&gt; 0 - Cannot read CSV data
&gt; 1 - Cannot deserialize RGB color
&gt; 2 - CSV deserialize error: record 1 (line: 2, byte: 15): field 1: number too large to fit in target type
&gt; 3 - field 1: number too large to fit in target type
</code></pre>
<p>Run the recipe with <code>RUST_BACKTRACE=1</code> to display a detailed <a href="https://docs.rs/error-chain/*/error_chain/trait.ChainedError.html#tymethod.backtrace"><code>backtrace</code></a> associated with this error.</p>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#file-system-1" id="file-system-1">File System</a></h1>
<table><thead><tr><th>Recipe</th><th>Crates</th><th>Categories</th></tr></thead><tbody>
<tr><td><a href="file/read-write.html#read-lines-of-strings-from-a-file">Read lines of strings from a file</a></td><td><a href="https://doc.rust-lang.org/std"><img src="https://badge-cache.kominick.com/badge/std-1.29.1-blue.svg" alt="std-badge" /></a></td><td><a href="https://crates.io/categories/filesystem"><img src="https://badge-cache.kominick.com/badge/filesystem--x.svg?style=social" alt="cat-filesystem-badge" /></a></td></tr>
<tr><td><a href="file/read-write.html#avoid-writing-and-reading-from-a-same-file">Avoid writing and reading from a same file</a></td><td><a href="https://docs.rs/same-file/"><img src="https://badge-cache.kominick.com/crates/v/same_file.svg?label=same_file" alt="same_file-badge" /></a></td><td><a href="https://crates.io/categories/filesystem"><img src="https://badge-cache.kominick.com/badge/filesystem--x.svg?style=social" alt="cat-filesystem-badge" /></a></td></tr>
<tr><td><a href="file/read-write.html#access-a-file-randomly-using-a-memory-map">Access a file randomly using a memory map</a></td><td><a href="https://docs.rs/memmap/"><img src="https://badge-cache.kominick.com/crates/v/memmap.svg?label=memmap" alt="memmap-badge" /></a></td><td><a href="https://crates.io/categories/filesystem"><img src="https://badge-cache.kominick.com/badge/filesystem--x.svg?style=social" alt="cat-filesystem-badge" /></a></td></tr>
<tr><td><a href="file/dir.html#file-names-that-have-been-modified-in-the-last-24-hours">File names that have been modified in the last 24 hours</a></td><td><a href="https://doc.rust-lang.org/std"><img src="https://badge-cache.kominick.com/badge/std-1.29.1-blue.svg" alt="std-badge" /></a></td><td><a href="https://crates.io/categories/filesystem"><img src="https://badge-cache.kominick.com/badge/filesystem--x.svg?style=social" alt="cat-filesystem-badge" /></a> <a href="https://crates.io/categories/os"><img src="https://badge-cache.kominick.com/badge/OS--x.svg?style=social" alt="cat-os-badge" /></a></td></tr>
<tr><td><a href="file/dir.html#find-loops-for-a-given-path">Find loops for a given path</a></td><td><a href="https://docs.rs/same-file/"><img src="https://badge-cache.kominick.com/crates/v/same_file.svg?label=same_file" alt="same_file-badge" /></a></td><td><a href="https://crates.io/categories/filesystem"><img src="https://badge-cache.kominick.com/badge/filesystem--x.svg?style=social" alt="cat-filesystem-badge" /></a></td></tr>
<tr><td><a href="file/dir.html#recursively-find-duplicate-file-names">Recursively find duplicate file names</a></td><td><a href="https://docs.rs/walkdir/"><img src="https://badge-cache.kominick.com/crates/v/walkdir.svg?label=walkdir" alt="walkdir-badge" /></a></td><td><a href="https://crates.io/categories/filesystem"><img src="https://badge-cache.kominick.com/badge/filesystem--x.svg?style=social" alt="cat-filesystem-badge" /></a></td></tr>
<tr><td><a href="file/dir.html#recursively-find-all-files-with-given-predicate">Recursively find all files with given predicate</a></td><td><a href="https://docs.rs/walkdir/"><img src="https://badge-cache.kominick.com/crates/v/walkdir.svg?label=walkdir" alt="walkdir-badge" /></a></td><td><a href="https://crates.io/categories/filesystem"><img src="https://badge-cache.kominick.com/badge/filesystem--x.svg?style=social" alt="cat-filesystem-badge" /></a></td></tr>
<tr><td><a href="file/dir.html#traverse-directories-while-skipping-dotfiles">Traverse directories while skipping dotfiles</a></td><td><a href="https://docs.rs/walkdir/"><img src="https://badge-cache.kominick.com/crates/v/walkdir.svg?label=walkdir" alt="walkdir-badge" /></a></td><td><a href="https://crates.io/categories/filesystem"><img src="https://badge-cache.kominick.com/badge/filesystem--x.svg?style=social" alt="cat-filesystem-badge" /></a></td></tr>
<tr><td><a href="file/dir.html#recursively-calculate-file-sizes-at-given-depth">Recursively calculate file sizes at given depth</a></td><td><a href="https://docs.rs/walkdir/"><img src="https://badge-cache.kominick.com/crates/v/walkdir.svg?label=walkdir" alt="walkdir-badge" /></a></td><td><a href="https://crates.io/categories/filesystem"><img src="https://badge-cache.kominick.com/badge/filesystem--x.svg?style=social" alt="cat-filesystem-badge" /></a></td></tr>
<tr><td><a href="file/dir.html#find-all-png-files-recursively">Find all png files recursively</a></td><td><a href="https://docs.rs/glob/"><img src="https://badge-cache.kominick.com/crates/v/glob.svg?label=glob" alt="glob-badge" /></a></td><td><a href="https://crates.io/categories/filesystem"><img src="https://badge-cache.kominick.com/badge/filesystem--x.svg?style=social" alt="cat-filesystem-badge" /></a></td></tr>
<tr><td><a href="file/dir.html#find-all-files-with-given-pattern-ignoring-filename-case">Find all files with given pattern ignoring filename case</a></td><td><a href="https://docs.rs/glob/"><img src="https://badge-cache.kominick.com/crates/v/glob.svg?label=glob" alt="glob-badge" /></a></td><td><a href="https://crates.io/categories/filesystem"><img src="https://badge-cache.kominick.com/badge/filesystem--x.svg?style=social" alt="cat-filesystem-badge" /></a></td></tr>
</tbody></table>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#read--write" id="read--write">Read &amp; Write</a></h1>
<h2><a class="header" href="#read-lines-of-strings-from-a-file" id="read-lines-of-strings-from-a-file">Read lines of strings from a file</a></h2>
<p><a href="https://doc.rust-lang.org/std"><img src="https://badge-cache.kominick.com/badge/std-1.29.1-blue.svg" alt="std-badge" /></a> <a href="https://crates.io/categories/filesystem"><img src="https://badge-cache.kominick.com/badge/filesystem--x.svg?style=social" alt="cat-filesystem-badge" /></a></p>
<p>Writes a three-line message to a file, then reads it back a line at a
time with the <a href="https://doc.rust-lang.org/std/io/struct.Lines.html"><code>Lines</code></a> iterator created by
<a href="https://doc.rust-lang.org/std/io/trait.BufRead.html#method.lines"><code>BufRead::lines</code></a>. <a href="https://doc.rust-lang.org/std/fs/struct.File.html"><code>File</code></a> implements <a href="https://doc.rust-lang.org/std/io/trait.Read.html"><code>Read</code></a> which provides <a href="https://doc.rust-lang.org/std/io/struct.BufReader.html"><code>BufReader</code></a>
trait. <a href="https://doc.rust-lang.org/std/fs/struct.File.html#method.create"><code>File::create</code></a> opens a <a href="https://doc.rust-lang.org/std/fs/struct.File.html"><code>File</code></a> for writing, <a href="https://doc.rust-lang.org/std/fs/struct.File.html#method.open"><code>File::open</code></a> for
reading.</p>
<pre><pre class="playground"><code class="language-rust edition2018">use std::fs::File;
use std::io::{Write, BufReader, BufRead, Error};
fn main() -&gt; Result&lt;(), Error&gt; {
let path = &quot;lines.txt&quot;;
let mut output = File::create(path)?;
write!(output, &quot;Rust\n💖\nFun&quot;)?;
let input = File::open(path)?;
let buffered = BufReader::new(input);
for line in buffered.lines() {
println!(&quot;{}&quot;, line?);
}
Ok(())
}
</code></pre></pre>
<h2><a class="header" href="#avoid-writing-and-reading-from-a-same-file" id="avoid-writing-and-reading-from-a-same-file">Avoid writing and reading from a same file</a></h2>
<p><a href="https://docs.rs/same-file/"><img src="https://badge-cache.kominick.com/crates/v/same_file.svg?label=same_file" alt="same_file-badge" /></a> <a href="https://crates.io/categories/filesystem"><img src="https://badge-cache.kominick.com/badge/filesystem--x.svg?style=social" alt="cat-filesystem-badge" /></a></p>
<p>Use <a href="https://docs.rs/same-file/*/same_file/struct.Handle.html"><code>same_file::Handle</code></a> to a file that can be tested for equality with
other handles. In this example, the handles of file to be read from and
to be written to are tested for equality.</p>
<pre><pre class="playground"><code class="language-rust edition2018 no_run">use same_file::Handle;
use std::fs::File;
use std::io::{BufRead, BufReader, Error, ErrorKind};
use std::path::Path;
fn main() -&gt; Result&lt;(), Error&gt; {
let path_to_read = Path::new(&quot;new.txt&quot;);
let stdout_handle = Handle::stdout()?;
let handle = Handle::from_path(path_to_read)?;
if stdout_handle == handle {
return Err(Error::new(
ErrorKind::Other,
&quot;You are reading and writing to the same file&quot;,
));
} else {
let file = File::open(&amp;path_to_read)?;
let file = BufReader::new(file);
for (num, line) in file.lines().enumerate() {
println!(&quot;{} : {}&quot;, num, line?.to_uppercase());
}
}
Ok(())
}
</code></pre></pre>
<pre><code class="language-bash">cargo run
</code></pre>
<p>displays the contents of the file new.txt.</p>
<pre><code class="language-bash">cargo run &gt;&gt; ./new.txt
</code></pre>
<p>errors because the two files are same.</p>
<h2><a class="header" href="#access-a-file-randomly-using-a-memory-map" id="access-a-file-randomly-using-a-memory-map">Access a file randomly using a memory map</a></h2>
<p><a href="https://docs.rs/memmap/"><img src="https://badge-cache.kominick.com/crates/v/memmap.svg?label=memmap" alt="memmap-badge" /></a> <a href="https://crates.io/categories/filesystem"><img src="https://badge-cache.kominick.com/badge/filesystem--x.svg?style=social" alt="cat-filesystem-badge" /></a></p>
<p>Creates a memory map of a file using <a href="https://docs.rs/memmap/">memmap</a> and simulates some non-sequential
reads from the file. Using a memory map means you just index into a slice rather
than dealing with <a href="https://doc.rust-lang.org/std/fs/struct.File.html#method.seek"><code>seek</code></a> to navigate a File.</p>
<p>The <a href="https://docs.rs/memmap/*/memmap/struct.Mmap.html#method.map"><code>Mmap::map</code></a> function assumes the file
behind the memory map is not being modified at the same time by another process
or else a <a href="https://en.wikipedia.org/wiki/Race_condition#File_systems">race condition</a> occurs.</p>
<pre><pre class="playground"><code class="language-rust edition2018">use memmap::Mmap;
use std::fs::File;
use std::io::{Write, Error};
fn main() -&gt; Result&lt;(), Error&gt; {
<span class="boring"> write!(File::create(&quot;content.txt&quot;)?, &quot;My hovercraft is full of eels!&quot;)?;
</span><span class="boring">
</span> let file = File::open(&quot;content.txt&quot;)?;
let map = unsafe { Mmap::map(&amp;file)? };
let random_indexes = [0, 1, 2, 19, 22, 10, 11, 29];
assert_eq!(&amp;map[3..13], b&quot;hovercraft&quot;);
let random_bytes: Vec&lt;u8&gt; = random_indexes.iter()
.map(|&amp;idx| map[idx])
.collect();
assert_eq!(&amp;random_bytes[..], b&quot;My loaf!&quot;);
Ok(())
}
</code></pre></pre>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#directory-traversal" id="directory-traversal">Directory Traversal</a></h1>
<h2><a class="header" href="#file-names-that-have-been-modified-in-the-last-24-hours" id="file-names-that-have-been-modified-in-the-last-24-hours">File names that have been modified in the last 24 hours</a></h2>
<p><a href="https://doc.rust-lang.org/std"><img src="https://badge-cache.kominick.com/badge/std-1.29.1-blue.svg" alt="std-badge" /></a> <a href="https://crates.io/categories/filesystem"><img src="https://badge-cache.kominick.com/badge/filesystem--x.svg?style=social" alt="cat-filesystem-badge" /></a></p>
<p>Gets the current working directory by calling <a href="https://doc.rust-lang.org/std/env/fn.current_dir.html"><code>env::current_dir</code></a>,
then for each entries in <a href="https://doc.rust-lang.org/std/fs/fn.read_dir.html"><code>fs::read_dir</code></a>, extracts the
<a href="https://doc.rust-lang.org/std/fs/struct.DirEntry.html#method.path"><code>DirEntry::path</code></a> and gets the metadata via <a href="https://doc.rust-lang.org/std/fs/struct.Metadata.html"><code>fs::Metadata</code></a>. The
<a href="https://doc.rust-lang.org/std/fs/struct.Metadata.html#method.modified"><code>Metadata::modified</code></a> returns the <a href="https://doc.rust-lang.org/std/time/struct.SystemTime.html#method.elapsed"><code>SystemTime::elapsed</code></a> time since
last modification. <a href="https://doc.rust-lang.org/std/time/struct.Duration.html#method.as_secs"><code>Duration::as_secs</code></a> converts the time to seconds and
compared with 24 hours (24 * 60 * 60 seconds). <a href="https://doc.rust-lang.org/std/fs/struct.Metadata.html#method.is_file"><code>Metadata::is_file</code></a> filters
out directories.</p>
<pre><pre class="playground"><code class="language-rust edition2018"><span class="boring">use error_chain::error_chain;
</span><span class="boring">
</span>use std::{env, fs};
<span class="boring">error_chain! {
</span><span class="boring"> foreign_links {
</span><span class="boring"> Io(std::io::Error);
</span><span class="boring"> SystemTimeError(std::time::SystemTimeError);
</span><span class="boring"> }
</span><span class="boring">}
</span><span class="boring">
</span>fn main() -&gt; Result&lt;()&gt; {
let current_dir = env::current_dir()?;
println!(
&quot;Entries modified in the last 24 hours in {:?}:&quot;,
current_dir
);
for entry in fs::read_dir(current_dir)? {
let entry = entry?;
let path = entry.path();
let metadata = fs::metadata(&amp;path)?;
let last_modified = metadata.modified()?.elapsed()?.as_secs();
if last_modified &lt; 24 * 3600 &amp;&amp; metadata.is_file() {
println!(
&quot;Last modified: {:?} seconds, is read only: {:?}, size: {:?} bytes, filename: {:?}&quot;,
last_modified,
metadata.permissions().readonly(),
metadata.len(),
path.file_name().ok_or(&quot;No filename&quot;)?
);
}
}
Ok(())
}
</code></pre></pre>
<h2><a class="header" href="#find-loops-for-a-given-path" id="find-loops-for-a-given-path">Find loops for a given path</a></h2>
<p><a href="https://docs.rs/same-file/"><img src="https://badge-cache.kominick.com/crates/v/same_file.svg?label=same_file" alt="same_file-badge" /></a> <a href="https://crates.io/categories/filesystem"><img src="https://badge-cache.kominick.com/badge/filesystem--x.svg?style=social" alt="cat-filesystem-badge" /></a></p>
<p>Use <a href="https://docs.rs/same-file/*/same_file/fn.is_same_file.html"><code>same_file::is_same_file</code></a> to detect loops for a given path.
For example, a loop could be created on a Unix system via symlinks:</p>
<pre><code class="language-bash">mkdir -p /tmp/foo/bar/baz
ln -s /tmp/foo/ /tmp/foo/bar/baz/qux
</code></pre>
<p>The following would assert that a loop exists.</p>
<pre><pre class="playground"><code class="language-rust edition2018 no_run">use std::io;
use std::path::{Path, PathBuf};
use same_file::is_same_file;
fn contains_loop&lt;P: AsRef&lt;Path&gt;&gt;(path: P) -&gt; io::Result&lt;Option&lt;(PathBuf, PathBuf)&gt;&gt; {
let path = path.as_ref();
let mut path_buf = path.to_path_buf();
while path_buf.pop() {
if is_same_file(&amp;path_buf, path)? {
return Ok(Some((path_buf, path.to_path_buf())));
} else if let Some(looped_paths) = contains_loop(&amp;path_buf)? {
return Ok(Some(looped_paths));
}
}
return Ok(None);
}
fn main() {
assert_eq!(
contains_loop(&quot;/tmp/foo/bar/baz/qux/bar/baz&quot;).unwrap(),
Some((
PathBuf::from(&quot;/tmp/foo&quot;),
PathBuf::from(&quot;/tmp/foo/bar/baz/qux&quot;)
))
);
}
</code></pre></pre>
<h2><a class="header" href="#recursively-find-duplicate-file-names" id="recursively-find-duplicate-file-names">Recursively find duplicate file names</a></h2>
<p><a href="https://docs.rs/walkdir/"><img src="https://badge-cache.kominick.com/crates/v/walkdir.svg?label=walkdir" alt="walkdir-badge" /></a> <a href="https://crates.io/categories/filesystem"><img src="https://badge-cache.kominick.com/badge/filesystem--x.svg?style=social" alt="cat-filesystem-badge" /></a></p>
<p>Find recursively in the current directory duplicate filenames,
printing them only once.</p>
<pre><pre class="playground"><code class="language-rust edition2018 no_run">use std::collections::HashMap;
use walkdir::WalkDir;
fn main() {
let mut filenames = HashMap::new();
for entry in WalkDir::new(&quot;.&quot;)
.into_iter()
.filter_map(Result::ok)
.filter(|e| !e.file_type().is_dir()) {
let f_name = String::from(entry.file_name().to_string_lossy());
let counter = filenames.entry(f_name.clone()).or_insert(0);
*counter += 1;
if *counter == 2 {
println!(&quot;{}&quot;, f_name);
}
}
}
</code></pre></pre>
<h2><a class="header" href="#recursively-find-all-files-with-given-predicate" id="recursively-find-all-files-with-given-predicate">Recursively find all files with given predicate</a></h2>
<p><a href="https://docs.rs/walkdir/"><img src="https://badge-cache.kominick.com/crates/v/walkdir.svg?label=walkdir" alt="walkdir-badge" /></a> <a href="https://crates.io/categories/filesystem"><img src="https://badge-cache.kominick.com/badge/filesystem--x.svg?style=social" alt="cat-filesystem-badge" /></a></p>
<p>Find JSON files modified within the last day in the current directory.
Using <a href="https://docs.rs/walkdir/*/walkdir/struct.WalkDir.html#method.follow_links"><code>follow_links</code></a> ensures symbolic links are followed like they were
normal directories and files.</p>
<pre><pre class="playground"><code class="language-rust edition2018 no_run"><span class="boring">use error_chain::error_chain;
</span>
use walkdir::WalkDir;
<span class="boring">
</span><span class="boring">error_chain! {
</span><span class="boring"> foreign_links {
</span><span class="boring"> WalkDir(walkdir::Error);
</span><span class="boring"> Io(std::io::Error);
</span><span class="boring"> SystemTime(std::time::SystemTimeError);
</span><span class="boring"> }
</span><span class="boring">}
</span>
fn main() -&gt; Result&lt;()&gt; {
for entry in WalkDir::new(&quot;.&quot;)
.follow_links(true)
.into_iter()
.filter_map(|e| e.ok()) {
let f_name = entry.file_name().to_string_lossy();
let sec = entry.metadata()?.modified()?;
if f_name.ends_with(&quot;.json&quot;) &amp;&amp; sec.elapsed()?.as_secs() &lt; 86400 {
println!(&quot;{}&quot;, f_name);
}
}
Ok(())
}
</code></pre></pre>
<h2><a class="header" href="#traverse-directories-while-skipping-dotfiles" id="traverse-directories-while-skipping-dotfiles">Traverse directories while skipping dotfiles</a></h2>
<p><a href="https://docs.rs/walkdir/"><img src="https://badge-cache.kominick.com/crates/v/walkdir.svg?label=walkdir" alt="walkdir-badge" /></a> <a href="https://crates.io/categories/filesystem"><img src="https://badge-cache.kominick.com/badge/filesystem--x.svg?style=social" alt="cat-filesystem-badge" /></a></p>
<p>Uses <a href="https://docs.rs/walkdir/*/walkdir/struct.IntoIter.html#method.filter_entry"><code>filter_entry</code></a> to descend recursively into entries passing the
<code>is_not_hidden</code> predicate thus skipping hidden files and directories.
<a href="https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.filter"><code>Iterator::filter</code></a> applies to each <a href="https://docs.rs/walkdir/*/walkdir/struct.DirEntry.html"><code>WalkDir::DirEntry</code></a> even if the parent
is a hidden directory.</p>
<p>Root dir <code>&quot;.&quot;</code> yields through <a href="https://docs.rs/walkdir/*/walkdir/struct.DirEntry.html#method.depth"><code>WalkDir::depth</code></a> usage in <code>is_not_hidden</code>
predicate.</p>
<pre><pre class="playground"><code class="language-rust edition2018 no_run">use walkdir::{DirEntry, WalkDir};
fn is_not_hidden(entry: &amp;DirEntry) -&gt; bool {
entry
.file_name()
.to_str()
.map(|s| entry.depth() == 0 || !s.starts_with(&quot;.&quot;))
.unwrap_or(false)
}
fn main() {
WalkDir::new(&quot;.&quot;)
.into_iter()
.filter_entry(|e| is_not_hidden(e))
.filter_map(|v| v.ok())
.for_each(|x| println!(&quot;{}&quot;, x.path().display()));
}
</code></pre></pre>
<h2><a class="header" href="#recursively-calculate-file-sizes-at-given-depth" id="recursively-calculate-file-sizes-at-given-depth">Recursively calculate file sizes at given depth</a></h2>
<p><a href="https://docs.rs/walkdir/"><img src="https://badge-cache.kominick.com/crates/v/walkdir.svg?label=walkdir" alt="walkdir-badge" /></a> <a href="https://crates.io/categories/filesystem"><img src="https://badge-cache.kominick.com/badge/filesystem--x.svg?style=social" alt="cat-filesystem-badge" /></a></p>
<p>Recursion depth can be flexibly set by <a href="https://docs.rs/walkdir/*/walkdir/struct.WalkDir.html#method.min_depth"><code>WalkDir::min_depth</code></a> &amp; <a href="https://docs.rs/walkdir/*/walkdir/struct.WalkDir.html#method.max_depth"><code>WalkDir::max_depth</code></a> methods.
Calculates sum of all file sizes to 3 subfolders depth, ignoring files in the root folder.</p>
<pre><pre class="playground"><code class="language-rust edition2018">use walkdir::WalkDir;
fn main() {
let total_size = WalkDir::new(&quot;.&quot;)
.min_depth(1)
.max_depth(3)
.into_iter()
.filter_map(|entry| entry.ok())
.filter_map(|entry| entry.metadata().ok())
.filter(|metadata| metadata.is_file())
.fold(0, |acc, m| acc + m.len());
println!(&quot;Total size: {} bytes.&quot;, total_size);
}
</code></pre></pre>
<h2><a class="header" href="#find-all-png-files-recursively" id="find-all-png-files-recursively">Find all png files recursively</a></h2>
<p><a href="https://docs.rs/glob/"><img src="https://badge-cache.kominick.com/crates/v/glob.svg?label=glob" alt="glob-badge" /></a> <a href="https://crates.io/categories/filesystem"><img src="https://badge-cache.kominick.com/badge/filesystem--x.svg?style=social" alt="cat-filesystem-badge" /></a></p>
<p>Recursively find all PNG files in the current directory.
In this case, the <code>**</code> pattern matches the current directory and all subdirectories.</p>
<p>Use the <code>**</code> pattern in any path portion. For example, <code>/media/**/*.png</code>
matches all PNGs in <code>media</code> and it's subdirectories.</p>
<pre><pre class="playground"><code class="language-rust edition2018 no_run"><span class="boring">use error_chain::error_chain;
</span>
use glob::glob;
<span class="boring">
</span><span class="boring">error_chain! {
</span><span class="boring"> foreign_links {
</span><span class="boring"> Glob(glob::GlobError);
</span><span class="boring"> Pattern(glob::PatternError);
</span><span class="boring"> }
</span><span class="boring">}
</span>
fn main() -&gt; Result&lt;()&gt; {
for entry in glob(&quot;**/*.png&quot;)? {
println!(&quot;{}&quot;, entry?.display());
}
Ok(())
}
</code></pre></pre>
<h2><a class="header" href="#find-all-files-with-given-pattern-ignoring-filename-case" id="find-all-files-with-given-pattern-ignoring-filename-case">Find all files with given pattern ignoring filename case.</a></h2>
<p><a href="https://docs.rs/glob/"><img src="https://badge-cache.kominick.com/crates/v/glob.svg?label=glob" alt="glob-badge" /></a> <a href="https://crates.io/categories/filesystem"><img src="https://badge-cache.kominick.com/badge/filesystem--x.svg?style=social" alt="cat-filesystem-badge" /></a></p>
<p>Find all image files in the <code>/media/</code> directory matching the <code>img_[0-9]*.png</code> pattern.</p>
<p>A custom <a href="https://docs.rs/glob/*/glob/struct.MatchOptions.html"><code>MatchOptions</code></a> struct is passed to the <a href="https://docs.rs/glob/*/glob/fn.glob_with.html"><code>glob_with</code></a> function making the glob pattern case insensitive while keeping the other options <a href="https://doc.rust-lang.org/std/default/trait.Default.html"><code>Default</code></a>.</p>
<pre><pre class="playground"><code class="language-rust edition2018 no_run">use error_chain::error_chain;
use glob::{glob_with, MatchOptions};
error_chain! {
foreign_links {
Glob(glob::GlobError);
Pattern(glob::PatternError);
}
}
fn main() -&gt; Result&lt;()&gt; {
let options = MatchOptions {
case_sensitive: false,
..Default::default()
};
for entry in glob_with(&quot;/media/img_[0-9]*.png&quot;, options)? {
println!(&quot;{}&quot;, entry?.display());
}
Ok(())
}
</code></pre></pre>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#hardware-support-1" id="hardware-support-1">Hardware Support</a></h1>
<table><thead><tr><th>Recipe</th><th>Crates</th><th>Categories</th></tr></thead><tbody>
<tr><td><a href="hardware/processor.html#check-number-of-logical-cpu-cores">Check number of logical cpu cores</a></td><td><a href="https://docs.rs/num_cpus/"><img src="https://badge-cache.kominick.com/crates/v/num_cpus.svg?label=num_cpus" alt="num_cpus-badge" /></a></td><td><a href="https://crates.io/categories/hardware-support"><img src="https://badge-cache.kominick.com/badge/hardware_support--x.svg?style=social" alt="cat-hardware-support-badge" /></a></td></tr>
</tbody></table>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#processor" id="processor">Processor</a></h1>
<h2><a class="header" href="#check-number-of-logical-cpu-cores" id="check-number-of-logical-cpu-cores">Check number of logical cpu cores</a></h2>
<p><a href="https://docs.rs/num_cpus/"><img src="https://badge-cache.kominick.com/crates/v/num_cpus.svg?label=num_cpus" alt="num_cpus-badge" /></a> <a href="https://crates.io/categories/hardware-support"><img src="https://badge-cache.kominick.com/badge/hardware_support--x.svg?style=social" alt="cat-hardware-support-badge" /></a></p>
<p>Shows the number of logical CPU cores in current machine using [<code>num_cpus::get</code>].</p>
<pre><pre class="playground"><code class="language-rust edition2018">fn main() {
println!(&quot;Number of logical cores is {}&quot;, num_cpus::get());
}
</code></pre></pre>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#memory-management-1" id="memory-management-1">Memory Management</a></h1>
<table><thead><tr><th>Recipe</th><th>Crates</th><th>Categories</th></tr></thead><tbody>
<tr><td><a href="mem/global_static.html#declare-lazily-evaluated-constant">Declare lazily evaluated constant</a></td><td><a href="https://docs.rs/lazy_static/"><img src="https://badge-cache.kominick.com/crates/v/lazy_static.svg?label=lazy_static" alt="lazy_static-badge" /></a></td><td><a href="https://crates.io/categories/caching"><img src="https://badge-cache.kominick.com/badge/caching--x.svg?style=social" alt="cat-caching-badge" /></a> <a href="https://crates.io/categories/rust-patterns"><img src="https://badge-cache.kominick.com/badge/rust_patterns--x.svg?style=social" alt="cat-rust-patterns-badge" /></a></td></tr>
</tbody></table>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#constants" id="constants">Constants</a></h1>
<h2><a class="header" href="#declare-lazily-evaluated-constant" id="declare-lazily-evaluated-constant">Declare lazily evaluated constant</a></h2>
<p><a href="https://docs.rs/lazy_static/"><img src="https://badge-cache.kominick.com/crates/v/lazy_static.svg?label=lazy_static" alt="lazy_static-badge" /></a> <a href="https://crates.io/categories/caching"><img src="https://badge-cache.kominick.com/badge/caching--x.svg?style=social" alt="cat-caching-badge" /></a> <a href="https://crates.io/categories/rust-patterns"><img src="https://badge-cache.kominick.com/badge/rust_patterns--x.svg?style=social" alt="cat-rust-patterns-badge" /></a></p>
<p>Declares a lazily evaluated constant <a href="https://doc.rust-lang.org/std/collections/struct.HashMap.html"><code>HashMap</code></a>. The <a href="https://doc.rust-lang.org/std/collections/struct.HashMap.html"><code>HashMap</code></a> will
be evaluated once and stored behind a global static reference.</p>
<pre><pre class="playground"><code class="language-rust edition2018">use lazy_static::lazy_static;
use std::collections::HashMap;
lazy_static! {
static ref PRIVILEGES: HashMap&lt;&amp;'static str, Vec&lt;&amp;'static str&gt;&gt; = {
let mut map = HashMap::new();
map.insert(&quot;James&quot;, vec![&quot;user&quot;, &quot;admin&quot;]);
map.insert(&quot;Jim&quot;, vec![&quot;user&quot;]);
map
};
}
fn show_access(name: &amp;str) {
let access = PRIVILEGES.get(name);
println!(&quot;{}: {:?}&quot;, name, access);
}
fn main() {
let access = PRIVILEGES.get(&quot;James&quot;);
println!(&quot;James: {:?}&quot;, access);
show_access(&quot;Jim&quot;);
}
</code></pre></pre>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#networking-1" id="networking-1">Networking</a></h1>
<table><thead><tr><th>Recipe</th><th>Crates</th><th>Categories</th></tr></thead><tbody>
<tr><td><a href="net/server.html#listen-on-unused-port-tcpip">Listen on unused port TCP/IP</a></td><td><a href="https://doc.rust-lang.org/std"><img src="https://badge-cache.kominick.com/badge/std-1.29.1-blue.svg" alt="std-badge" /></a></td><td><a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a></td></tr>
</tbody></table>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#server" id="server">Server</a></h1>
<h2><a class="header" href="#listen-on-unused-port-tcpip" id="listen-on-unused-port-tcpip">Listen on unused port TCP/IP</a></h2>
<p><a href="https://doc.rust-lang.org/std"><img src="https://badge-cache.kominick.com/badge/std-1.29.1-blue.svg" alt="std-badge" /></a> <a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a></p>
<p>In this example, the port is displayed on the console, and the program will
listen until a request is made. <code>SocketAddrV4</code> assigns a random port when
setting port to 0.</p>
<pre><pre class="playground"><code class="language-rust edition2018 no_run">use std::net::{SocketAddrV4, Ipv4Addr, TcpListener};
use std::io::{Read, Error};
fn main() -&gt; Result&lt;(), Error&gt; {
let loopback = Ipv4Addr::new(127, 0, 0, 1);
let socket = SocketAddrV4::new(loopback, 0);
let listener = TcpListener::bind(socket)?;
let port = listener.local_addr()?;
println!(&quot;Listening on {}, access this port to end the program&quot;, port);
let (mut tcp_stream, addr) = listener.accept()?; //block until requested
println!(&quot;Connection received! {:?} is sending data.&quot;, addr);
let mut input = String::new();
let _ = tcp_stream.read_to_string(&amp;mut input)?;
println!(&quot;{:?} says {}&quot;, addr, input);
Ok(())
}
</code></pre></pre>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#operating-system-1" id="operating-system-1">Operating System</a></h1>
<table><thead><tr><th>Recipe</th><th>Crates</th><th>Categories</th></tr></thead><tbody>
<tr><td><a href="os/external.html#run-an-external-command-and-process-stdout">Run an external command and process stdout</a></td><td><a href="https://docs.rs/regex/"><img src="https://badge-cache.kominick.com/crates/v/regex.svg?label=regex" alt="regex-badge" /></a></td><td><a href="https://crates.io/categories/os"><img src="https://badge-cache.kominick.com/badge/OS--x.svg?style=social" alt="cat-os-badge" /></a> <a href="https://crates.io/categories/text-processing"><img src="https://badge-cache.kominick.com/badge/text_processing--x.svg?style=social" alt="cat-text-processing-badge" /></a></td></tr>
<tr><td><a href="os/external.html#run-an-external-command-passing-it-stdin-and-check-for-an-error-code">Run an external command passing it stdin and check for an error code</a></td><td><a href="https://docs.rs/regex/"><img src="https://badge-cache.kominick.com/crates/v/regex.svg?label=regex" alt="regex-badge" /></a></td><td><a href="https://crates.io/categories/os"><img src="https://badge-cache.kominick.com/badge/OS--x.svg?style=social" alt="cat-os-badge" /></a> <a href="https://crates.io/categories/text-processing"><img src="https://badge-cache.kominick.com/badge/text_processing--x.svg?style=social" alt="cat-text-processing-badge" /></a></td></tr>
<tr><td><a href="os/external.html#run-piped-external-commands">Run piped external commands</a></td><td><a href="https://doc.rust-lang.org/std"><img src="https://badge-cache.kominick.com/badge/std-1.29.1-blue.svg" alt="std-badge" /></a></td><td><a href="https://crates.io/categories/os"><img src="https://badge-cache.kominick.com/badge/OS--x.svg?style=social" alt="cat-os-badge" /></a></td></tr>
<tr><td><a href="os/external.html#redirect-both-stdout-and-stderr-of-child-process-to-the-same-file">Redirect both stdout and stderr of child process to the same file</a></td><td><a href="https://doc.rust-lang.org/std"><img src="https://badge-cache.kominick.com/badge/std-1.29.1-blue.svg" alt="std-badge" /></a></td><td><a href="https://crates.io/categories/os"><img src="https://badge-cache.kominick.com/badge/OS--x.svg?style=social" alt="cat-os-badge" /></a></td></tr>
<tr><td><a href="os/external.html#continuously-process-child-process-outputs">Continuously process child process' outputs</a></td><td><a href="https://doc.rust-lang.org/std"><img src="https://badge-cache.kominick.com/badge/std-1.29.1-blue.svg" alt="std-badge" /></a></td><td><a href="https://crates.io/categories/os"><img src="https://badge-cache.kominick.com/badge/OS--x.svg?style=social" alt="cat-os-badge" /></a><a href="https://crates.io/categories/text-processing"><img src="https://badge-cache.kominick.com/badge/text_processing--x.svg?style=social" alt="cat-text-processing-badge" /></a></td></tr>
<tr><td><a href="os/external.html#read-environment-variable">Read environment variable</a></td><td><a href="https://doc.rust-lang.org/std"><img src="https://badge-cache.kominick.com/badge/std-1.29.1-blue.svg" alt="std-badge" /></a></td><td><a href="https://crates.io/categories/os"><img src="https://badge-cache.kominick.com/badge/OS--x.svg?style=social" alt="cat-os-badge" /></a></td></tr>
</tbody></table>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#external-command" id="external-command">External Command</a></h1>
<h2><a class="header" href="#run-an-external-command-and-process-stdout" id="run-an-external-command-and-process-stdout">Run an external command and process stdout</a></h2>
<p><a href="https://docs.rs/regex/"><img src="https://badge-cache.kominick.com/crates/v/regex.svg?label=regex" alt="regex-badge" /></a> <a href="https://crates.io/categories/os"><img src="https://badge-cache.kominick.com/badge/OS--x.svg?style=social" alt="cat-os-badge" /></a> <a href="https://crates.io/categories/text-processing"><img src="https://badge-cache.kominick.com/badge/text_processing--x.svg?style=social" alt="cat-text-processing-badge" /></a></p>
<p>Runs <code>git log --oneline</code> as an external <a href="https://doc.rust-lang.org/std/process/struct.Command.html"><code>Command</code></a> and inspects its <a href="https://doc.rust-lang.org/std/process/struct.Output.html"><code>Output</code></a>
using <a href="https://docs.rs/regex/*/regex/struct.Regex.html"><code>Regex</code></a> to get the hash and message of the last 5 commits.</p>
<pre><pre class="playground"><code class="language-rust edition2018 no_run"><span class="boring">use error_chain::error_chain;
</span>
use std::process::Command;
use regex::Regex;
<span class="boring">
</span><span class="boring">error_chain!{
</span><span class="boring"> foreign_links {
</span><span class="boring"> Io(std::io::Error);
</span><span class="boring"> Regex(regex::Error);
</span><span class="boring"> Utf8(std::string::FromUtf8Error);
</span><span class="boring"> }
</span><span class="boring">}
</span>
#[derive(PartialEq, Default, Clone, Debug)]
struct Commit {
hash: String,
message: String,
}
fn main() -&gt; Result&lt;()&gt; {
let output = Command::new(&quot;git&quot;).arg(&quot;log&quot;).arg(&quot;--oneline&quot;).output()?;
if !output.status.success() {
error_chain::bail!(&quot;Command executed with failing error code&quot;);
}
let pattern = Regex::new(r&quot;(?x)
([0-9a-fA-F]+) # commit hash
(.*) # The commit message&quot;)?;
String::from_utf8(output.stdout)?
.lines()
.filter_map(|line| pattern.captures(line))
.map(|cap| {
Commit {
hash: cap[1].to_string(),
message: cap[2].trim().to_string(),
}
})
.take(5)
.for_each(|x| println!(&quot;{:?}&quot;, x));
Ok(())
}
</code></pre></pre>
<h2><a class="header" href="#run-an-external-command-passing-it-stdin-and-check-for-an-error-code" id="run-an-external-command-passing-it-stdin-and-check-for-an-error-code">Run an external command passing it stdin and check for an error code</a></h2>
<p><a href="https://doc.rust-lang.org/std"><img src="https://badge-cache.kominick.com/badge/std-1.29.1-blue.svg" alt="std-badge" /></a> <a href="https://crates.io/categories/os"><img src="https://badge-cache.kominick.com/badge/OS--x.svg?style=social" alt="cat-os-badge" /></a></p>
<p>Opens the <code>python</code> interpreter using an external <a href="https://doc.rust-lang.org/std/process/struct.Command.html"><code>Command</code></a> and passes it a
python statement for execution. <a href="https://doc.rust-lang.org/std/process/struct.Output.html"><code>Output</code></a> of statement is then parsed.</p>
<pre><pre class="playground"><code class="language-rust edition2018 no_run"><span class="boring">use error_chain::error_chain;
</span><span class="boring">
</span>use std::collections::HashSet;
use std::io::Write;
use std::process::{Command, Stdio};
<span class="boring">
</span><span class="boring">error_chain!{
</span><span class="boring"> errors { CmdError }
</span><span class="boring"> foreign_links {
</span><span class="boring"> Io(std::io::Error);
</span><span class="boring"> Utf8(std::string::FromUtf8Error);
</span><span class="boring"> }
</span><span class="boring">}
</span>
fn main() -&gt; Result&lt;()&gt; {
let mut child = Command::new(&quot;python&quot;).stdin(Stdio::piped())
.stderr(Stdio::piped())
.stdout(Stdio::piped())
.spawn()?;
child.stdin
.as_mut()
.ok_or(&quot;Child process stdin has not been captured!&quot;)?
.write_all(b&quot;import this; copyright(); credits(); exit()&quot;)?;
let output = child.wait_with_output()?;
if output.status.success() {
let raw_output = String::from_utf8(output.stdout)?;
let words = raw_output.split_whitespace()
.map(|s| s.to_lowercase())
.collect::&lt;HashSet&lt;_&gt;&gt;();
println!(&quot;Found {} unique words:&quot;, words.len());
println!(&quot;{:#?}&quot;, words);
Ok(())
} else {
let err = String::from_utf8(output.stderr)?;
error_chain::bail!(&quot;External command failed:\n {}&quot;, err)
}
}
</code></pre></pre>
<h2><a class="header" href="#run-piped-external-commands" id="run-piped-external-commands">Run piped external commands</a></h2>
<p><a href="https://doc.rust-lang.org/std"><img src="https://badge-cache.kominick.com/badge/std-1.29.1-blue.svg" alt="std-badge" /></a> <a href="https://crates.io/categories/os"><img src="https://badge-cache.kominick.com/badge/OS--x.svg?style=social" alt="cat-os-badge" /></a></p>
<p>Shows up to the 10<sup>th</sup> biggest files and subdirectories in
the current working directory. It is equivalent to running: <code>du -ah . | sort -hr | head -n 10</code>.</p>
<p><a href="https://doc.rust-lang.org/std/process/struct.Command.html"><code>Command</code></a>s represent a process. Output of a child process is captured with a
<a href="https://doc.rust-lang.org/std/process/struct.Stdio.html"><code>Stdio::piped</code></a> between parent and child.</p>
<pre><pre class="playground"><code class="language-rust edition2018 no_run"><span class="boring">use error_chain::error_chain;
</span><span class="boring">
</span>use std::process::{Command, Stdio};
<span class="boring">
</span><span class="boring">error_chain! {
</span><span class="boring"> foreign_links {
</span><span class="boring"> Io(std::io::Error);
</span><span class="boring"> Utf8(std::string::FromUtf8Error);
</span><span class="boring"> }
</span><span class="boring">}
</span>
fn main() -&gt; Result&lt;()&gt; {
let directory = std::env::current_dir()?;
let mut du_output_child = Command::new(&quot;du&quot;)
.arg(&quot;-ah&quot;)
.arg(&amp;directory)
.stdout(Stdio::piped())
.spawn()?;
if let Some(du_output) = du_output_child.stdout.take() {
let mut sort_output_child = Command::new(&quot;sort&quot;)
.arg(&quot;-hr&quot;)
.stdin(du_output)
.stdout(Stdio::piped())
.spawn()?;
du_output_child.wait()?;
if let Some(sort_output) = sort_output_child.stdout.take() {
let head_output_child = Command::new(&quot;head&quot;)
.args(&amp;[&quot;-n&quot;, &quot;10&quot;])
.stdin(sort_output)
.stdout(Stdio::piped())
.spawn()?;
let head_stdout = head_output_child.wait_with_output()?;
sort_output_child.wait()?;
println!(
&quot;Top 10 biggest files and directories in '{}':\n{}&quot;,
directory.display(),
String::from_utf8(head_stdout.stdout).unwrap()
);
}
}
Ok(())
}
</code></pre></pre>
<h2><a class="header" href="#redirect-both-stdout-and-stderr-of-child-process-to-the-same-file" id="redirect-both-stdout-and-stderr-of-child-process-to-the-same-file">Redirect both stdout and stderr of child process to the same file</a></h2>
<p><a href="https://doc.rust-lang.org/std"><img src="https://badge-cache.kominick.com/badge/std-1.29.1-blue.svg" alt="std-badge" /></a> <a href="https://crates.io/categories/os"><img src="https://badge-cache.kominick.com/badge/OS--x.svg?style=social" alt="cat-os-badge" /></a></p>
<p>Spawns a child process and redirects <code>stdout</code> and <code>stderr</code> to the same
file. It follows the same idea as <a href="os/external.html#run-piped-external-commands">run piped external
commands</a>, however <a href="https://doc.rust-lang.org/std/process/struct.Stdio.html"><code>process::Stdio</code></a>
writes to a specified file. <a href="https://doc.rust-lang.org/std/fs/struct.File.html#method.try_clone"><code>File::try_clone</code></a> references the same file handle
for <code>stdout</code> and <code>stderr</code>. It will ensure that both handles write with the same
cursor position.</p>
<p>The below recipe is equivalent to run the Unix shell command <code>ls . oops &gt;out.txt 2&gt;&amp;1</code>.</p>
<pre><pre class="playground"><code class="language-rust edition2018 no_run">use std::fs::File;
use std::io::Error;
use std::process::{Command, Stdio};
fn main() -&gt; Result&lt;(), Error&gt; {
let outputs = File::create(&quot;out.txt&quot;)?;
let errors = outputs.try_clone()?;
Command::new(&quot;ls&quot;)
.args(&amp;[&quot;.&quot;, &quot;oops&quot;])
.stdout(Stdio::from(outputs))
.stderr(Stdio::from(errors))
.spawn()?
.wait_with_output()?;
Ok(())
}
</code></pre></pre>
<h2><a class="header" href="#continuously-process-child-process-outputs" id="continuously-process-child-process-outputs">Continuously process child process' outputs</a></h2>
<p><a href="https://doc.rust-lang.org/std"><img src="https://badge-cache.kominick.com/badge/std-1.29.1-blue.svg" alt="std-badge" /></a> <a href="https://crates.io/categories/os"><img src="https://badge-cache.kominick.com/badge/OS--x.svg?style=social" alt="cat-os-badge" /></a></p>
<p>In <a href="os/external.html#run-an-external-command-and-process-stdout">Run an external command and process stdout</a>,
processing doesn't start until external <a href="https://doc.rust-lang.org/std/process/struct.Command.html"><code>Command</code></a> is finished.
The recipe below calls <a href="https://doc.rust-lang.org/std/process/struct.Stdio.html"><code>Stdio::piped</code></a> to create a pipe, and reads
<code>stdout</code> continuously as soon as the <a href="https://doc.rust-lang.org/std/io/struct.BufReader.html"><code>BufReader</code></a> is updated.</p>
<p>The below recipe is equivalent to the Unix shell command
<code>journalctl | grep usb</code>.</p>
<pre><pre class="playground"><code class="language-rust edition2018 no_run">use std::process::{Command, Stdio};
use std::io::{BufRead, BufReader, Error, ErrorKind};
fn main() -&gt; Result&lt;(), Error&gt; {
let stdout = Command::new(&quot;journalctl&quot;)
.stdout(Stdio::piped())
.spawn()?
.stdout
.ok_or_else(|| Error::new(ErrorKind::Other,&quot;Could not capture standard output.&quot;))?;
let reader = BufReader::new(stdout);
reader
.lines()
.filter_map(|line| line.ok())
.filter(|line| line.find(&quot;usb&quot;).is_some())
.for_each(|line| println!(&quot;{}&quot;, line));
Ok(())
}
</code></pre></pre>
<h2><a class="header" href="#read-environment-variable" id="read-environment-variable">Read Environment Variable</a></h2>
<p><a href="https://doc.rust-lang.org/std"><img src="https://badge-cache.kominick.com/badge/std-1.29.1-blue.svg" alt="std-badge" /></a> <a href="https://crates.io/categories/os"><img src="https://badge-cache.kominick.com/badge/OS--x.svg?style=social" alt="cat-os-badge" /></a></p>
<p>Reads an environment variable via <a href="https://doc.rust-lang.org/std/env/fn.var.html">std::env::var</a>.</p>
<pre><pre class="playground"><code class="language-rust edition2018 no_run">use std::env;
use std::fs;
use std::io::Error;
fn main() -&gt; Result&lt;(), Error&gt; {
// read `config_path` from the environment variable `CONFIG`.
// If `CONFIG` isn't set, fall back to a default config path.
let config_path = env::var(&quot;CONFIG&quot;)
.unwrap_or(&quot;/etc/myapp/config&quot;.to_string());
let config: String = fs::read_to_string(config_path)?;
println!(&quot;Config: {}&quot;, config);
Ok(())
}
</code></pre></pre>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#science-1" id="science-1">Science</a></h1>
<h2><a class="header" href="#mathematics-1" id="mathematics-1">Mathematics</a></h2>
<table><thead><tr><th>Recipe</th><th>Crates</th><th>Categories</th></tr></thead><tbody>
<tr><td><a href="mathematics/linear_algebra.html#vector-norm">Vector Norm</a></td><td><a href="https://docs.rs/ndarray"><img src="https://badge-cache.kominick.com/crate/ndarray.svg?label=ndarray" alt="ndarray-badge" /></a></td><td><a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></td></tr>
<tr><td><a href="mathematics/linear_algebra.html#adding-matrices">Adding matrices</a></td><td><a href="https://docs.rs/ndarray"><img src="https://badge-cache.kominick.com/crate/ndarray.svg?label=ndarray" alt="ndarray-badge" /></a></td><td><a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></td></tr>
<tr><td><a href="mathematics/linear_algebra.html#multiplying-matrices">Multiplying matrices</a></td><td><a href="https://docs.rs/ndarray"><img src="https://badge-cache.kominick.com/crate/ndarray.svg?label=ndarray" alt="ndarray-badge" /></a></td><td><a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></td></tr>
<tr><td><a href="mathematics/linear_algebra.html#multiply-a-scalar-with-a-vector-with-a-matrix">Multiply a scalar with a vector with a matrix</a></td><td><a href="https://docs.rs/ndarray"><img src="https://badge-cache.kominick.com/crate/ndarray.svg?label=ndarray" alt="ndarray-badge" /></a></td><td><a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></td></tr>
<tr><td><a href="mathematics/linear_algebra.html#invert-matrix">Invert matrix</a></td><td><a href="https://docs.rs/nalgebra"><img src="https://badge-cache.kominick.com/crate/nalgebra.svg?label=nalgebra" alt="nalgebra-badge" /></a></td><td><a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></td></tr>
<tr><td><a href="mathematics/trigonometry.html#calculating-the-side-length-of-a-triangle">Calculating the side length of a triangle</a></td><td><a href="https://doc.rust-lang.org/std"><img src="https://badge-cache.kominick.com/badge/std-1.29.1-blue.svg" alt="std-badge" /></a></td><td><a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></td></tr>
<tr><td><a href="mathematics/trigonometry.html#verifying-tan-is-equal-to-sin-divided-by-cos">Verifying tan is equal to sin divided by cos</a></td><td><a href="https://doc.rust-lang.org/std"><img src="https://badge-cache.kominick.com/badge/std-1.29.1-blue.svg" alt="std-badge" /></a></td><td><a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></td></tr>
<tr><td><a href="mathematics/trigonometry.html#distance-between-two-points-on-the-earth">Distance between two points on the Earth</a></td><td><a href="https://doc.rust-lang.org/std"><img src="https://badge-cache.kominick.com/badge/std-1.29.1-blue.svg" alt="std-badge" /></a></td><td><a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></td></tr>
<tr><td><a href="mathematics/complex_numbers.html#creating-complex-numbers">Creating complex numbers</a></td><td><a href="https://docs.rs/num/"><img src="https://badge-cache.kominick.com/crates/v/num.svg?label=num" alt="num-badge" /></a></td><td><a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></td></tr>
<tr><td><a href="mathematics/complex_numbers.html#adding-complex-numbers">Adding complex numbers</a></td><td><a href="https://docs.rs/num/"><img src="https://badge-cache.kominick.com/crates/v/num.svg?label=num" alt="num-badge" /></a></td><td><a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></td></tr>
<tr><td><a href="mathematics/complex_numbers.html#mathematical-functions">Mathematical functions on complex numbers</a></td><td><a href="https://docs.rs/num/"><img src="https://badge-cache.kominick.com/crates/v/num.svg?label=num" alt="num-badge" /></a></td><td><a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></td></tr>
<tr><td><a href="mathematics/statistics.html#measures-of-central-tendency">Measures of central tendency</a></td><td><a href="https://doc.rust-lang.org/std"><img src="https://badge-cache.kominick.com/badge/std-1.29.1-blue.svg" alt="std-badge" /></a></td><td><a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></td></tr>
<tr><td><a href="mathematics/statistics.html#standard-deviation">Computing standard deviation</a></td><td><a href="https://doc.rust-lang.org/std"><img src="https://badge-cache.kominick.com/badge/std-1.29.1-blue.svg" alt="std-badge" /></a></td><td><a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></td></tr>
<tr><td><a href="mathematics/miscellaneous.html#big-integers">Big integers</a></td><td><a href="https://docs.rs/num/"><img src="https://badge-cache.kominick.com/crates/v/num.svg?label=num" alt="num-badge" /></a></td><td><a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></td></tr>
</tbody></table>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h2><a class="header" href="#mathematics-2" id="mathematics-2">Mathematics</a></h2>
<table><thead><tr><th>Recipe</th><th>Crates</th><th>Categories</th></tr></thead><tbody>
<tr><td><a href="science/mathematics/linear_algebra.html#vector-norm">Vector Norm</a></td><td><a href="https://docs.rs/ndarray"><img src="https://badge-cache.kominick.com/crate/ndarray.svg?label=ndarray" alt="ndarray-badge" /></a></td><td><a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></td></tr>
<tr><td><a href="science/mathematics/linear_algebra.html#adding-matrices">Adding matrices</a></td><td><a href="https://docs.rs/ndarray"><img src="https://badge-cache.kominick.com/crate/ndarray.svg?label=ndarray" alt="ndarray-badge" /></a></td><td><a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></td></tr>
<tr><td><a href="science/mathematics/linear_algebra.html#multiplying-matrices">Multiplying matrices</a></td><td><a href="https://docs.rs/ndarray"><img src="https://badge-cache.kominick.com/crate/ndarray.svg?label=ndarray" alt="ndarray-badge" /></a></td><td><a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></td></tr>
<tr><td><a href="science/mathematics/linear_algebra.html#multiply-a-scalar-with-a-vector-with-a-matrix">Multiply a scalar with a vector with a matrix</a></td><td><a href="https://docs.rs/ndarray"><img src="https://badge-cache.kominick.com/crate/ndarray.svg?label=ndarray" alt="ndarray-badge" /></a></td><td><a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></td></tr>
<tr><td><a href="science/mathematics/linear_algebra.html#invert-matrix">Invert matrix</a></td><td><a href="https://docs.rs/nalgebra"><img src="https://badge-cache.kominick.com/crate/nalgebra.svg?label=nalgebra" alt="nalgebra-badge" /></a></td><td><a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></td></tr>
<tr><td><a href="science/mathematics/trigonometry.html#calculating-the-side-length-of-a-triangle">Calculating the side length of a triangle</a></td><td><a href="https://doc.rust-lang.org/std"><img src="https://badge-cache.kominick.com/badge/std-1.29.1-blue.svg" alt="std-badge" /></a></td><td><a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></td></tr>
<tr><td><a href="science/mathematics/trigonometry.html#verifying-tan-is-equal-to-sin-divided-by-cos">Verifying tan is equal to sin divided by cos</a></td><td><a href="https://doc.rust-lang.org/std"><img src="https://badge-cache.kominick.com/badge/std-1.29.1-blue.svg" alt="std-badge" /></a></td><td><a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></td></tr>
<tr><td><a href="science/mathematics/trigonometry.html#distance-between-two-points-on-the-earth">Distance between two points on the Earth</a></td><td><a href="https://doc.rust-lang.org/std"><img src="https://badge-cache.kominick.com/badge/std-1.29.1-blue.svg" alt="std-badge" /></a></td><td><a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></td></tr>
<tr><td><a href="science/mathematics/complex_numbers.html#creating-complex-numbers">Creating complex numbers</a></td><td><a href="https://docs.rs/num/"><img src="https://badge-cache.kominick.com/crates/v/num.svg?label=num" alt="num-badge" /></a></td><td><a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></td></tr>
<tr><td><a href="science/mathematics/complex_numbers.html#adding-complex-numbers">Adding complex numbers</a></td><td><a href="https://docs.rs/num/"><img src="https://badge-cache.kominick.com/crates/v/num.svg?label=num" alt="num-badge" /></a></td><td><a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></td></tr>
<tr><td><a href="science/mathematics/complex_numbers.html#mathematical-functions">Mathematical functions on complex numbers</a></td><td><a href="https://docs.rs/num/"><img src="https://badge-cache.kominick.com/crates/v/num.svg?label=num" alt="num-badge" /></a></td><td><a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></td></tr>
<tr><td><a href="science/mathematics/statistics.html#measures-of-central-tendency">Measures of central tendency</a></td><td><a href="https://doc.rust-lang.org/std"><img src="https://badge-cache.kominick.com/badge/std-1.29.1-blue.svg" alt="std-badge" /></a></td><td><a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></td></tr>
<tr><td><a href="science/mathematics/statistics.html#standard-deviation">Computing standard deviation</a></td><td><a href="https://doc.rust-lang.org/std"><img src="https://badge-cache.kominick.com/badge/std-1.29.1-blue.svg" alt="std-badge" /></a></td><td><a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></td></tr>
<tr><td><a href="science/mathematics/miscellaneous.html#big-integers">Big integers</a></td><td><a href="https://docs.rs/num/"><img src="https://badge-cache.kominick.com/crates/v/num.svg?label=num" alt="num-badge" /></a></td><td><a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></td></tr>
</tbody></table>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#linear-algebra" id="linear-algebra">Linear Algebra</a></h1>
<h2><a class="header" href="#adding-matrices" id="adding-matrices">Adding matrices</a></h2>
<p><a href="https://docs.rs/crate/ndarray/*"><img src="https://badge-cache.kominick.com/crate/ndarray.svg?label=ndarray" alt="ndarray-badge" /></a> <a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></p>
<p>Creates two 2-D matrices with <a href="https://docs.rs/ndarray/*/ndarray/fn.arr2.html"><code>ndarray::arr2</code></a> and sums them element-wise.</p>
<p>Note the sum is computed as <code>let sum = &amp;a + &amp;b</code>. The <code>&amp;</code> operator is used to avoid consuming <code>a</code> and <code>b</code>, making them available later for display. A new array is created containing their sum.</p>
<pre><pre class="playground"><code class="language-rust edition2018">use ndarray::arr2;
fn main() {
let a = arr2(&amp;[[1, 2, 3],
[4, 5, 6]]);
let b = arr2(&amp;[[6, 5, 4],
[3, 2, 1]]);
let sum = &amp;a + &amp;b;
println!(&quot;{}&quot;, a);
println!(&quot;+&quot;);
println!(&quot;{}&quot;, b);
println!(&quot;=&quot;);
println!(&quot;{}&quot;, sum);
}
</code></pre></pre>
<h2><a class="header" href="#multiplying-matrices" id="multiplying-matrices">Multiplying matrices</a></h2>
<p><a href="https://docs.rs/crate/ndarray/*"><img src="https://badge-cache.kominick.com/crate/ndarray.svg?label=ndarray" alt="ndarray-badge" /></a> <a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></p>
<p>Creates two matrices with <a href="https://docs.rs/ndarray/*/ndarray/fn.arr2.html"><code>ndarray::arr2</code></a> and performs matrix multiplication on them with <a href="https://docs.rs/ndarray/*/ndarray/struct.ArrayBase.html#method.dot-1"><code>ndarray::ArrayBase::dot</code></a>.</p>
<pre><pre class="playground"><code class="language-rust edition2018">use ndarray::arr2;
fn main() {
let a = arr2(&amp;[[1, 2, 3],
[4, 5, 6]]);
let b = arr2(&amp;[[6, 3],
[5, 2],
[4, 1]]);
println!(&quot;{}&quot;, a.dot(&amp;b));
}
</code></pre></pre>
<h2><a class="header" href="#multiply-a-scalar-with-a-vector-with-a-matrix" id="multiply-a-scalar-with-a-vector-with-a-matrix">Multiply a scalar with a vector with a matrix</a></h2>
<p><a href="https://docs.rs/crate/ndarray/*"><img src="https://badge-cache.kominick.com/crate/ndarray.svg?label=ndarray" alt="ndarray-badge" /></a> <a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></p>
<p>Creates a 1-D array (vector) with <a href="https://docs.rs/ndarray/*/ndarray/fn.arr1.html"><code>ndarray::arr1</code></a> and a 2-D array (matrix)
with <a href="https://docs.rs/ndarray/*/ndarray/fn.arr2.html"><code>ndarray::arr2</code></a>.</p>
<p>First, a scalar is multiplied by the vector to get
another vector. Then, the matrix is multiplied by the new vector with
<a href="https://docs.rs/ndarray/*/ndarray/struct.ArrayBase.html#method.dot-1"><code>ndarray::Array2::dot</code></a>. (Matrix multiplication is performed using <code>dot</code>, while
the <code>*</code> operator performs element-wise multiplication.)</p>
<p>In <code>ndarray</code>, 1-D arrays can be interpreted as either row or column vectors
depending on context. If representing the orientation of a vector is important,
a 2-D array with one row or one column must be used instead. In this example,
the vector is a 1-D array on the right-hand side, so <code>dot</code> handles it as a column
vector.</p>
<pre><pre class="playground"><code class="language-rust edition2018">use ndarray::{arr1, arr2, Array1};
fn main() {
let scalar = 4;
let vector = arr1(&amp;[1, 2, 3]);
let matrix = arr2(&amp;[[4, 5, 6],
[7, 8, 9]]);
let new_vector: Array1&lt;_&gt; = scalar * vector;
println!(&quot;{}&quot;, new_vector);
let new_matrix = matrix.dot(&amp;new_vector);
println!(&quot;{}&quot;, new_matrix);
}
</code></pre></pre>
<h2><a class="header" href="#vector-comparison" id="vector-comparison">Vector comparison</a></h2>
<p><a href="https://docs.rs/crate/ndarray/*"><img src="https://badge-cache.kominick.com/crate/ndarray.svg?label=ndarray" alt="ndarray-badge" /></a></p>
<p>The <a href="https://docs.rs/crate/ndarray/*">ndarray</a> crate supports a number of ways to create arrays -- this recipe creates
<a href="https://docs.rs/ndarray/*/ndarray/struct.ArrayBase.html"><code>ndarray::Array</code></a>s from <code>std::Vec</code> using <code>from</code>. Then, it sums the arrays element-wise.</p>
<p>This recipe contains an example of comparing two floating-point vectors element-wise.
Floating-point numbers are often stored inexactly, making exact comparisons difficult.
However, the <a href="https://docs.rs/approx/*/approx/macro.assert_abs_diff_eq.html"><code>assert_abs_diff_eq!</code></a> macro from the <a href="https://docs.rs/approx/*/approx/index.html"><code>approx</code></a> crate allows for convenient
element-wise comparisons. To use the <code>approx</code> crate with <code>ndarray</code>, the <code>approx</code>
feature must be added to the <code>ndarray</code> dependency in <code>Cargo.toml</code>. For example,
<code>ndarray = { version = &quot;0.13&quot;, features = [&quot;approx&quot;] }</code>.</p>
<p>This recipe also contains additional ownership examples. Here, <code>let z = a + b</code> consumes
<code>a</code> and <code>b</code>, updates <code>a</code> with the result, then moves ownership to <code>z</code>. Alternatively,
<code>let w = &amp;c + &amp;d</code> creates a new vector without consuming <code>c</code> or <code>d</code>, allowing
their modification later. See <a href="https://docs.rs/ndarray/*/ndarray/struct.ArrayBase.html#binary-operators-with-two-arrays">Binary Operators With Two Arrays</a> for additional detail.</p>
<pre><pre class="playground"><code class="language-rust edition2018">use approx::assert_abs_diff_eq;
use ndarray::Array;
fn main() {
let a = Array::from(vec![1., 2., 3., 4., 5.]);
let b = Array::from(vec![5., 4., 3., 2., 1.]);
let mut c = Array::from(vec![1., 2., 3., 4., 5.]);
let mut d = Array::from(vec![5., 4., 3., 2., 1.]);
let z = a + b;
let w = &amp;c + &amp;d;
assert_abs_diff_eq!(z, Array::from(vec![6., 6., 6., 6., 6.]));
println!(&quot;c = {}&quot;, c);
c[0] = 10.;
d[1] = 10.;
assert_abs_diff_eq!(w, Array::from(vec![6., 6., 6., 6., 6.]));
}
</code></pre></pre>
<h2><a class="header" href="#vector-norm" id="vector-norm">Vector norm</a></h2>
<p><a href="https://docs.rs/crate/ndarray/*"><img src="https://badge-cache.kominick.com/crate/ndarray.svg?label=ndarray" alt="ndarray-badge" /></a></p>
<p>This recipe demonstrates use of the <a href="https://docs.rs/ndarray/*/ndarray/type.Array1.html"><code>Array1</code></a> type, <a href="https://docs.rs/ndarray/*/ndarray/type.ArrayView1.html"><code>ArrayView1</code></a> type,
<a href="https://docs.rs/ndarray/*/ndarray/struct.ArrayBase.html#method.fold"><code>fold</code></a> method, and <a href="https://docs.rs/ndarray/*/ndarray/struct.ArrayBase.html#method.dot"><code>dot</code></a> method in computing the <a href="http://mathworld.wolfram.com/L1-Norm.html">l1</a> and <a href="http://mathworld.wolfram.com/L2-Norm.html">l2</a> norms of a
given vector.
+ The <code>l2_norm</code> function is the simpler of the two, as it computes the
square root of the dot product of a vector with itself.
+ The <code>l1_norm</code> function is computed by a <code>fold</code>
operation that sums the absolute values of the elements. (This could also be
performed with <code>x.mapv(f64::abs).scalar_sum()</code>, but that would allocate a new
array for the result of the <code>mapv</code>.)</p>
<p>Note that both <code>l1_norm</code> and <code>l2_norm</code> take the <a href="https://docs.rs/ndarray/*/ndarray/type.ArrayView1.html"><code>ArrayView1</code></a> type. This recipe
considers vector norms, so the norm functions only need to accept one-dimensional
views (hence <a href="https://docs.rs/ndarray/*/ndarray/type.ArrayView1.html"><code>ArrayView1</code></a>). While the functions could take a
parameter of type <code>&amp;Array1&lt;f64&gt;</code> instead, that would require the caller to have
a reference to an owned array, which is more restrictive than just having access
to a view (since a view can be created from any array or view, not just an owned
array).</p>
<p><code>Array</code> and <code>ArrayView</code> are both type aliases for <code>ArrayBase</code>. So, the most
general argument type for the caller would be <code>&amp;ArrayBase&lt;S, Ix1&gt; where S: Data</code>,
because then the caller could use <code>&amp;array</code> or <code>&amp;view</code> instead of <code>x.view()</code>.
If the function is part of a public API, that may be a better choice for the
benefit of users. For internal functions, the more concise <code>ArrayView1&lt;f64&gt;</code>
may be preferable.</p>
<pre><pre class="playground"><code class="language-rust edition2018">use ndarray::{array, Array1, ArrayView1};
fn l1_norm(x: ArrayView1&lt;f64&gt;) -&gt; f64 {
x.fold(0., |acc, elem| acc + elem.abs())
}
fn l2_norm(x: ArrayView1&lt;f64&gt;) -&gt; f64 {
x.dot(&amp;x).sqrt()
}
fn normalize(mut x: Array1&lt;f64&gt;) -&gt; Array1&lt;f64&gt; {
let norm = l2_norm(x.view());
x.mapv_inplace(|e| e/norm);
x
}
fn main() {
let x = array![1., 2., 3., 4., 5.];
println!(&quot;||x||_2 = {}&quot;, l2_norm(x.view()));
println!(&quot;||x||_1 = {}&quot;, l1_norm(x.view()));
println!(&quot;Normalizing x yields {:?}&quot;, normalize(x));
}
</code></pre></pre>
<h2><a class="header" href="#invert-matrix" id="invert-matrix">Invert matrix</a></h2>
<p><a href="https://docs.rs/nalgebra"><img src="https://badge-cache.kominick.com/crate/nalgebra.svg?label=nalgebra" alt="nalgebra-badge" /></a> <a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></p>
<p>Creates a 3x3 matrix with <a href="https://docs.rs/nalgebra/*/nalgebra/base/type.Matrix3.html"><code>nalgebra::Matrix3</code></a> and inverts it, if possible.</p>
<pre><pre class="playground"><code class="language-rust edition2018">use nalgebra::Matrix3;
fn main() {
let m1 = Matrix3::new(2.0, 1.0, 1.0, 3.0, 2.0, 1.0, 2.0, 1.0, 2.0);
println!(&quot;m1 = {}&quot;, m1);
match m1.try_inverse() {
Some(inv) =&gt; {
println!(&quot;The inverse of m1 is: {}&quot;, inv);
}
None =&gt; {
println!(&quot;m1 is not invertible!&quot;);
}
}
}
</code></pre></pre>
<h2><a class="header" href="#de-serialize-a-matrix" id="de-serialize-a-matrix">(De)-Serialize a Matrix</a></h2>
<p><a href="https://docs.rs/crate/ndarray/*"><img src="https://badge-cache.kominick.com/crate/ndarray.svg?label=ndarray" alt="ndarray-badge" /></a> <a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></p>
<p>Serialize and deserialize a matrix to and from JSON. Serialization is taken care of
by <a href="https://docs.rs/serde_json/*/serde_json/fn.to_string.html"><code>serde_json::to_string</code></a> and <a href="https://docs.rs/serde_json/*/serde_json/fn.from_str.html"><code>serde_json::from_str</code></a> performs deserialization.</p>
<p>Note that serialization followed by deserialization gives back the original matrix.</p>
<pre><pre class="playground"><code class="language-rust">extern crate nalgebra;
extern crate serde_json;
use nalgebra::DMatrix;
fn main() -&gt; Result&lt;(), std::io::Error&gt; {
let row_slice: Vec&lt;i32&gt; = (1..5001).collect();
let matrix = DMatrix::from_row_slice(50, 100, &amp;row_slice);
// serialize matrix
let serialized_matrix = serde_json::to_string(&amp;matrix)?;
// deserialize matrix
let deserialized_matrix: DMatrix&lt;i32&gt; = serde_json::from_str(&amp;serialized_matrix)?;
// verify that `deserialized_matrix` is equal to `matrix`
assert!(deserialized_matrix == matrix);
Ok(())
}
</code></pre></pre>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#trigonometry" id="trigonometry">Trigonometry</a></h1>
<h2><a class="header" href="#calculating-the-side-length-of-a-triangle" id="calculating-the-side-length-of-a-triangle">Calculating the side length of a triangle</a></h2>
<p><a href="https://doc.rust-lang.org/std"><img src="https://badge-cache.kominick.com/badge/std-1.29.1-blue.svg" alt="std-badge" /></a> <a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></p>
<p>Calculates the length of the hypotenuse of a right-angle triangle with an angle of 2 radians and opposite side length of 80.</p>
<pre><pre class="playground"><code class="language-rust edition2018">fn main() {
let angle: f64 = 2.0;
let side_length = 80.0;
let hypotenuse = side_length / angle.sin();
println!(&quot;Hypotenuse: {}&quot;, hypotenuse);
}
</code></pre></pre>
<h2><a class="header" href="#verifying-tan-is-equal-to-sin-divided-by-cos" id="verifying-tan-is-equal-to-sin-divided-by-cos">Verifying tan is equal to sin divided by cos</a></h2>
<p><a href="https://doc.rust-lang.org/std"><img src="https://badge-cache.kominick.com/badge/std-1.29.1-blue.svg" alt="std-badge" /></a> <a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></p>
<p>Verifies tan(x) is equal to sin(x)/cos(x) for x = 6.</p>
<pre><pre class="playground"><code class="language-rust edition2018">fn main() {
let x: f64 = 6.0;
let a = x.tan();
let b = x.sin() / x.cos();
assert_eq!(a, b);
}
</code></pre></pre>
<h2><a class="header" href="#distance-between-two-points-on-the-earth" id="distance-between-two-points-on-the-earth">Distance between two points on the Earth</a></h2>
<p><a href="https://doc.rust-lang.org/std"><img src="https://badge-cache.kominick.com/badge/std-1.29.1-blue.svg" alt="std-badge" /></a></p>
<p>By default, Rust provides mathematical <a href="https://doc.rust-lang.org/std/primitive.f64.html#methods">float methods</a> such as
trigonometric functions, square root, conversion functions between
radians and degrees, and so forth.</p>
<p>The following example computes the distance in kilometers between two
points on the Earth with the <a href="https://en.wikipedia.org/wiki/Haversine_formula">Haversine formula</a>. Points are expressed
as pairs of latitude and longitude in degrees. Then, <a href="https://doc.rust-lang.org/std/primitive.f64.html#method.to_radians"><code>to_radians</code></a>
converts them in radian. <a href="https://doc.rust-lang.org/std/primitive.f64.html#method.sin"><code>sin</code></a>, <a href="https://doc.rust-lang.org/std/primitive.f64.html#method.cos"><code>cos</code></a>, <a href="https://doc.rust-lang.org/std/primitive.f64.html#method.powi"><code>powi</code></a> and <a href="https://doc.rust-lang.org/std/primitive.f64.html#method.sqrt"><code>sqrt</code></a>
compute the central angle. Finally, it's possible to calculate the
distance.</p>
<pre><pre class="playground"><code class="language-rust edition2018">fn main() {
let earth_radius_kilometer = 6371.0_f64;
let (paris_latitude_degrees, paris_longitude_degrees) = (48.85341_f64, -2.34880_f64);
let (london_latitude_degrees, london_longitude_degrees) = (51.50853_f64, -0.12574_f64);
let paris_latitude = paris_latitude_degrees.to_radians();
let london_latitude = london_latitude_degrees.to_radians();
let delta_latitude = (paris_latitude_degrees - london_latitude_degrees).to_radians();
let delta_longitude = (paris_longitude_degrees - london_longitude_degrees).to_radians();
let central_angle_inner = (delta_latitude / 2.0).sin().powi(2)
+ paris_latitude.cos() * london_latitude.cos() * (delta_longitude / 2.0).sin().powi(2);
let central_angle = 2.0 * central_angle_inner.sqrt().asin();
let distance = earth_radius_kilometer * central_angle;
println!(
&quot;Distance between Paris and London on the surface of Earth is {:.1} kilometers&quot;,
distance
);
}
</code></pre></pre>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#complex-numbers" id="complex-numbers">Complex numbers</a></h1>
<h2><a class="header" href="#creating-complex-numbers" id="creating-complex-numbers">Creating complex numbers</a></h2>
<p><a href="https://docs.rs/num/"><img src="https://badge-cache.kominick.com/crates/v/num.svg?label=num" alt="num-badge" /></a> <a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></p>
<p>Creates complex numbers of type <a href="https://autumnai.github.io/cuticula/num/complex/struct.Complex.html"><code>num::complex::Complex</code></a>. Both the real and
imaginary part of the complex number must be of the same type.</p>
<pre><pre class="playground"><code class="language-rust edition2018">fn main() {
let complex_integer = num::complex::Complex::new(10, 20);
let complex_float = num::complex::Complex::new(10.1, 20.1);
println!(&quot;Complex integer: {}&quot;, complex_integer);
println!(&quot;Complex float: {}&quot;, complex_float);
}
</code></pre></pre>
<h2><a class="header" href="#adding-complex-numbers" id="adding-complex-numbers">Adding complex numbers</a></h2>
<p><a href="https://docs.rs/num/"><img src="https://badge-cache.kominick.com/crates/v/num.svg?label=num" alt="num-badge" /></a> <a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></p>
<p>Performing mathematical operations on complex numbers is the same as on
built in types: the numbers in question must be of the same type (i.e. floats
or integers).</p>
<pre><pre class="playground"><code class="language-rust edition2018">fn main() {
let complex_num1 = num::complex::Complex::new(10.0, 20.0); // Must use floats
let complex_num2 = num::complex::Complex::new(3.1, -4.2);
let sum = complex_num1 + complex_num2;
println!(&quot;Sum: {}&quot;, sum);
}
</code></pre></pre>
<h2><a class="header" href="#mathematical-functions" id="mathematical-functions">Mathematical functions</a></h2>
<p><a href="https://docs.rs/num/"><img src="https://badge-cache.kominick.com/crates/v/num.svg?label=num" alt="num-badge" /></a> <a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></p>
<p>Complex numbers have a range of interesting properties when it comes to
how they interact with other mathematical functions, most notibly the family
of sine functions as well as the number e. To use these functions with
complex numbers, the Complex type has a few built in
functions, all of which can be found here: <a href="https://autumnai.github.io/cuticula/num/complex/struct.Complex.html"><code>num::complex::Complex</code></a>.</p>
<pre><pre class="playground"><code class="language-rust edition2018">use std::f64::consts::PI;
use num::complex::Complex;
fn main() {
let x = Complex::new(0.0, 2.0*PI);
println!(&quot;e^(2i * pi) = {}&quot;, x.exp()); // =~1
}
</code></pre></pre>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#statistics" id="statistics">Statistics</a></h1>
<h3><a class="header" href="#measures-of-central-tendency" id="measures-of-central-tendency">Measures of central tendency</a></h3>
<p><a href="https://doc.rust-lang.org/std"><img src="https://badge-cache.kominick.com/badge/std-1.29.1-blue.svg" alt="std-badge" /></a> <a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></p>
<p>These examples calculate measures of central tendency for a data set contained within a Rust array. There may be no mean, median or mode to calculate for an empty set of data, so each function returns an <a href="https://doc.rust-lang.org/std/option/enum.Option.html"><code>Option</code></a> to be handled by the caller.</p>
<p>The first example calculates the mean (the sum of all measurements divided by the number of measurements in the set) by producing an iterator of references over the data, and using <a href="https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.sum"><code>sum</code></a> and <a href="https://doc.rust-lang.org/std/primitive.slice.html#method.len"><code>len</code></a> to determine the total value and count of values respectively.</p>
<pre><pre class="playground"><code class="language-rust edition2018">fn main() {
let data = [3, 1, 6, 1, 5, 8, 1, 8, 10, 11];
let sum = data.iter().sum::&lt;i32&gt;() as f32;
let count = data.len();
let mean = match count {
positive if positive &gt; 0 =&gt; Some(sum / count as f32),
_ =&gt; None
};
println!(&quot;Mean of the data is {:?}&quot;, mean);
}
</code></pre></pre>
<p>The second example calculates the median using the quickselect algorithm, which avoids a full <a href="https://doc.rust-lang.org/std/primitive.slice.html#method.sort"><code>sort</code></a> by sorting only partitions of the data set known to possibly contain the median. This uses <a href="https://doc.rust-lang.org/std/cmp/trait.Ord.html#tymethod.cmp"><code>cmp</code></a> and <a href="https://doc.rust-lang.org/std/cmp/enum.Ordering.html"><code>Ordering</code></a> to succinctly decide the next partition to examine, and <a href="https://doc.rust-lang.org/std/primitive.slice.html#method.split_at"><code>split_at</code></a> to choose an arbitrary pivot for the next partition at each step.</p>
<pre><pre class="playground"><code class="language-rust edition2018">use std::cmp::Ordering;
fn partition(data: &amp;[i32]) -&gt; Option&lt;(Vec&lt;i32&gt;, i32, Vec&lt;i32&gt;)&gt; {
match data.len() {
0 =&gt; None,
_ =&gt; {
let (pivot_slice, tail) = data.split_at(1);
let pivot = pivot_slice[0];
let (left, right) = tail.iter()
.fold((vec![], vec![]), |mut splits, next| {
{
let (ref mut left, ref mut right) = &amp;mut splits;
if next &lt; &amp;pivot {
left.push(*next);
} else {
right.push(*next);
}
}
splits
});
Some((left, pivot, right))
}
}
}
fn select(data: &amp;[i32], k: usize) -&gt; Option&lt;i32&gt; {
let part = partition(data);
match part {
None =&gt; None,
Some((left, pivot, right)) =&gt; {
let pivot_idx = left.len();
match pivot_idx.cmp(&amp;k) {
Ordering::Equal =&gt; Some(pivot),
Ordering::Greater =&gt; select(&amp;left, k),
Ordering::Less =&gt; select(&amp;right, k - (pivot_idx + 1)),
}
},
}
}
fn median(data: &amp;[i32]) -&gt; Option&lt;f32&gt; {
let size = data.len();
match size {
even if even % 2 == 0 =&gt; {
let fst_med = select(data, (even / 2) - 1);
let snd_med = select(data, even / 2);
match (fst_med, snd_med) {
(Some(fst), Some(snd)) =&gt; Some((fst + snd) as f32 / 2.0),
_ =&gt; None
}
},
odd =&gt; select(data, odd / 2).map(|x| x as f32)
}
}
fn main() {
let data = [3, 1, 6, 1, 5, 8, 1, 8, 10, 11];
let part = partition(&amp;data);
println!(&quot;Partition is {:?}&quot;, part);
let sel = select(&amp;data, 5);
println!(&quot;Selection at ordered index {} is {:?}&quot;, 5, sel);
let med = median(&amp;data);
println!(&quot;Median is {:?}&quot;, med);
}
</code></pre></pre>
<p>The final example calculates the mode using a mutable <a href="https://doc.rust-lang.org/std/collections/struct.HashMap.html"><code>HashMap</code></a> to collect counts of each distinct integer from the set, using a <a href="https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.fold"><code>fold</code></a> and the <a href="https://doc.rust-lang.org/std/collections/hash_map/enum.Entry.html"><code>entry</code></a> API. The most frequent value in the <a href="https://doc.rust-lang.org/std/collections/struct.HashMap.html"><code>HashMap</code></a> surfaces with <a href="https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.max_by_key"><code>max_by_key</code></a>.</p>
<pre><pre class="playground"><code class="language-rust edition2018">use std::collections::HashMap;
fn main() {
let data = [3, 1, 6, 1, 5, 8, 1, 8, 10, 11];
let frequencies = data.iter().fold(HashMap::new(), |mut freqs, value| {
*freqs.entry(value).or_insert(0) += 1;
freqs
});
let mode = frequencies
.into_iter()
.max_by_key(|&amp;(_, count)| count)
.map(|(value, _)| *value);
println!(&quot;Mode of the data is {:?}&quot;, mode);
}
</code></pre></pre>
<h3><a class="header" href="#standard-deviation" id="standard-deviation">Standard deviation</a></h3>
<p><a href="https://doc.rust-lang.org/std"><img src="https://badge-cache.kominick.com/badge/std-1.29.1-blue.svg" alt="std-badge" /></a> <a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></p>
<p>This example calculates the standard deviation and z-score of a set of measurements.</p>
<p>The standard deviation is defined as the square root of the variance (here calculated with f32's [<code>sqrt</code>], where the variance is the <a href="https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.sum"><code>sum</code></a> of the squared difference between each measurement and the [<code>mean</code>], divided by the number of measurements.</p>
<p>The z-score is the number of standard deviations a single measurement spans away from the [<code>mean</code>] of the data set.</p>
<pre><pre class="playground"><code class="language-rust edition2018">fn mean(data: &amp;[i32]) -&gt; Option&lt;f32&gt; {
let sum = data.iter().sum::&lt;i32&gt;() as f32;
let count = data.len();
match count {
positive if positive &gt; 0 =&gt; Some(sum / count as f32),
_ =&gt; None,
}
}
fn std_deviation(data: &amp;[i32]) -&gt; Option&lt;f32&gt; {
match (mean(data), data.len()) {
(Some(data_mean), count) if count &gt; 0 =&gt; {
let variance = data.iter().map(|value| {
let diff = data_mean - (*value as f32);
diff * diff
}).sum::&lt;f32&gt;() / count as f32;
Some(variance.sqrt())
},
_ =&gt; None
}
}
fn main() {
let data = [3, 1, 6, 1, 5, 8, 1, 8, 10, 11];
let data_mean = mean(&amp;data);
println!(&quot;Mean is {:?}&quot;, data_mean);
let data_std_deviation = std_deviation(&amp;data);
println!(&quot;Standard deviation is {:?}&quot;, data_std_deviation);
let zscore = match (data_mean, data_std_deviation) {
(Some(mean), Some(std_deviation)) =&gt; {
let diff = data[4] as f32 - mean;
Some(diff / std_deviation)
},
_ =&gt; None
};
println!(&quot;Z-score of data at index 4 (with value {}) is {:?}&quot;, data[4], zscore);
}
</code></pre></pre>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#miscellaneous" id="miscellaneous">Miscellaneous</a></h1>
<h2><a class="header" href="#big-integers" id="big-integers">Big integers</a></h2>
<p><a href="https://docs.rs/num/"><img src="https://badge-cache.kominick.com/crates/v/num.svg?label=num" alt="num-badge" /></a> <a href="https://crates.io/categories/science"><img src="https://badge-cache.kominick.com/badge/science--x.svg?style=social" alt="cat-science-badge" /></a></p>
<p>Calculation for integers exceeding 128 bits are possible with <a href="https://docs.rs/num/0.2.0/num/struct.BigInt.html"><code>BigInt</code></a>.</p>
<pre><pre class="playground"><code class="language-rust edition2018">use num::bigint::{BigInt, ToBigInt};
fn factorial(x: i32) -&gt; BigInt {
if let Some(mut factorial) = 1.to_bigint() {
for i in 1..=x {
factorial = factorial * i;
}
factorial
}
else {
panic!(&quot;Failed to calculate factorial!&quot;);
}
}
fn main() {
println!(&quot;{}! equals {}&quot;, 100, factorial(100));
}
</code></pre></pre>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#text-processing-1" id="text-processing-1">Text Processing</a></h1>
<table><thead><tr><th>Recipe</th><th>Crates</th><th>Categories</th></tr></thead><tbody>
<tr><td><a href="text/string_parsing.html#collect-unicode-graphemes">Collect Unicode Graphemes</a></td><td><a href="https://docs.rs/unicode-segmentation/"><img src="https://badge-cache.kominick.com/crates/v/unicode-segmentation.svg?label=unicode-segmentation" alt="unicode-segmentation-badge" /></a></td><td><a href="https://crates.io/categories/text-processing"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></td></tr>
<tr><td><a href="text/regex.html#verify-and-extract-login-from-an-email-address">Verify and extract login from an email address</a></td><td><a href="https://docs.rs/regex/"><img src="https://badge-cache.kominick.com/crates/v/regex.svg?label=regex" alt="regex-badge" /></a> <a href="https://docs.rs/lazy_static/"><img src="https://badge-cache.kominick.com/crates/v/lazy_static.svg?label=lazy_static" alt="lazy_static-badge" /></a></td><td><a href="https://crates.io/categories/text-processing"><img src="https://badge-cache.kominick.com/badge/text_processing--x.svg?style=social" alt="cat-text-processing-badge" /></a></td></tr>
<tr><td><a href="text/regex.html#extract-a-list-of-unique-hashtags-from-a-text">Extract a list of unique #Hashtags from a text</a></td><td><a href="https://docs.rs/regex/"><img src="https://badge-cache.kominick.com/crates/v/regex.svg?label=regex" alt="regex-badge" /></a> <a href="https://docs.rs/lazy_static/"><img src="https://badge-cache.kominick.com/crates/v/lazy_static.svg?label=lazy_static" alt="lazy_static-badge" /></a></td><td><a href="https://crates.io/categories/text-processing"><img src="https://badge-cache.kominick.com/badge/text_processing--x.svg?style=social" alt="cat-text-processing-badge" /></a></td></tr>
<tr><td><a href="text/regex.html#extract-phone-numbers-from-text">Extract phone numbers from text</a></td><td><a href="https://docs.rs/regex/"><img src="https://badge-cache.kominick.com/crates/v/regex.svg?label=regex" alt="regex-badge" /></a></td><td><a href="https://crates.io/categories/text-processing"><img src="https://badge-cache.kominick.com/badge/text_processing--x.svg?style=social" alt="cat-text-processing-badge" /></a></td></tr>
<tr><td><a href="text/regex.html#filter-a-log-file-by-matching-multiple-regular-expressions">Filter a log file by matching multiple regular expressions</a></td><td><a href="https://docs.rs/regex/"><img src="https://badge-cache.kominick.com/crates/v/regex.svg?label=regex" alt="regex-badge" /></a></td><td><a href="https://crates.io/categories/text-processing"><img src="https://badge-cache.kominick.com/badge/text_processing--x.svg?style=social" alt="cat-text-processing-badge" /></a></td></tr>
<tr><td><a href="text/regex.html#replace-all-occurrences-of-one-text-pattern-with-another-pattern">Replace all occurrences of one text pattern with another pattern.</a></td><td><a href="https://docs.rs/regex/"><img src="https://badge-cache.kominick.com/crates/v/regex.svg?label=regex" alt="regex-badge" /></a> <a href="https://docs.rs/lazy_static/"><img src="https://badge-cache.kominick.com/crates/v/lazy_static.svg?label=lazy_static" alt="lazy_static-badge" /></a></td><td><a href="https://crates.io/categories/text-processing"><img src="https://badge-cache.kominick.com/badge/text_processing--x.svg?style=social" alt="cat-text-processing-badge" /></a></td></tr>
<tr><td><a href="text/string_parsing.html#implement-the-fromstr-trait-for-a-custom-struct">Implement the <code>FromStr</code> trait for a custom <code>struct</code></a></td><td><a href="https://doc.rust-lang.org/std"><img src="https://badge-cache.kominick.com/badge/std-1.29.1-blue.svg" alt="std-badge" /></a></td><td><a href="https://crates.io/categories/text-processing"><img src="https://badge-cache.kominick.com/badge/text_processing--x.svg?style=social" alt="cat-text-processing-badge" /></a></td></tr>
</tbody></table>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#regular-expressions" id="regular-expressions">Regular Expressions</a></h1>
<h2><a class="header" href="#verify-and-extract-login-from-an-email-address" id="verify-and-extract-login-from-an-email-address">Verify and extract login from an email address</a></h2>
<p><a href="https://docs.rs/regex/"><img src="https://badge-cache.kominick.com/crates/v/regex.svg?label=regex" alt="regex-badge" /></a> <a href="https://docs.rs/lazy_static/"><img src="https://badge-cache.kominick.com/crates/v/lazy_static.svg?label=lazy_static" alt="lazy_static-badge" /></a> <a href="https://crates.io/categories/text-processing"><img src="https://badge-cache.kominick.com/badge/text_processing--x.svg?style=social" alt="cat-text-processing-badge" /></a></p>
<p>Validates that an email address is formatted correctly, and extracts everything
before the @ symbol.</p>
<pre><pre class="playground"><code class="language-rust edition2018">use lazy_static::lazy_static;
use regex::Regex;
fn extract_login(input: &amp;str) -&gt; Option&lt;&amp;str&gt; {
lazy_static! {
static ref RE: Regex = Regex::new(r&quot;(?x)
^(?P&lt;login&gt;[^@\s]+)@
([[:word:]]+\.)*
[[:word:]]+$
&quot;).unwrap();
}
RE.captures(input).and_then(|cap| {
cap.name(&quot;login&quot;).map(|login| login.as_str())
})
}
fn main() {
assert_eq!(extract_login(r&quot;I❤email@example.com&quot;), Some(r&quot;I❤email&quot;));
assert_eq!(
extract_login(r&quot;sdf+sdsfsd.as.sdsd@jhkk.d.rl&quot;),
Some(r&quot;sdf+sdsfsd.as.sdsd&quot;)
);
assert_eq!(extract_login(r&quot;More@Than@One@at.com&quot;), None);
assert_eq!(extract_login(r&quot;Not an email@email&quot;), None);
}
</code></pre></pre>
<h2><a class="header" href="#extract-a-list-of-unique-hashtags-from-a-text" id="extract-a-list-of-unique-hashtags-from-a-text">Extract a list of unique #Hashtags from a text</a></h2>
<p><a href="https://docs.rs/regex/"><img src="https://badge-cache.kominick.com/crates/v/regex.svg?label=regex" alt="regex-badge" /></a> <a href="https://docs.rs/lazy_static/"><img src="https://badge-cache.kominick.com/crates/v/lazy_static.svg?label=lazy_static" alt="lazy_static-badge" /></a> <a href="https://crates.io/categories/text-processing"><img src="https://badge-cache.kominick.com/badge/text_processing--x.svg?style=social" alt="cat-text-processing-badge" /></a></p>
<p>Extracts, sorts, and deduplicates list of hashtags from text.</p>
<p>The hashtag regex given here only catches Latin hashtags that start with a
letter. The complete <a href="https://github.com/twitter/twitter-text/blob/c9fc09782efe59af4ee82855768cfaf36273e170/java/src/com/twitter/Regex.java#L255">twitter hashtag regex</a> is much more complicated.</p>
<pre><pre class="playground"><code class="language-rust edition2018">use lazy_static::lazy_static;
use regex::Regex;
use std::collections::HashSet;
fn extract_hashtags(text: &amp;str) -&gt; HashSet&lt;&amp;str&gt; {
lazy_static! {
static ref HASHTAG_REGEX : Regex = Regex::new(
r&quot;\#[a-zA-Z][0-9a-zA-Z_]*&quot;
).unwrap();
}
HASHTAG_REGEX.find_iter(text).map(|mat| mat.as_str()).collect()
}
fn main() {
let tweet = &quot;Hey #world, I just got my new #dog, say hello to Till. #dog #forever #2 #_ &quot;;
let tags = extract_hashtags(tweet);
assert!(tags.contains(&quot;#dog&quot;) &amp;&amp; tags.contains(&quot;#forever&quot;) &amp;&amp; tags.contains(&quot;#world&quot;));
assert_eq!(tags.len(), 3);
}
</code></pre></pre>
<h2><a class="header" href="#extract-phone-numbers-from-text" id="extract-phone-numbers-from-text">Extract phone numbers from text</a></h2>
<p><a href="https://docs.rs/regex/"><img src="https://badge-cache.kominick.com/crates/v/regex.svg?label=regex" alt="regex-badge" /></a> <a href="https://crates.io/categories/text-processing"><img src="https://badge-cache.kominick.com/badge/text_processing--x.svg?style=social" alt="cat-text-processing-badge" /></a></p>
<p>Processes a string of text using <a href="https://docs.rs/regex/*/regex/struct.Regex.html#method.captures_iter"><code>Regex::captures_iter</code></a> to capture multiple
phone numbers. The example here is for US convention phone numbers.</p>
<pre><pre class="playground"><code class="language-rust edition2018"><span class="boring">use error_chain::error_chain;
</span>
use regex::Regex;
use std::fmt;
<span class="boring">
</span><span class="boring">error_chain!{
</span><span class="boring"> foreign_links {
</span><span class="boring"> Regex(regex::Error);
</span><span class="boring"> Io(std::io::Error);
</span><span class="boring"> }
</span><span class="boring">}
</span>
struct PhoneNumber&lt;'a&gt; {
area: &amp;'a str,
exchange: &amp;'a str,
subscriber: &amp;'a str,
}
impl&lt;'a&gt; fmt::Display for PhoneNumber&lt;'a&gt; {
fn fmt(&amp;self, f: &amp;mut fmt::Formatter) -&gt; fmt::Result {
write!(f, &quot;1 ({}) {}-{}&quot;, self.area, self.exchange, self.subscriber)
}
}
fn main() -&gt; Result&lt;()&gt; {
let phone_text = &quot;
+1 505 881 9292 (v) +1 505 778 2212 (c) +1 505 881 9297 (f)
(202) 991 9534
Alex 5553920011
1 (800) 233-2010
1.299.339.1020&quot;;
let re = Regex::new(
r#&quot;(?x)
(?:\+?1)? # Country Code Optional
[\s\.]?
(([2-9]\d{2})|\(([2-9]\d{2})\)) # Area Code
[\s\.\-]?
([2-9]\d{2}) # Exchange Code
[\s\.\-]?
(\d{4}) # Subscriber Number&quot;#,
)?;
let phone_numbers = re.captures_iter(phone_text).filter_map(|cap| {
let groups = (cap.get(2).or(cap.get(3)), cap.get(4), cap.get(5));
match groups {
(Some(area), Some(ext), Some(sub)) =&gt; Some(PhoneNumber {
area: area.as_str(),
exchange: ext.as_str(),
subscriber: sub.as_str(),
}),
_ =&gt; None,
}
});
assert_eq!(
phone_numbers.map(|m| m.to_string()).collect::&lt;Vec&lt;_&gt;&gt;(),
vec![
&quot;1 (505) 881-9292&quot;,
&quot;1 (505) 778-2212&quot;,
&quot;1 (505) 881-9297&quot;,
&quot;1 (202) 991-9534&quot;,
&quot;1 (555) 392-0011&quot;,
&quot;1 (800) 233-2010&quot;,
&quot;1 (299) 339-1020&quot;,
]
);
Ok(())
}
</code></pre></pre>
<h2><a class="header" href="#filter-a-log-file-by-matching-multiple-regular-expressions" id="filter-a-log-file-by-matching-multiple-regular-expressions">Filter a log file by matching multiple regular expressions</a></h2>
<p><a href="https://docs.rs/regex/"><img src="https://badge-cache.kominick.com/crates/v/regex.svg?label=regex" alt="regex-badge" /></a> <a href="https://crates.io/categories/text-processing"><img src="https://badge-cache.kominick.com/badge/text_processing--x.svg?style=social" alt="cat-text-processing-badge" /></a></p>
<p>Reads a file named <code>application.log</code> and only outputs the lines
containing “version X.X.X”, some IP address followed by port 443
(e.g. “192.168.0.1:443”), or a specific warning.</p>
<p>A <a href="https://docs.rs/regex/*/regex/struct.RegexSetBuilder.html"><code>regex::RegexSetBuilder</code></a> composes a <a href="https://docs.rs/regex/*/regex/struct.RegexSet.html"><code>regex::RegexSet</code></a>.
Since backslashes are very common in regular expressions, using
<a href="https://doc.rust-lang.org/reference/tokens.html#raw-string-literals">raw string literals</a> makes them more readable.</p>
<pre><pre class="playground"><code class="language-rust edition2018 no_run"><span class="boring">use error_chain::error_chain;
</span>
use std::fs::File;
use std::io::{BufReader, BufRead};
use regex::RegexSetBuilder;
<span class="boring">error_chain! {
</span><span class="boring"> foreign_links {
</span><span class="boring"> Io(std::io::Error);
</span><span class="boring"> Regex(regex::Error);
</span><span class="boring"> }
</span><span class="boring">}
</span><span class="boring">
</span>fn main() -&gt; Result&lt;()&gt; {
let log_path = &quot;application.log&quot;;
let buffered = BufReader::new(File::open(log_path)?);
let set = RegexSetBuilder::new(&amp;[
r#&quot;version &quot;\d\.\d\.\d&quot;&quot;#,
r#&quot;\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:443&quot;#,
r#&quot;warning.*timeout expired&quot;#,
]).case_insensitive(true)
.build()?;
buffered
.lines()
.filter_map(|line| line.ok())
.filter(|line| set.is_match(line.as_str()))
.for_each(|x| println!(&quot;{}&quot;, x));
Ok(())
}
</code></pre></pre>
<h2><a class="header" href="#replace-all-occurrences-of-one-text-pattern-with-another-pattern" id="replace-all-occurrences-of-one-text-pattern-with-another-pattern">Replace all occurrences of one text pattern with another pattern.</a></h2>
<p><a href="https://docs.rs/regex/"><img src="https://badge-cache.kominick.com/crates/v/regex.svg?label=regex" alt="regex-badge" /></a> <a href="https://docs.rs/lazy_static/"><img src="https://badge-cache.kominick.com/crates/v/lazy_static.svg?label=lazy_static" alt="lazy_static-badge" /></a> <a href="https://crates.io/categories/text-processing"><img src="https://badge-cache.kominick.com/badge/text_processing--x.svg?style=social" alt="cat-text-processing-badge" /></a></p>
<p>Replaces all occurrences of the standard ISO 8601 <em>YYYY-MM-DD</em> date pattern
with the equivalent American English date with slashes.
For example <code>2013-01-15</code> becomes <code>01/15/2013</code>.</p>
<p>The method <a href="https://docs.rs/regex/*/regex/struct.Regex.html#method.replace_all"><code>Regex::replace_all</code></a> replaces all occurrences of the whole regex.
<code>&amp;str</code> implements the <code>Replacer</code> trait which allows variables like <code>$abcde</code> to
refer to corresponding named capture groups <code>(?P&lt;abcde&gt;REGEX)</code> from the search
regex. See the <a href="https://docs.rs/regex/*/regex/struct.Regex.html#replacement-string-syntax">replacement string syntax</a> for examples and escaping detail.</p>
<pre><pre class="playground"><code class="language-rust edition2018">use lazy_static::lazy_static;
use std::borrow::Cow;
use regex::Regex;
fn reformat_dates(before: &amp;str) -&gt; Cow&lt;str&gt; {
lazy_static! {
static ref ISO8601_DATE_REGEX : Regex = Regex::new(
r&quot;(?P&lt;y&gt;\d{4})-(?P&lt;m&gt;\d{2})-(?P&lt;d&gt;\d{2})&quot;
).unwrap();
}
ISO8601_DATE_REGEX.replace_all(before, &quot;$m/$d/$y&quot;)
}
fn main() {
let before = &quot;2012-03-14, 2013-01-15 and 2014-07-05&quot;;
let after = reformat_dates(before);
assert_eq!(after, &quot;03/14/2012, 01/15/2013 and 07/05/2014&quot;);
}
</code></pre></pre>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#string-parsing" id="string-parsing">String Parsing</a></h1>
<h2><a class="header" href="#collect-unicode-graphemes" id="collect-unicode-graphemes">Collect Unicode Graphemes</a></h2>
<p><a href="https://docs.rs/unicode-segmentation/1.2.1/unicode_segmentation/"><img src="https://badge-cache.kominick.com/crates/v/unicode-segmentation.svg?label=unicode-segmentation" alt="unicode-segmentation-badge" /></a> <a href="https://crates.io/categories/text-processing"><img src="https://badge-cache.kominick.com/badge/text_processing--x.svg?style=social" alt="cat-text-processing-badge" /></a></p>
<p>Collect individual Unicode graphemes from UTF-8 string using the
<a href="https://docs.rs/unicode-segmentation/*/unicode_segmentation/trait.UnicodeSegmentation.html#tymethod.graphemes"><code>UnicodeSegmentation::graphemes</code></a> function from the <a href="https://docs.rs/unicode-segmentation/1.2.1/unicode_segmentation/"><code>unicode-segmentation</code></a> crate.</p>
<pre><pre class="playground"><code class="language-rust edition2018">use unicode_segmentation::UnicodeSegmentation;
fn main() {
let name = &quot;José Guimarães\r\n&quot;;
let graphemes = UnicodeSegmentation::graphemes(name, true)
.collect::&lt;Vec&lt;&amp;str&gt;&gt;();
assert_eq!(graphemes[3], &quot;é&quot;);
}
</code></pre></pre>
<h2><a class="header" href="#implement-the-fromstr-trait-for-a-custom-struct" id="implement-the-fromstr-trait-for-a-custom-struct">Implement the <code>FromStr</code> trait for a custom <code>struct</code></a></h2>
<p><a href="https://doc.rust-lang.org/std"><img src="https://badge-cache.kominick.com/badge/std-1.29.1-blue.svg" alt="std-badge" /></a> <a href="https://crates.io/categories/text-processing"><img src="https://badge-cache.kominick.com/badge/text_processing--x.svg?style=social" alt="cat-text-processing-badge" /></a></p>
<p>Creates a custom struct <code>RGB</code> and implements the <code>FromStr</code> trait to convert a provided color hex code into its RGB color code.</p>
<pre><pre class="playground"><code class="language-rust edition2018">use std::str::FromStr;
#[derive(Debug, PartialEq)]
struct RGB {
r: u8,
g: u8,
b: u8,
}
impl FromStr for RGB {
type Err = std::num::ParseIntError;
// Parses a color hex code of the form '#rRgGbB..' into an
// instance of 'RGB'
fn from_str(hex_code: &amp;str) -&gt; Result&lt;Self, Self::Err&gt; {
// u8::from_str_radix(src: &amp;str, radix: u32) converts a string
// slice in a given base to u8
let r: u8 = u8::from_str_radix(&amp;hex_code[1..3], 16)?;
let g: u8 = u8::from_str_radix(&amp;hex_code[3..5], 16)?;
let b: u8 = u8::from_str_radix(&amp;hex_code[5..7], 16)?;
Ok(RGB { r, g, b })
}
}
fn main() {
let code: &amp;str = &amp;r&quot;#fa7268&quot;;
match RGB::from_str(code) {
Ok(rgb) =&gt; {
println!(
r&quot;The RGB color code is: R: {} G: {} B: {}&quot;,
rgb.r, rgb.g, rgb.b
);
}
Err(_) =&gt; {
println!(&quot;{} is not a valid color hex code!&quot;, code);
}
}
// test whether from_str performs as expected
assert_eq!(
RGB::from_str(&amp;r&quot;#fa7268&quot;).unwrap(),
RGB {
r: 250,
g: 114,
b: 104
}
);
}
</code></pre></pre>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#web-programming-1" id="web-programming-1">Web Programming</a></h1>
<h2><a class="header" href="#scraping-web-pages-1" id="scraping-web-pages-1">Scraping Web Pages</a></h2>
<table><thead><tr><th>Recipe</th><th>Crates</th><th>Categories</th></tr></thead><tbody>
<tr><td><a href="web/scraping.html#extract-all-links-from-a-webpage-html">Extract all links from a webpage HTML</a></td><td><a href="https://docs.rs/reqwest/"><img src="https://badge-cache.kominick.com/crates/v/reqwest.svg?label=reqwest" alt="reqwest-badge" /></a> <a href="https://docs.rs/select/"><img src="https://badge-cache.kominick.com/crates/v/select.svg?label=select" alt="select-badge" /></a></td><td><a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a></td></tr>
<tr><td><a href="web/scraping.html#check-a-webpage-for-broken-links">Check webpage for broken links</a></td><td><a href="https://docs.rs/reqwest/"><img src="https://badge-cache.kominick.com/crates/v/reqwest.svg?label=reqwest" alt="reqwest-badge" /></a> <a href="https://docs.rs/select/"><img src="https://badge-cache.kominick.com/crates/v/select.svg?label=select" alt="select-badge" /></a> <a href="https://docs.rs/url/"><img src="https://badge-cache.kominick.com/crates/v/url.svg?label=url" alt="url-badge" /></a></td><td><a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a></td></tr>
<tr><td><a href="web/scraping.html#extract-all-unique-links-from-a-mediawiki-markup">Extract all unique links from a MediaWiki markup</a></td><td><a href="https://docs.rs/reqwest/"><img src="https://badge-cache.kominick.com/crates/v/reqwest.svg?label=reqwest" alt="reqwest-badge" /></a> <a href="https://docs.rs/regex/"><img src="https://badge-cache.kominick.com/crates/v/regex.svg?label=regex" alt="regex-badge" /></a></td><td><a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a></td></tr>
</tbody></table>
<h2><a class="header" href="#uniform-resource-locations-url-1" id="uniform-resource-locations-url-1">Uniform Resource Locations (URL)</a></h2>
<table><thead><tr><th>Recipe</th><th>Crates</th><th>Categories</th></tr></thead><tbody>
<tr><td><a href="web/url.html#parse-a-url-from-a-string-to-a-url-type">Parse a URL from a string to a <code>Url</code> type</a></td><td><a href="https://docs.rs/url/"><img src="https://badge-cache.kominick.com/crates/v/url.svg?label=url" alt="url-badge" /></a></td><td><a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a></td></tr>
<tr><td><a href="web/url.html#create-a-base-url-by-removing-path-segments">Create a base URL by removing path segments</a></td><td><a href="https://docs.rs/url/"><img src="https://badge-cache.kominick.com/crates/v/url.svg?label=url" alt="url-badge" /></a></td><td><a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a></td></tr>
<tr><td><a href="web/url.html#create-new-urls-from-a-base-url">Create new URLs from a base URL</a></td><td><a href="https://docs.rs/url/"><img src="https://badge-cache.kominick.com/crates/v/url.svg?label=url" alt="url-badge" /></a></td><td><a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a></td></tr>
<tr><td><a href="web/url.html#extract-the-url-origin-scheme--host--port">Extract the URL origin (scheme / host / port)</a></td><td><a href="https://docs.rs/url/"><img src="https://badge-cache.kominick.com/crates/v/url.svg?label=url" alt="url-badge" /></a></td><td><a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a></td></tr>
<tr><td><a href="web/url.html#remove-fragment-identifiers-and-query-pairs-from-a-url">Remove fragment identifiers and query pairs from a URL</a></td><td><a href="https://docs.rs/url/"><img src="https://badge-cache.kominick.com/crates/v/url.svg?label=url" alt="url-badge" /></a></td><td><a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a></td></tr>
</tbody></table>
<h2><a class="header" href="#media-types-mime-1" id="media-types-mime-1">Media Types (MIME)</a></h2>
<table><thead><tr><th>Recipe</th><th>Crates</th><th>Categories</th></tr></thead><tbody>
<tr><td><a href="web/mime.html#get-mime-type-from-string">Get MIME type from string</a></td><td><a href="https://docs.rs/mime/"><img src="https://badge-cache.kominick.com/crates/v/csv.svg?label=mime" alt="mime-badge" /></a></td><td><a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></td></tr>
<tr><td><a href="web/mime.html#get-mime-type-from-filename">Get MIME type from filename</a></td><td><a href="https://docs.rs/mime/"><img src="https://badge-cache.kominick.com/crates/v/csv.svg?label=mime" alt="mime-badge" /></a></td><td><a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></td></tr>
<tr><td><a href="web/mime.html#parse-the-mime-type-of-a-http-response">Parse the MIME type of a HTTP response</a></td><td><a href="https://docs.rs/mime/"><img src="https://badge-cache.kominick.com/crates/v/csv.svg?label=mime" alt="mime-badge" /></a> <a href="https://docs.rs/reqwest/"><img src="https://badge-cache.kominick.com/crates/v/reqwest.svg?label=reqwest" alt="reqwest-badge" /></a></td><td><a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a> <a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></td></tr>
</tbody></table>
<h2><a class="header" href="#clients-1" id="clients-1">Clients</a></h2>
<table><thead><tr><th>Recipe</th><th>Crates</th><th>Categories</th></tr></thead><tbody>
<tr><td><a href="web/clients/requests.html#make-a-http-get-request">Make a HTTP GET request</a></td><td><a href="https://docs.rs/reqwest/"><img src="https://badge-cache.kominick.com/crates/v/reqwest.svg?label=reqwest" alt="reqwest-badge" /></a></td><td><a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a></td></tr>
<tr><td><a href="web/clients/apis.html#query-the-github-api">Query the GitHub API</a></td><td><a href="https://docs.rs/reqwest/"><img src="https://badge-cache.kominick.com/crates/v/reqwest.svg?label=reqwest" alt="reqwest-badge" /></a> <a href="https://docs.rs/serde/"><img src="https://badge-cache.kominick.com/crates/v/serde.svg?label=serde" alt="serde-badge" /></a></td><td><a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a> <a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></td></tr>
<tr><td><a href="web/clients/apis.html#check-if-an-api-resource-exists">Check if an API resource exists</a></td><td><a href="https://docs.rs/reqwest/"><img src="https://badge-cache.kominick.com/crates/v/reqwest.svg?label=reqwest" alt="reqwest-badge" /></a></td><td><a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a></td></tr>
<tr><td><a href="web/clients/apis.html#create-and-delete-gist-with-github-api">Create and delete Gist with GitHub API</a></td><td><a href="https://docs.rs/reqwest/"><img src="https://badge-cache.kominick.com/crates/v/reqwest.svg?label=reqwest" alt="reqwest-badge" /></a> <a href="https://docs.rs/serde/"><img src="https://badge-cache.kominick.com/crates/v/serde.svg?label=serde" alt="serde-badge" /></a></td><td><a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a> <a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></td></tr>
<tr><td><a href="web/clients/apis.html#consume-a-paginated-restful-api">Consume a paginated RESTful API</a></td><td><a href="https://docs.rs/reqwest/"><img src="https://badge-cache.kominick.com/crates/v/reqwest.svg?label=reqwest" alt="reqwest-badge" /></a> <a href="https://docs.rs/serde/"><img src="https://badge-cache.kominick.com/crates/v/serde.svg?label=serde" alt="serde-badge" /></a></td><td><a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a> <a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></td></tr>
<tr><td><a href="web/clients/download.html#download-a-file-to-a-temporary-directory">Download a file to a temporary directory</a></td><td><a href="https://docs.rs/reqwest/"><img src="https://badge-cache.kominick.com/crates/v/reqwest.svg?label=reqwest" alt="reqwest-badge" /></a> <a href="https://docs.rs/tempdir/"><img src="https://badge-cache.kominick.com/crates/v/tempdir.svg?label=tempdir" alt="tempdir-badge" /></a></td><td><a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a> <a href="https://crates.io/categories/filesystem"><img src="https://badge-cache.kominick.com/badge/filesystem--x.svg?style=social" alt="cat-filesystem-badge" /></a></td></tr>
<tr><td><a href="web/clients/download.html#make-a-partial-download-with-http-range-headers">Make a partial download with HTTP range headers</a></td><td><a href="https://docs.rs/reqwest/"><img src="https://badge-cache.kominick.com/crates/v/reqwest.svg?label=reqwest" alt="reqwest-badge" /></a></td><td><a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a></td></tr>
<tr><td><a href="web/clients/download.html#post-a-file-to-paste-rs">POST a file to paste-rs</a></td><td><a href="https://docs.rs/reqwest/"><img src="https://badge-cache.kominick.com/crates/v/reqwest.svg?label=reqwest" alt="reqwest-badge" /></a></td><td><a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a></td></tr>
</tbody></table>
<h2><a class="header" href="#web-authentication-1" id="web-authentication-1">Web Authentication</a></h2>
<table><thead><tr><th>Recipe</th><th>Crates</th><th>Categories</th></tr></thead><tbody>
<tr><td><a href="web/clients/authentication.html#basic-authentication">Basic Authentication</a></td><td><a href="https://docs.rs/reqwest/"><img src="https://badge-cache.kominick.com/crates/v/reqwest.svg?label=reqwest" alt="reqwest-badge" /></a></td><td><a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a></td></tr>
</tbody></table>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#extracting-links" id="extracting-links">Extracting Links</a></h1>
<h2><a class="header" href="#extract-all-links-from-a-webpage-html" id="extract-all-links-from-a-webpage-html">Extract all links from a webpage HTML</a></h2>
<p><a href="https://docs.rs/reqwest/"><img src="https://badge-cache.kominick.com/crates/v/reqwest.svg?label=reqwest" alt="reqwest-badge" /></a> <a href="https://docs.rs/select/"><img src="https://badge-cache.kominick.com/crates/v/select.svg?label=select" alt="select-badge" /></a> <a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a></p>
<p>Use <a href="https://docs.rs/reqwest/*/reqwest/fn.get.html"><code>reqwest::get</code></a> to perform a HTTP GET request and then use
<a href="https://docs.rs/select/*/select/document/struct.Document.html#method.from_read"><code>Document::from_read</code></a> to parse the response into a HTML document.
<a href="https://docs.rs/select/*/select/document/struct.Document.html#method.find"><code>find</code></a> with the criteria of <a href="https://docs.rs/select/*/select/predicate/struct.Name.html"><code>Name</code></a> is &quot;a&quot; retrieves all links.
Call <a href="https://doc.rust-lang.org/core/iter/trait.Iterator.html#method.filter_map"><code>filter_map</code></a> on the <a href="https://docs.rs/select/*/select/selection/struct.Selection.html"><code>Selection</code></a> retrieves URLs
from links that have the &quot;href&quot; <a href="https://docs.rs/select/*/select/node/struct.Node.html#method.attr"><code>attr</code></a> (attribute).</p>
<pre><pre class="playground"><code class="language-rust edition2018 no_run">use error_chain::error_chain;
use select::document::Document;
use select::predicate::Name;
error_chain! {
foreign_links {
ReqError(reqwest::Error);
IoError(std::io::Error);
}
}
#[tokio::main]
async fn main() -&gt; Result&lt;()&gt; {
let res = reqwest::get(&quot;https://www.rust-lang.org/en-US/&quot;)
.await?
.text()
.await?;
Document::from(res.as_str())
.find(Name(&quot;a&quot;))
.filter_map(|n| n.attr(&quot;href&quot;))
.for_each(|x| println!(&quot;{}&quot;, x));
Ok(())
}
</code></pre></pre>
<h2><a class="header" href="#check-a-webpage-for-broken-links" id="check-a-webpage-for-broken-links">Check a webpage for broken links</a></h2>
<p><a href="https://docs.rs/reqwest/"><img src="https://badge-cache.kominick.com/crates/v/reqwest.svg?label=reqwest" alt="reqwest-badge" /></a> <a href="https://docs.rs/select/"><img src="https://badge-cache.kominick.com/crates/v/select.svg?label=select" alt="select-badge" /></a> <a href="https://docs.rs/url/"><img src="https://badge-cache.kominick.com/crates/v/url.svg?label=url" alt="url-badge" /></a> <a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a></p>
<p>Call <code>get_base_url</code> to retrieve the base URL. If the document has a base tag,
get the href <a href="https://docs.rs/select/*/select/node/struct.Node.html#method.attr"><code>attr</code></a> from base tag. <a href="https://docs.rs/url/*/url/enum.Position.html#variant.BeforePath"><code>Position::BeforePath</code></a> of the original
URL acts as a default.</p>
<p>Iterates through links in the document and creates a <a href="https://docs.rs/tokio/*/tokio/fn.spawn.html"><code>tokio::spawn</code></a> task that will
parse an individual link with <a href="https://docs.rs/url/*/url/struct.ParseOptions.html"><code>url::ParseOptions</code></a> and <a href="https://docs.rs/url/*/url/struct.Url.html#method.parse"><code>Url::parse</code></a>).
The task makes a request to the links with <a href="https://docs.rs/reqwest/">reqwest</a> and verifies
<a href="https://docs.rs/reqwest/*/reqwest/struct.StatusCode.html"><code>StatusCode</code></a>. Then the tasks <code>await</code> completion before ending the program.</p>
<pre><pre class="playground"><code class="language-rust edition2018 no_run">use error_chain::error_chain;
use reqwest::StatusCode;
use select::document::Document;
use select::predicate::Name;
use std::collections::HashSet;
use url::{Position, Url};
error_chain! {
foreign_links {
ReqError(reqwest::Error);
IoError(std::io::Error);
UrlParseError(url::ParseError);
JoinError(tokio::task::JoinError);
}
}
async fn get_base_url(url: &amp;Url, doc: &amp;Document) -&gt; Result&lt;Url&gt; {
let base_tag_href = doc.find(Name(&quot;base&quot;)).filter_map(|n| n.attr(&quot;href&quot;)).nth(0);
let base_url =
base_tag_href.map_or_else(|| Url::parse(&amp;url[..Position::BeforePath]), Url::parse)?;
Ok(base_url)
}
async fn check_link(url: &amp;Url) -&gt; Result&lt;bool&gt; {
let res = reqwest::get(url.as_ref()).await?;
Ok(res.status() != StatusCode::NOT_FOUND)
}
#[tokio::main]
async fn main() -&gt; Result&lt;()&gt; {
let url = Url::parse(&quot;https://www.rust-lang.org/en-US/&quot;)?;
let res = reqwest::get(url.as_ref()).await?.text().await?;
let document = Document::from(res.as_str());
let base_url = get_base_url(&amp;url, &amp;document).await?;
let base_parser = Url::options().base_url(Some(&amp;base_url));
let links: HashSet&lt;Url&gt; = document
.find(Name(&quot;a&quot;))
.filter_map(|n| n.attr(&quot;href&quot;))
.filter_map(|link| base_parser.parse(link).ok())
.collect();
let mut tasks = vec![];
for link in links {
tasks.push(tokio::spawn(async move {
if check_link(&amp;link).await.unwrap() {
println!(&quot;{} is OK&quot;, link);
} else {
println!(&quot;{} is Broken&quot;, link);
}
}));
}
for task in tasks {
task.await?
}
Ok(())
}
</code></pre></pre>
<h2><a class="header" href="#extract-all-unique-links-from-a-mediawiki-markup" id="extract-all-unique-links-from-a-mediawiki-markup">Extract all unique links from a MediaWiki markup</a></h2>
<p><a href="https://docs.rs/reqwest/"><img src="https://badge-cache.kominick.com/crates/v/reqwest.svg?label=reqwest" alt="reqwest-badge" /></a> <a href="https://docs.rs/regex/"><img src="https://badge-cache.kominick.com/crates/v/regex.svg?label=regex" alt="regex-badge" /></a> <a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a></p>
<p>Pull the source of a MediaWiki page using <a href="https://docs.rs/reqwest/*/reqwest/fn.get.html"><code>reqwest::get</code></a> and then
look for all entries of internal and external links with
<a href="https://docs.rs/regex/*/regex/struct.Regex.html#method.captures_iter"><code>Regex::captures_iter</code></a>. Using <a href="https://doc.rust-lang.org/std/borrow/enum.Cow.html"><code>Cow</code></a> avoids excessive <a href="https://doc.rust-lang.org/std/string/struct.String.html"><code>String</code></a> allocations.</p>
<p>MediaWiki link syntax is described <a href="https://www.mediawiki.org/wiki/Help:Links">here</a>.</p>
<pre><pre class="playground"><code class="language-rust edition2018 no_run">use lazy_static::lazy_static;
use regex::Regex;
use std::borrow::Cow;
use std::collections::HashSet;
use std::error::Error;
fn extract_links(content: &amp;str) -&gt; HashSet&lt;Cow&lt;str&gt;&gt; {
lazy_static! {
static ref WIKI_REGEX: Regex = Regex::new(
r&quot;(?x)
\[\[(?P&lt;internal&gt;[^\[\]|]*)[^\[\]]*\]\] # internal links
|
(url=|URL\||\[)(?P&lt;external&gt;http.*?)[ \|}] # external links
&quot;
)
.unwrap();
}
let links: HashSet&lt;_&gt; = WIKI_REGEX
.captures_iter(content)
.map(|c| match (c.name(&quot;internal&quot;), c.name(&quot;external&quot;)) {
(Some(val), None) =&gt; Cow::from(val.as_str().to_lowercase()),
(None, Some(val)) =&gt; Cow::from(val.as_str()),
_ =&gt; unreachable!(),
})
.collect();
links
}
#[tokio::main]
async fn main() -&gt; Result&lt;(), Box&lt;dyn Error&gt;&gt; {
let content = reqwest::get(
&quot;https://en.wikipedia.org/w/index.php?title=Rust_(programming_language)&amp;action=raw&quot;,
)
.await?
.text()
.await?;
println!(&quot;{:#?}&quot;, extract_links(content.as_str()));
Ok(())
}
</code></pre></pre>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#uniform-resource-location" id="uniform-resource-location">Uniform Resource Location</a></h1>
<h2><a class="header" href="#parse-a-url-from-a-string-to-a-url-type" id="parse-a-url-from-a-string-to-a-url-type">Parse a URL from a string to a <code>Url</code> type</a></h2>
<p><a href="https://docs.rs/url/"><img src="https://badge-cache.kominick.com/crates/v/url.svg?label=url" alt="url-badge" /></a> <a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a></p>
<p>The <a href="https://docs.rs/url/*/url/struct.Url.html#method.parse"><code>parse</code></a> method from the <code>url</code> crate validates and parses a <code>&amp;str</code> into a
<a href="https://docs.rs/url/*/url/struct.Url.html"><code>Url</code></a> struct. The input string may be malformed so this method returns
<code>Result&lt;Url, ParseError&gt;</code>.</p>
<p>Once the URL has been parsed, it can be used with all of the methods in the
<code>Url</code> type.</p>
<pre><pre class="playground"><code class="language-rust edition2018">
use url::{Url, ParseError};
fn main() -&gt; Result&lt;(), ParseError&gt; {
let s = &quot;https://github.com/rust-lang/rust/issues?labels=E-easy&amp;state=open&quot;;
let parsed = Url::parse(s)?;
println!(&quot;The path part of the URL is: {}&quot;, parsed.path());
Ok(())
}
</code></pre></pre>
<h2><a class="header" href="#create-a-base-url-by-removing-path-segments" id="create-a-base-url-by-removing-path-segments">Create a base URL by removing path segments</a></h2>
<p><a href="https://docs.rs/url/"><img src="https://badge-cache.kominick.com/crates/v/url.svg?label=url" alt="url-badge" /></a> <a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a></p>
<p>A base URL includes a protocol and a domain. Base URLs have no folders,
files or query strings. Each of those items are stripped out of the given
URL. <a href="https://docs.rs/url/*/url/struct.PathSegmentsMut.html#method.clear"><code>PathSegmentsMut::clear</code></a> removes paths and <a href="https://docs.rs/url/*/url/struct.Url.html#method.set_query"><code>Url::set_query</code></a> removes
query string.</p>
<pre><pre class="playground"><code class="language-rust edition2018"><span class="boring">use error_chain::error_chain;
</span>
use url::Url;
<span class="boring">
</span><span class="boring">error_chain! {
</span><span class="boring"> foreign_links {
</span><span class="boring"> UrlParse(url::ParseError);
</span><span class="boring"> }
</span><span class="boring"> errors {
</span><span class="boring"> CannotBeABase
</span><span class="boring"> }
</span><span class="boring">}
</span>
fn main() -&gt; Result&lt;()&gt; {
let full = &quot;https://github.com/rust-lang/cargo?asdf&quot;;
let url = Url::parse(full)?;
let base = base_url(url)?;
assert_eq!(base.as_str(), &quot;https://github.com/&quot;);
println!(&quot;The base of the URL is: {}&quot;, base);
Ok(())
}
fn base_url(mut url: Url) -&gt; Result&lt;Url&gt; {
match url.path_segments_mut() {
Ok(mut path) =&gt; {
path.clear();
}
Err(_) =&gt; {
return Err(Error::from_kind(ErrorKind::CannotBeABase));
}
}
url.set_query(None);
Ok(url)
}
</code></pre></pre>
<h2><a class="header" href="#create-new-urls-from-a-base-url" id="create-new-urls-from-a-base-url">Create new URLs from a base URL</a></h2>
<p><a href="https://docs.rs/url/"><img src="https://badge-cache.kominick.com/crates/v/url.svg?label=url" alt="url-badge" /></a> <a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a></p>
<p>The <a href="https://docs.rs/url/*/url/struct.Url.html#method.join"><code>join</code></a> method creates a new URL from a base and relative path.</p>
<pre><pre class="playground"><code class="language-rust edition2018">
use url::{Url, ParseError};
fn main() -&gt; Result&lt;(), ParseError&gt; {
let path = &quot;/rust-lang/cargo&quot;;
let gh = build_github_url(path)?;
assert_eq!(gh.as_str(), &quot;https://github.com/rust-lang/cargo&quot;);
println!(&quot;The joined URL is: {}&quot;, gh);
Ok(())
}
fn build_github_url(path: &amp;str) -&gt; Result&lt;Url, ParseError&gt; {
const GITHUB: &amp;'static str = &quot;https://github.com&quot;;
let base = Url::parse(GITHUB).expect(&quot;hardcoded URL is known to be valid&quot;);
let joined = base.join(path)?;
Ok(joined)
}
</code></pre></pre>
<h2><a class="header" href="#extract-the-url-origin-scheme--host--port" id="extract-the-url-origin-scheme--host--port">Extract the URL origin (scheme / host / port)</a></h2>
<p><a href="https://docs.rs/url/"><img src="https://badge-cache.kominick.com/crates/v/url.svg?label=url" alt="url-badge" /></a> <a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a></p>
<p>The <a href="https://docs.rs/url/*/url/struct.Url.html"><code>Url</code></a> struct exposes various methods to extract information about the URL
it represents.</p>
<pre><pre class="playground"><code class="language-rust edition2018">
use url::{Url, Host, ParseError};
fn main() -&gt; Result&lt;(), ParseError&gt; {
let s = &quot;ftp://rust-lang.org/examples&quot;;
let url = Url::parse(s)?;
assert_eq!(url.scheme(), &quot;ftp&quot;);
assert_eq!(url.host(), Some(Host::Domain(&quot;rust-lang.org&quot;)));
assert_eq!(url.port_or_known_default(), Some(21));
println!(&quot;The origin is as expected!&quot;);
Ok(())
}
</code></pre></pre>
<p><a href="https://docs.rs/url/*/url/struct.Url.html#method.origin"><code>origin</code></a> produces the same result.</p>
<pre><pre class="playground"><code class="language-rust edition2018"><span class="boring">use error_chain::error_chain;
</span>
use url::{Url, Origin, Host};
<span class="boring">error_chain! {
</span><span class="boring"> foreign_links {
</span><span class="boring"> UrlParse(url::ParseError);
</span><span class="boring"> }
</span><span class="boring">}
</span><span class="boring">
</span>fn main() -&gt; Result&lt;()&gt; {
let s = &quot;ftp://rust-lang.org/examples&quot;;
let url = Url::parse(s)?;
let expected_scheme = &quot;ftp&quot;.to_owned();
let expected_host = Host::Domain(&quot;rust-lang.org&quot;.to_owned());
let expected_port = 21;
let expected = Origin::Tuple(expected_scheme, expected_host, expected_port);
let origin = url.origin();
assert_eq!(origin, expected);
println!(&quot;The origin is as expected!&quot;);
Ok(())
}
</code></pre></pre>
<h2><a class="header" href="#remove-fragment-identifiers-and-query-pairs-from-a-url" id="remove-fragment-identifiers-and-query-pairs-from-a-url">Remove fragment identifiers and query pairs from a URL</a></h2>
<p><a href="https://docs.rs/url/"><img src="https://badge-cache.kominick.com/crates/v/url.svg?label=url" alt="url-badge" /></a> <a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a></p>
<p>Parses <a href="https://docs.rs/url/*/url/struct.Url.html"><code>Url</code></a> and slices it with <a href="https://docs.rs/url/*/url/enum.Position.html"><code>url::Position</code></a> to strip unneeded URL parts.</p>
<pre><pre class="playground"><code class="language-rust edition2018">
use url::{Url, Position, ParseError};
fn main() -&gt; Result&lt;(), ParseError&gt; {
let parsed = Url::parse(&quot;https://github.com/rust-lang/rust/issues?labels=E-easy&amp;state=open&quot;)?;
let cleaned: &amp;str = &amp;parsed[..Position::AfterPath];
println!(&quot;cleaned: {}&quot;, cleaned);
Ok(())
}
</code></pre></pre>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#media-types" id="media-types">Media Types</a></h1>
<h2><a class="header" href="#get-mime-type-from-string" id="get-mime-type-from-string">Get MIME type from string</a></h2>
<p><a href="https://docs.rs/mime/"><img src="https://badge-cache.kominick.com/crates/v/csv.svg?label=mime" alt="mime-badge" /></a> <a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></p>
<p>The following example shows how to parse a <a href="https://docs.rs/mime/*/mime/struct.Mime.html"><code>MIME</code></a> type from a string using the
<a href="https://docs.rs/mime/">mime</a> crate. <a href="https://docs.rs/mime/*/mime/struct.FromStrError.html"><code>FromStrError</code></a> produces a default <a href="https://docs.rs/mime/*/mime/struct.Mime.html"><code>MIME</code></a> type in an
<code>unwrap_or</code> clause.</p>
<pre><pre class="playground"><code class="language-rust edition2018">use mime::{Mime, APPLICATION_OCTET_STREAM};
fn main() {
let invalid_mime_type = &quot;i n v a l i d&quot;;
let default_mime = invalid_mime_type
.parse::&lt;Mime&gt;()
.unwrap_or(APPLICATION_OCTET_STREAM);
println!(
&quot;MIME for {:?} used default value {:?}&quot;,
invalid_mime_type, default_mime
);
let valid_mime_type = &quot;TEXT/PLAIN&quot;;
let parsed_mime = valid_mime_type
.parse::&lt;Mime&gt;()
.unwrap_or(APPLICATION_OCTET_STREAM);
println!(
&quot;MIME for {:?} was parsed as {:?}&quot;,
valid_mime_type, parsed_mime
);
}
</code></pre></pre>
<h2><a class="header" href="#get-mime-type-from-filename" id="get-mime-type-from-filename">Get MIME type from filename</a></h2>
<p><a href="https://docs.rs/mime/"><img src="https://badge-cache.kominick.com/crates/v/csv.svg?label=mime" alt="mime-badge" /></a> <a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></p>
<p>The following example shows how to return the correct MIME type from a given
filename using the <a href="https://docs.rs/mime/">mime</a> crate. The program will check for file extensions
and match against a known list. The return value is <a href="https://docs.rs/mime/*/mime/struct.Mime.html"><code>mime:Mime</code></a>.</p>
<pre><pre class="playground"><code class="language-rust edition2018">use mime::Mime;
fn find_mimetype (filename : &amp;String) -&gt; Mime{
let parts : Vec&lt;&amp;str&gt; = filename.split('.').collect();
let res = match parts.last() {
Some(v) =&gt;
match *v {
&quot;png&quot; =&gt; mime::IMAGE_PNG,
&quot;jpg&quot; =&gt; mime::IMAGE_JPEG,
&quot;json&quot; =&gt; mime::APPLICATION_JSON,
&amp;_ =&gt; mime::TEXT_PLAIN,
},
None =&gt; mime::TEXT_PLAIN,
};
return res;
}
fn main() {
let filenames = vec!(&quot;foobar.jpg&quot;, &quot;foo.bar&quot;, &quot;foobar.png&quot;);
for file in filenames {
let mime = find_mimetype(&amp;file.to_owned());
println!(&quot;MIME for {}: {}&quot;, file, mime);
}
}
</code></pre></pre>
<h2><a class="header" href="#parse-the-mime-type-of-a-http-response" id="parse-the-mime-type-of-a-http-response">Parse the MIME type of a HTTP response</a></h2>
<p><a href="https://docs.rs/reqwest/"><img src="https://badge-cache.kominick.com/crates/v/reqwest.svg?label=reqwest" alt="reqwest-badge" /></a> <a href="https://docs.rs/mime/"><img src="https://badge-cache.kominick.com/crates/v/csv.svg?label=mime" alt="mime-badge" /></a> <a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a> <a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></p>
<p>When receiving a HTTP reponse from <code>reqwest</code> the <a href="https://developer.mozilla.org/docs/Web/HTTP/Basics_of_HTTP/MIME_types">MIME type</a> or media type may be
found in the <a href="https://developer.mozilla.org/docs/Web/HTTP/Headers/Content-Type">Content-Type</a> header. <a href="https://docs.rs/reqwest/*/reqwest/header/struct.HeaderMap.html#method.get"><code>reqwest::header::HeaderMap::get</code></a> retrieves
the header as a <a href="https://docs.rs/reqwest/*/reqwest/header/struct.HeaderValue.html"><code>reqwest::header::HeaderValue</code></a>, which can be converted to a
string. The <code>mime</code> crate can then parse that, yielding a <a href="https://docs.rs/mime/*/mime/struct.Mime.html"><code>mime::Mime</code></a> value.</p>
<p>The <a href="https://docs.rs/mime/*/mime/struct.Mime.html"><code>mime</code></a> crate also defines some commonly used MIME types.</p>
<p>Note that the <a href="https://docs.rs/reqwest/*/reqwest/header/index.html"><code>reqwest::header</code></a> module is exported from the <a href="https://docs.rs/http/*/http/"><code>http</code></a> crate.</p>
<pre><pre class="playground"><code class="language-rust edition2018 no_run">use error_chain::error_chain;
use mime::Mime;
use std::str::FromStr;
use reqwest::header::CONTENT_TYPE;
error_chain! {
foreign_links {
Reqwest(reqwest::Error);
Header(reqwest::header::ToStrError);
Mime(mime::FromStrError);
}
}
#[tokio::main]
async fn main() -&gt; Result&lt;()&gt; {
let response = reqwest::get(&quot;https://www.rust-lang.org/logos/rust-logo-32x32.png&quot;).await?;
let headers = response.headers();
match headers.get(CONTENT_TYPE) {
None =&gt; {
println!(&quot;The response does not contain a Content-Type header.&quot;);
}
Some(content_type) =&gt; {
let content_type = Mime::from_str(content_type.to_str()?)?;
let media_type = match (content_type.type_(), content_type.subtype()) {
(mime::TEXT, mime::HTML) =&gt; &quot;a HTML document&quot;,
(mime::TEXT, _) =&gt; &quot;a text document&quot;,
(mime::IMAGE, mime::PNG) =&gt; &quot;a PNG image&quot;,
(mime::IMAGE, _) =&gt; &quot;an image&quot;,
_ =&gt; &quot;neither text nor image&quot;,
};
println!(&quot;The reponse contains {}.&quot;, media_type);
}
};
Ok(())
}
</code></pre></pre>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h2><a class="header" href="#clients-2" id="clients-2">Clients</a></h2>
<table><thead><tr><th>Recipe</th><th>Crates</th><th>Categories</th></tr></thead><tbody>
<tr><td><a href="web/clients/requests.html#make-a-http-get-request">Make a HTTP GET request</a></td><td><a href="https://docs.rs/reqwest/"><img src="https://badge-cache.kominick.com/crates/v/reqwest.svg?label=reqwest" alt="reqwest-badge" /></a></td><td><a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a></td></tr>
<tr><td><a href="web/clients/apis.html#query-the-github-api">Query the GitHub API</a></td><td><a href="https://docs.rs/reqwest/"><img src="https://badge-cache.kominick.com/crates/v/reqwest.svg?label=reqwest" alt="reqwest-badge" /></a> <a href="https://docs.rs/serde/"><img src="https://badge-cache.kominick.com/crates/v/serde.svg?label=serde" alt="serde-badge" /></a></td><td><a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a> <a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></td></tr>
<tr><td><a href="web/clients/apis.html#check-if-an-api-resource-exists">Check if an API resource exists</a></td><td><a href="https://docs.rs/reqwest/"><img src="https://badge-cache.kominick.com/crates/v/reqwest.svg?label=reqwest" alt="reqwest-badge" /></a></td><td><a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a></td></tr>
<tr><td><a href="web/clients/apis.html#create-and-delete-gist-with-github-api">Create and delete Gist with GitHub API</a></td><td><a href="https://docs.rs/reqwest/"><img src="https://badge-cache.kominick.com/crates/v/reqwest.svg?label=reqwest" alt="reqwest-badge" /></a> <a href="https://docs.rs/serde/"><img src="https://badge-cache.kominick.com/crates/v/serde.svg?label=serde" alt="serde-badge" /></a></td><td><a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a> <a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></td></tr>
<tr><td><a href="web/clients/apis.html#consume-a-paginated-restful-api">Consume a paginated RESTful API</a></td><td><a href="https://docs.rs/reqwest/"><img src="https://badge-cache.kominick.com/crates/v/reqwest.svg?label=reqwest" alt="reqwest-badge" /></a> <a href="https://docs.rs/serde/"><img src="https://badge-cache.kominick.com/crates/v/serde.svg?label=serde" alt="serde-badge" /></a></td><td><a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a> <a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></td></tr>
<tr><td><a href="web/clients/download.html#download-a-file-to-a-temporary-directory">Download a file to a temporary directory</a></td><td><a href="https://docs.rs/reqwest/"><img src="https://badge-cache.kominick.com/crates/v/reqwest.svg?label=reqwest" alt="reqwest-badge" /></a> <a href="https://docs.rs/tempdir/"><img src="https://badge-cache.kominick.com/crates/v/tempdir.svg?label=tempdir" alt="tempdir-badge" /></a></td><td><a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a> <a href="https://crates.io/categories/filesystem"><img src="https://badge-cache.kominick.com/badge/filesystem--x.svg?style=social" alt="cat-filesystem-badge" /></a></td></tr>
<tr><td><a href="web/clients/download.html#make-a-partial-download-with-http-range-headers">Make a partial download with HTTP range headers</a></td><td><a href="https://docs.rs/reqwest/"><img src="https://badge-cache.kominick.com/crates/v/reqwest.svg?label=reqwest" alt="reqwest-badge" /></a></td><td><a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a></td></tr>
<tr><td><a href="web/clients/download.html#post-a-file-to-paste-rs">POST a file to paste-rs</a></td><td><a href="https://docs.rs/reqwest/"><img src="https://badge-cache.kominick.com/crates/v/reqwest.svg?label=reqwest" alt="reqwest-badge" /></a></td><td><a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a></td></tr>
</tbody></table>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#making-requests" id="making-requests">Making Requests</a></h1>
<h2><a class="header" href="#make-a-http-get-request" id="make-a-http-get-request">Make a HTTP GET request</a></h2>
<p><a href="https://docs.rs/reqwest/"><img src="https://badge-cache.kominick.com/crates/v/reqwest.svg?label=reqwest" alt="reqwest-badge" /></a> <a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a></p>
<p>Parses the supplied URL and makes a synchronous HTTP GET request
with <a href="https://docs.rs/reqwest/*/reqwest/blocking/fn.get.html"><code>reqwest::blocking::get</code></a>. Prints obtained <a href="https://docs.rs/reqwest/*/reqwest/blocking/struct.Response.html"><code>reqwest::blocking::Response</code></a>
status and headers. Reads HTTP response body into an allocated <a href="https://doc.rust-lang.org/std/string/struct.String.html"><code>String</code></a>
using <a href="https://doc.rust-lang.org/std/io/trait.Read.html#method.read_to_string"><code>read_to_string</code></a>.</p>
<pre><pre class="playground"><code class="language-rust edition2018 no_run">use error_chain::error_chain;
use std::io::Read;
error_chain! {
foreign_links {
Io(std::io::Error);
HttpRequest(reqwest::Error);
}
}
fn main() -&gt; Result&lt;()&gt; {
let mut res = reqwest::blocking::get(&quot;http://httpbin.org/get&quot;)?;
let mut body = String::new();
res.read_to_string(&amp;mut body)?;
println!(&quot;Status: {}&quot;, res.status());
println!(&quot;Headers:\n{:#?}&quot;, res.headers());
println!(&quot;Body:\n{}&quot;, body);
Ok(())
}
</code></pre></pre>
<h2><a class="header" href="#async" id="async">Async</a></h2>
<p>A similar approach can be used by including the <a href="https://docs.rs/crate/tokio/0.2.11"><code>tokio</code></a> executor
to make the main function asynchronous, retrieving the same information.</p>
<p>In this example, <a href="https://tokio.rs/tokio/tutorial/hello-tokio#the-code"><code>tokio::main</code></a> handles all the heavy executor setup
and allows sequential code implemented without blocking until <code>.await</code>.</p>
<p>Uses the asynchronous versions of <a href="https://docs.rs/reqwest/">reqwest</a>, both <a href="https://docs.rs/reqwest/*/reqwest/fn.get.html"><code>reqwest::get</code></a> and
<a href="https://docs.rs/reqwest/*/reqwest/struct.Response.html"><code>reqwest::Response</code></a>.</p>
<pre><pre class="playground"><code class="language-rust no_run">use error_chain::error_chain;
error_chain! {
foreign_links {
Io(std::io::Error);
HttpRequest(reqwest::Error);
}
}
#[tokio::main]
async fn main() -&gt; Result&lt;()&gt; {
let res = reqwest::get(&quot;http://httpbin.org/get&quot;).await?;
println!(&quot;Status: {}&quot;, res.status());
println!(&quot;Headers:\n{:#?}&quot;, res.headers());
let body = res.text().await?;
println!(&quot;Body:\n{}&quot;, body);
Ok(())
}
</code></pre></pre>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#calling-a-web-api" id="calling-a-web-api">Calling a Web API</a></h1>
<h2><a class="header" href="#query-the-github-api" id="query-the-github-api">Query the GitHub API</a></h2>
<p><a href="https://docs.rs/reqwest/"><img src="https://badge-cache.kominick.com/crates/v/reqwest.svg?label=reqwest" alt="reqwest-badge" /></a> <a href="https://docs.rs/serde/"><img src="https://badge-cache.kominick.com/crates/v/serde.svg?label=serde" alt="serde-badge" /></a> <a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a> <a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></p>
<p>Queries GitHub <a href="https://developer.github.com/v3/activity/starring/#list-stargazers">stargazers API v3</a>
with <a href="https://docs.rs/reqwest/*/reqwest/fn.get.html"><code>reqwest::get</code></a> to get list of all users who have marked a GitHub project with a star.
<a href="https://docs.rs/reqwest/*/reqwest/struct.Response.html"><code>reqwest::Response</code></a> is deserialized with <a href="https://docs.rs/reqwest/*/reqwest/struct.Response.html#method.json"><code>Response::json</code></a> into <code>User</code> objects implementing <a href="https://docs.rs/serde/*/serde/trait.Deserialize.html"><code>serde::Deserialize</code></a>.</p>
<p>[tokio::main] is used to set up the async executor and the process waits for [<code>reqwet::get</code>] to complete before
processing the response into User instances.</p>
<pre><pre class="playground"><code class="language-rust edition2018 no_run">use serde::Deserialize;
use reqwest::Error;
#[derive(Deserialize, Debug)]
struct User {
login: String,
id: u32,
}
#[tokio::main]
async fn main() -&gt; Result&lt;(), Error&gt; {
let request_url = format!(&quot;https://api.github.com/repos/{owner}/{repo}/stargazers&quot;,
owner = &quot;rust-lang-nursery&quot;,
repo = &quot;rust-cookbook&quot;);
println!(&quot;{}&quot;, request_url);
let response = reqwest::get(&amp;request_url).await?;
let users: Vec&lt;User&gt; = response.json().await?;
println!(&quot;{:?}&quot;, users);
Ok(())
}
</code></pre></pre>
<h2><a class="header" href="#check-if-an-api-resource-exists" id="check-if-an-api-resource-exists">Check if an API resource exists</a></h2>
<p><a href="https://docs.rs/reqwest/"><img src="https://badge-cache.kominick.com/crates/v/reqwest.svg?label=reqwest" alt="reqwest-badge" /></a> <a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a></p>
<p>Query the GitHub Users Endpoint using a HEAD
request (<a href="https://docs.rs/reqwest/*/reqwest/struct.Client.html#method.head"><code>Client::head</code></a>) and then inspect the response code to determine
success. This is a quick way to query a rest resource without needing to receive
a body. <a href="https://docs.rs/reqwest/*/reqwest/struct.Client.html"><code>reqwest::Client</code></a> configured with <a href="https://docs.rs/reqwest/*/reqwest/struct.ClientBuilder.html#method.timeout"><code>ClientBuilder::timeout</code></a> ensures
a request will not last longer than a timeout.</p>
<p>Due to both <a href="https://docs.rs/reqwest/*/reqwest/struct.ClientBuilder.html#method.build"><code>ClientBuilder::build</code></a> and [<code>ReqwestBuilder::send</code>] returning <a href="https://docs.rs/reqwest/*/reqwest/struct.Error.html"><code>reqwest::Error</code></a>
types, the shortcut <a href="https://docs.rs/reqwest/*/reqwest/type.Result.html"><code>reqwest::Result</code></a> is used for the main function return type. </p>
<pre><pre class="playground"><code class="language-rust edition2018 no_run">use reqwest::Result;
use std::time::Duration;
use reqwest::ClientBuilder;
#[tokio::main]
async fn main() -&gt; Result&lt;()&gt; {
let user = &quot;ferris-the-crab&quot;;
let request_url = format!(&quot;https://api.github.com/users/{}&quot;, user);
println!(&quot;{}&quot;, request_url);
let timeout = Duration::new(5, 0);
let client = ClientBuilder::new().timeout(timeout).build()?;
let response = client.head(&amp;request_url).send().await?;
if response.status().is_success() {
println!(&quot;{} is a user!&quot;, user);
} else {
println!(&quot;{} is not a user!&quot;, user);
}
Ok(())
}
</code></pre></pre>
<h2><a class="header" href="#create-and-delete-gist-with-github-api" id="create-and-delete-gist-with-github-api">Create and delete Gist with GitHub API</a></h2>
<p><a href="https://docs.rs/reqwest/"><img src="https://badge-cache.kominick.com/crates/v/reqwest.svg?label=reqwest" alt="reqwest-badge" /></a> <a href="https://docs.rs/serde/"><img src="https://badge-cache.kominick.com/crates/v/serde.svg?label=serde" alt="serde-badge" /></a> <a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a> <a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></p>
<p>Creates a gist with POST request to GitHub <a href="https://developer.github.com/v3/gists/">gists API v3</a>
using <a href="https://docs.rs/reqwest/*/reqwest/struct.Client.html#method.post"><code>Client::post</code></a> and removes it with DELETE request using <a href="https://docs.rs/reqwest/*/reqwest/struct.Client.html#method.delete"><code>Client::delete</code></a>.</p>
<p>The <a href="https://docs.rs/reqwest/*/reqwest/struct.Client.html"><code>reqwest::Client</code></a> is responsible for details of both requests including
URL, body and authentication. The POST body from <a href="https://docs.rs/serde_json/*/serde_json/macro.json.html"><code>serde_json::json!</code></a> macro
provides arbitrary JSON body. Call to <a href="https://docs.rs/reqwest/*/reqwest/struct.RequestBuilder.html#method.json"><code>RequestBuilder::json</code></a> sets the request
body. <a href="https://docs.rs/reqwest/*/reqwest/struct.RequestBuilder.html#method.basic_auth"><code>RequestBuilder::basic_auth</code></a> handles authentication. The call to
<a href="https://docs.rs/reqwest/*/reqwest/struct.RequestBuilder.html#method.send"><code>RequestBuilder::send</code></a> synchronously executes the requests.</p>
<pre><pre class="playground"><code class="language-rust edition2018 no_run">use error_chain::error_chain;
use serde::Deserialize;
use serde_json::json;
use std::env;
use reqwest::Client;
error_chain! {
foreign_links {
EnvVar(env::VarError);
HttpRequest(reqwest::Error);
}
}
#[derive(Deserialize, Debug)]
struct Gist {
id: String,
html_url: String,
}
#[tokio::main]
async fn main() -&gt; Result&lt;()&gt; {
let gh_user = env::var(&quot;GH_USER&quot;)?;
let gh_pass = env::var(&quot;GH_PASS&quot;)?;
let gist_body = json!({
&quot;description&quot;: &quot;the description for this gist&quot;,
&quot;public&quot;: true,
&quot;files&quot;: {
&quot;main.rs&quot;: {
&quot;content&quot;: r#&quot;fn main() { println!(&quot;hello world!&quot;);}&quot;#
}
}});
let request_url = &quot;https://api.github.com/gists&quot;;
let response = Client::new()
.post(request_url)
.basic_auth(gh_user.clone(), Some(gh_pass.clone()))
.json(&amp;gist_body)
.send().await?;
let gist: Gist = response.json().await?;
println!(&quot;Created {:?}&quot;, gist);
let request_url = format!(&quot;{}/{}&quot;,request_url, gist.id);
let response = Client::new()
.delete(&amp;request_url)
.basic_auth(gh_user, Some(gh_pass))
.send().await?;
println!(&quot;Gist {} deleted! Status code: {}&quot;,gist.id, response.status());
Ok(())
}
</code></pre></pre>
<p>The example uses <a href="https://tools.ietf.org/html/rfc2617">HTTP Basic Auth</a> in order to authorize access to <a href="https://developer.github.com/v3/auth/">GitHub API</a>.
Typical use case would employ one of the much more complex <a href="https://oauth.net/getting-started/">OAuth</a> authorization
flows.</p>
<h2><a class="header" href="#consume-a-paginated-restful-api" id="consume-a-paginated-restful-api">Consume a paginated RESTful API</a></h2>
<p><a href="https://docs.rs/reqwest/"><img src="https://badge-cache.kominick.com/crates/v/reqwest.svg?label=reqwest" alt="reqwest-badge" /></a> <a href="https://docs.rs/serde/"><img src="https://badge-cache.kominick.com/crates/v/serde.svg?label=serde" alt="serde-badge" /></a> <a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a> <a href="https://crates.io/categories/encoding"><img src="https://badge-cache.kominick.com/badge/encoding--x.svg?style=social" alt="cat-encoding-badge" /></a></p>
<p>Wraps a paginated web API in a convenient Rust iterator. The iterator lazily
fetches the next page of results from the remote server as it arrives at the end
of each page.</p>
<pre><pre class="playground"><code class="language-rust edition2018 no_run">use reqwest::Result;
use serde::Deserialize;
#[derive(Deserialize)]
struct ApiResponse {
dependencies: Vec&lt;Dependency&gt;,
meta: Meta,
}
#[derive(Deserialize)]
struct Dependency {
crate_id: String,
}
#[derive(Deserialize)]
struct Meta {
total: u32,
}
struct ReverseDependencies {
crate_id: String,
dependencies: &lt;Vec&lt;Dependency&gt; as IntoIterator&gt;::IntoIter,
client: reqwest::blocking::Client,
page: u32,
per_page: u32,
total: u32,
}
impl ReverseDependencies {
fn of(crate_id: &amp;str) -&gt; Result&lt;Self&gt; {
Ok(ReverseDependencies {
crate_id: crate_id.to_owned(),
dependencies: vec![].into_iter(),
client: reqwest::blocking::Client::new(),
page: 0,
per_page: 100,
total: 0,
})
}
fn try_next(&amp;mut self) -&gt; Result&lt;Option&lt;Dependency&gt;&gt; {
if let Some(dep) = self.dependencies.next() {
return Ok(Some(dep));
}
if self.page &gt; 0 &amp;&amp; self.page * self.per_page &gt;= self.total {
return Ok(None);
}
self.page += 1;
let url = format!(&quot;https://crates.io/api/v1/crates/{}/reverse_dependencies?page={}&amp;per_page={}&quot;,
self.crate_id,
self.page,
self.per_page);
let response = self.client.get(&amp;url).send()?.json::&lt;ApiResponse&gt;()?;
self.dependencies = response.dependencies.into_iter();
self.total = response.meta.total;
Ok(self.dependencies.next())
}
}
impl Iterator for ReverseDependencies {
type Item = Result&lt;Dependency&gt;;
fn next(&amp;mut self) -&gt; Option&lt;Self::Item&gt; {
match self.try_next() {
Ok(Some(dep)) =&gt; Some(Ok(dep)),
Ok(None) =&gt; None,
Err(err) =&gt; Some(Err(err)),
}
}
}
fn main() -&gt; Result&lt;()&gt; {
for dep in ReverseDependencies::of(&quot;serde&quot;)? {
println!(&quot;reverse dependency: {}&quot;, dep?.crate_id);
}
Ok(())
}
</code></pre></pre>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#downloads" id="downloads">Downloads</a></h1>
<h2><a class="header" href="#download-a-file-to-a-temporary-directory" id="download-a-file-to-a-temporary-directory">Download a file to a temporary directory</a></h2>
<p><a href="https://docs.rs/reqwest/"><img src="https://badge-cache.kominick.com/crates/v/reqwest.svg?label=reqwest" alt="reqwest-badge" /></a> <a href="https://docs.rs/tempdir/"><img src="https://badge-cache.kominick.com/crates/v/tempdir.svg?label=tempdir" alt="tempdir-badge" /></a> <a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a> <a href="https://crates.io/categories/filesystem"><img src="https://badge-cache.kominick.com/badge/filesystem--x.svg?style=social" alt="cat-filesystem-badge" /></a></p>
<p>Creates a temporary directory with <a href="https://docs.rs/tempfile/*/tempfile/struct.Builder.html"><code>tempfile::Builder</code></a> and downloads
a file over HTTP using <a href="https://docs.rs/reqwest/*/reqwest/fn.get.html"><code>reqwest::get</code></a> asynchronously.</p>
<p>Creates a target <a href="https://doc.rust-lang.org/std/fs/struct.File.html"><code>File</code></a> with name obtained from <a href="https://docs.rs/reqwest/*/reqwest/struct.Response.html#method.url"><code>Response::url</code></a> within
<a href="https://docs.rs/tempfile/3.1.0/tempfile/struct.Builder.html#method.tempdir"><code>tempdir()</code></a> and copies downloaded data into it with <a href="https://doc.rust-lang.org/std/io/fn.copy.html"><code>io::copy</code></a>.
The temporary directory is automatically removed on program exit.</p>
<pre><pre class="playground"><code class="language-rust edition2018 no_run">use error_chain::error_chain;
use std::io::copy;
use std::fs::File;
use tempfile::Builder;
error_chain! {
foreign_links {
Io(std::io::Error);
HttpRequest(reqwest::Error);
}
}
#[tokio::main]
async fn main() -&gt; Result&lt;()&gt; {
let tmp_dir = Builder::new().prefix(&quot;example&quot;).tempdir()?;
let target = &quot;https://www.rust-lang.org/logos/rust-logo-512x512.png&quot;;
let response = reqwest::get(target).await?;
let mut dest = {
let fname = response
.url()
.path_segments()
.and_then(|segments| segments.last())
.and_then(|name| if name.is_empty() { None } else { Some(name) })
.unwrap_or(&quot;tmp.bin&quot;);
println!(&quot;file to download: '{}'&quot;, fname);
let fname = tmp_dir.path().join(fname);
println!(&quot;will be located under: '{:?}'&quot;, fname);
File::create(fname)?
};
let content = response.text().await?;
copy(&amp;mut content.as_bytes(), &amp;mut dest)?;
Ok(())
}
</code></pre></pre>
<h2><a class="header" href="#post-a-file-to-paste-rs" id="post-a-file-to-paste-rs">POST a file to paste-rs</a></h2>
<p><a href="https://docs.rs/reqwest/"><img src="https://badge-cache.kominick.com/crates/v/reqwest.svg?label=reqwest" alt="reqwest-badge" /></a> <a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a></p>
<p><a href="https://docs.rs/reqwest/*/reqwest/struct.Client.html"><code>reqwest::Client</code></a> establishes a connection to https://paste.rs
following the <a href="https://docs.rs/reqwest/*/reqwest/struct.RequestBuilder.html"><code>reqwest::RequestBuilder</code></a> pattern. Calling <a href="https://docs.rs/reqwest/*/reqwest/struct.Client.html#method.post"><code>Client::post</code></a>
with a URL establishes the destination, <a href="https://docs.rs/reqwest/*/reqwest/struct.RequestBuilder.html#method.body"><code>RequestBuilder::body</code></a> sets the
content to send by reading the file, and <a href="https://docs.rs/reqwest/*/reqwest/struct.RequestBuilder.html#method.send"><code>RequestBuilder::send</code></a> blocks until
the file uploads and the response returns. <a href="https://doc.rust-lang.org/std/io/trait.Read.html#method.read_to_string"><code>read_to_string</code></a> returns the
response and displays in the console.</p>
<pre><pre class="playground"><code class="language-rust edition2018 no_run">use error_chain::error_chain;
use std::fs::File;
use std::io::Read;
error_chain! {
foreign_links {
HttpRequest(reqwest::Error);
IoError(::std::io::Error);
}
}
#[tokio::main]
async fn main() -&gt; Result&lt;()&gt; {
let paste_api = &quot;https://paste.rs&quot;;
let mut file = File::open(&quot;message&quot;)?;
let mut contents = String::new();
file.read_to_string(&amp;mut contents)?;
let client = reqwest::Client::new();
let res = client.post(paste_api)
.body(contents)
.send()
.await?;
let response_text = res.text().await?;
println!(&quot;Your paste is located at: {}&quot;,response_text );
Ok(())
}
</code></pre></pre>
<h2><a class="header" href="#make-a-partial-download-with-http-range-headers" id="make-a-partial-download-with-http-range-headers">Make a partial download with HTTP range headers</a></h2>
<p><a href="https://docs.rs/reqwest/"><img src="https://badge-cache.kominick.com/crates/v/reqwest.svg?label=reqwest" alt="reqwest-badge" /></a> <a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a></p>
<p>Uses <a href="https://docs.rs/reqwest/*/reqwest/blocking/struct.Client.html#method.head"><code>reqwest::blocking::Client::head</code></a> to get the <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Length">Content-Length</a> of the response.</p>
<p>The code then uses <a href="https://docs.rs/reqwest/*/reqwest/blocking/struct.Client.html#method.get"><code>reqwest::blocking::Client::get</code></a> to download the content in
chunks of 10240 bytes, while printing progress messages. This exmple uses the synchronous
reqwest module. The <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Range">Range</a> header specifies the chunk size and position.</p>
<p>The Range header is defined in <a href="https://tools.ietf.org/html/rfc7233#section-3.1">RFC7233</a>.</p>
<pre><pre class="playground"><code class="language-rust edition2018 no_run">use error_chain::error_chain;
use reqwest::header::{HeaderValue, CONTENT_LENGTH, RANGE};
use reqwest::StatusCode;
use std::fs::File;
use std::str::FromStr;
error_chain! {
foreign_links {
Io(std::io::Error);
Reqwest(reqwest::Error);
Header(reqwest::header::ToStrError);
}
}
struct PartialRangeIter {
start: u64,
end: u64,
buffer_size: u32,
}
impl PartialRangeIter {
pub fn new(start: u64, end: u64, buffer_size: u32) -&gt; Result&lt;Self&gt; {
if buffer_size == 0 {
Err(&quot;invalid buffer_size, give a value greater than zero.&quot;)?;
}
Ok(PartialRangeIter {
start,
end,
buffer_size,
})
}
}
impl Iterator for PartialRangeIter {
type Item = HeaderValue;
fn next(&amp;mut self) -&gt; Option&lt;Self::Item&gt; {
if self.start &gt; self.end {
None
} else {
let prev_start = self.start;
self.start += std::cmp::min(self.buffer_size as u64, self.end - self.start + 1);
Some(HeaderValue::from_str(&amp;format!(&quot;bytes={}-{}&quot;, prev_start, self.start - 1)).expect(&quot;string provided by format!&quot;))
}
}
}
fn main() -&gt; Result&lt;()&gt; {
let url = &quot;https://httpbin.org/range/102400?duration=2&quot;;
const CHUNK_SIZE: u32 = 10240;
let client = reqwest::blocking::Client::new();
let response = client.head(url).send()?;
let length = response
.headers()
.get(CONTENT_LENGTH)
.ok_or(&quot;response doesn't include the content length&quot;)?;
let length = u64::from_str(length.to_str()?).map_err(|_| &quot;invalid Content-Length header&quot;)?;
let mut output_file = File::create(&quot;download.bin&quot;)?;
println!(&quot;starting download...&quot;);
for range in PartialRangeIter::new(0, length - 1, CHUNK_SIZE)? {
println!(&quot;range {:?}&quot;, range);
let mut response = client.get(url).header(RANGE, range).send()?;
let status = response.status();
if !(status == StatusCode::OK || status == StatusCode::PARTIAL_CONTENT) {
error_chain::bail!(&quot;Unexpected server response: {}&quot;, status)
}
std::io::copy(&amp;mut response, &amp;mut output_file)?;
}
let content = response.text()?;
std::io::copy(&amp;mut content.as_bytes(), &amp;mut output_file)?;
println!(&quot;Finished with success!&quot;);
Ok(())
}
</code></pre></pre>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<h1><a class="header" href="#authentication" id="authentication">Authentication</a></h1>
<h2><a class="header" href="#basic-authentication" id="basic-authentication">Basic Authentication</a></h2>
<p><a href="https://docs.rs/reqwest/"><img src="https://badge-cache.kominick.com/crates/v/reqwest.svg?label=reqwest" alt="reqwest-badge" /></a> <a href="https://crates.io/categories/network-programming"><img src="https://badge-cache.kominick.com/badge/net--x.svg?style=social" alt="cat-net-badge" /></a></p>
<p>Uses <a href="https://docs.rs/reqwest/*/reqwest/struct.RequestBuilder.html#method.basic_auth"><code>reqwest::RequestBuilder::basic_auth</code></a> to perform a basic HTTP authentication.</p>
<pre><pre class="playground"><code class="language-rust edition2018 no_run">use reqwest::blocking::Client;
use reqwest::Error;
fn main() -&gt; Result&lt;(), Error&gt; {
let client = Client::new();
let user_name = &quot;testuser&quot;.to_string();
let password: Option&lt;String&gt; = None;
let response = client
.get(&quot;https://httpbin.org/&quot;)
.basic_auth(user_name, password)
.send();
println!(&quot;{:?}&quot;, response);
Ok(())
}
</code></pre></pre>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
</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 type="text/javascript">
window.playground_copyable = true;
</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 -->
<script type="text/javascript">
window.addEventListener('load', function() {
window.setTimeout(window.print, 100);
});
</script>
</body>
</html>