<!DOCTYPE HTML>
<html lang="en" class="sidebar-visible no-js">

<head>
    <!-- Book generated using mdBook -->
    <meta charset="UTF-8">
    <title>Rust 烹饪书</title>
    <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
    <meta name="description" content="有用的 Rust 代码 实践集合">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="theme-color" content="#ffffff" />

    <link rel="shortcut icon" href="favicon.png">
    <link rel="stylesheet" href="css/variables.css">
    <link rel="stylesheet" href="css/general.css">
    <link rel="stylesheet" href="css/chrome.css">
    <link rel="stylesheet" href="css/print.css" media="print">

    <!-- Fonts -->
    <link rel="stylesheet" href="FontAwesome/css/font-awesome.css">
    <link href="https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800"
        rel="stylesheet" type="text/css">
    <link href="https://fonts.googleapis.com/css?family=Source+Code+Pro:500" rel="stylesheet" type="text/css">

    <!-- Highlight.js Stylesheets -->
    <link rel="stylesheet" href="highlight.css">
    <link rel="stylesheet" href="tomorrow-night.css">
    <link rel="stylesheet" href="ayu-highlight.css">

    <!-- Custom theme stylesheets -->
    
    <link rel="stylesheet" href="theme/custom.css">
    

    
</head>

<body class="light">
    <!-- Provide site root to javascript -->
    <script type="text/javascript">var path_to_root = "";</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 = 'light'; }
        document.body.className = theme;
        document.querySelector('html').className = theme + ' js';
    </script>

    <!-- Hide / unhide sidebar before it is displayed -->
    <script type="text/javascript">
        var html = document.querySelector('html');
        var sidebar = 'hidden';
        if (document.body.clientWidth >= 1080) {
            try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch (e) { }
            sidebar = sidebar || 'visible';
        }
        html.classList.remove('sidebar-visible');
        html.classList.add("sidebar-" + sidebar);
    </script>

    <nav id="sidebar" class="sidebar" aria-label="Table of contents">
        <ol class="chapter"><li><a href="intro.zh.html"><strong aria-hidden="true">1.</strong> 目录表</a></li><li><a href="about.zh.html"><strong aria-hidden="true">2.</strong> 关于</a></li><li><a href="algorithms.zh.html"><strong aria-hidden="true">3.</strong> 算法</a></li><li><ol class="section"><li><a href="algorithms/randomness.zh.html"><strong aria-hidden="true">3.1.</strong> 生成随机值</a></li><li><a href="algorithms/sorting.zh.html"><strong aria-hidden="true">3.2.</strong> 排序向量</a></li></ol></li><li><a href="cli.zh.html"><strong aria-hidden="true">4.</strong> 命令行</a></li><li><ol class="section"><li><a href="cli/arguments.zh.html"><strong aria-hidden="true">4.1.</strong> 参数解析</a></li><li><a href="cli/ansi_terminal.zh.html"><strong aria-hidden="true">4.2.</strong> ANSI 终端</a></li></ol></li><li><a href="compression.zh.html"><strong aria-hidden="true">5.</strong> 压缩</a></li><li><ol class="section"><li><a href="compression/tar.zh.html"><strong aria-hidden="true">5.1.</strong> 与 Tarballs 合作</a></li></ol></li><li><a href="concurrency.zh.html"><strong aria-hidden="true">6.</strong> 并发性</a></li><li><ol class="section"><li><a href="concurrency/threads.zh.html"><strong aria-hidden="true">6.1.</strong> 显式线程</a></li><li><a href="concurrency/parallel.zh.html"><strong aria-hidden="true">6.2.</strong> 数据并行性</a></li></ol></li><li><a href="cryptography.zh.html"><strong aria-hidden="true">7.</strong> 密码学</a></li><li><ol class="section"><li><a href="cryptography/hashing.zh.html"><strong aria-hidden="true">7.1.</strong> 哈希</a></li><li><a href="cryptography/encryption.zh.html"><strong aria-hidden="true">7.2.</strong> 加密</a></li></ol></li><li><a href="data_structures.zh.html"><strong aria-hidden="true">8.</strong> 数据结构</a></li><li><ol class="section"><li><a href="data_structures/bitfield.zh.html"><strong aria-hidden="true">8.1.</strong> 位字段</a></li></ol></li><li><a href="database.zh.html"><strong aria-hidden="true">9.</strong> 数据库</a></li><li><ol class="section"><li><a href="database/sqlite.zh.html"><strong aria-hidden="true">9.1.</strong> SQLite</a></li><li><a href="database/postgres.zh.html"><strong aria-hidden="true">9.2.</strong> Postgres</a></li></ol></li><li><a href="datetime.zh.html"><strong aria-hidden="true">10.</strong> 日期和时间</a></li><li><ol class="section"><li><a href="datetime/duration.zh.html"><strong aria-hidden="true">10.1.</strong> 持续时间和计算</a></li><li><a href="datetime/parse.zh.html"><strong aria-hidden="true">10.2.</strong> 解析与显示</a></li></ol></li><li><a href="development_tools.zh.html"><strong aria-hidden="true">11.</strong> 开发工具</a></li><li><ol class="section"><li><a href="development_tools/debugging.zh.html"><strong aria-hidden="true">11.1.</strong> 调试</a></li><li><ol class="section"><li><a href="development_tools/debugging/log.zh.html"><strong aria-hidden="true">11.1.1.</strong> 日志消息</a></li><li><a href="development_tools/debugging/config_log.zh.html"><strong aria-hidden="true">11.1.2.</strong> 配置日志记录</a></li></ol></li><li><a href="development_tools/versioning.zh.html"><strong aria-hidden="true">11.2.</strong> 版本控制</a></li><li><a href="development_tools/build_tools.zh.html"><strong aria-hidden="true">11.3.</strong> 建立时间工具</a></li></ol></li><li><a href="encoding.zh.html"><strong aria-hidden="true">12.</strong> 编码</a></li><li><ol class="section"><li><a href="encoding/strings.zh.html"><strong aria-hidden="true">12.1.</strong> 字符集</a></li><li><a href="encoding/csv.zh.html"><strong aria-hidden="true">12.2.</strong> CSV 处理</a></li><li><a href="encoding/complex.zh.html"><strong aria-hidden="true">12.3.</strong> 结构化数据</a></li></ol></li><li><a href="errors.zh.html"><strong aria-hidden="true">13.</strong> 错误处理</a></li><li><ol class="section"><li><a href="errors/handle.zh.html"><strong aria-hidden="true">13.1.</strong> 处理错误变量</a></li></ol></li><li><a href="file.zh.html"><strong aria-hidden="true">14.</strong> 文件系统</a></li><li><ol class="section"><li><a href="file/read-write.zh.html"><strong aria-hidden="true">14.1.</strong> 读写</a></li><li><a href="file/dir.zh.html"><strong aria-hidden="true">14.2.</strong> 目录穿梭</a></li></ol></li><li><a href="hardware.zh.html"><strong aria-hidden="true">15.</strong> 硬件支持</a></li><li><ol class="section"><li><a href="hardware/processor.zh.html"><strong aria-hidden="true">15.1.</strong> 处理器</a></li></ol></li><li><a href="mem.zh.html"><strong aria-hidden="true">16.</strong> 内存管理</a></li><li><ol class="section"><li><a href="mem/global_static.zh.html"><strong aria-hidden="true">16.1.</strong> 全局静态</a></li></ol></li><li><a href="net.zh.html"><strong aria-hidden="true">17.</strong> 网络</a></li><li><ol class="section"><li><a href="net/server.zh.html"><strong aria-hidden="true">17.1.</strong> 服务器</a></li></ol></li><li><a href="os.zh.html"><strong aria-hidden="true">18.</strong> 操作系统</a></li><li><ol class="section"><li><a href="os/external.zh.html"><strong aria-hidden="true">18.1.</strong> 外部命令</a></li></ol></li><li><a href="science.zh.html"><strong aria-hidden="true">19.</strong> 科学类</a></li><li><ol class="section"><li><a href="science/mathematics.zh.html"><strong aria-hidden="true">19.1.</strong> 数学</a></li><li><ol class="section"><li><a href="science/mathematics/linear_algebra.zh.html"><strong aria-hidden="true">19.1.1.</strong> 线性代数</a></li><li><a href="science/mathematics/trigonometry.zh.html"><strong aria-hidden="true">19.1.2.</strong> 三角法</a></li><li><a href="science/mathematics/complex_numbers.zh.html"><strong aria-hidden="true">19.1.3.</strong> 复数</a></li><li><a href="science/mathematics/statistics.zh.html"><strong aria-hidden="true">19.1.4.</strong> 统计</a></li><li><a href="science/mathematics/miscellaneous.zh.html"><strong aria-hidden="true">19.1.5.</strong> 混杂</a></li></ol></li></ol></li><li><a href="text.zh.html"><strong aria-hidden="true">20.</strong> 文本处理</a></li><li><ol class="section"><li><a href="text/regex.zh.html"><strong aria-hidden="true">20.1.</strong> 正则表达式</a></li><li><a href="text/string_parsing.zh.html"><strong aria-hidden="true">20.2.</strong> 字符串解析</a></li></ol></li><li><a href="web.zh.html"><strong aria-hidden="true">21.</strong> 网页编程</a></li><li><ol class="section"><li><a href="web/scraping.zh.html"><strong aria-hidden="true">21.1.</strong> 提取链接</a></li><li><a href="web/url.zh.html"><strong aria-hidden="true">21.2.</strong> 统一资源定位地址:URL</a></li><li><a href="web/mime.zh.html"><strong aria-hidden="true">21.3.</strong> 媒体类型</a></li><li><a href="web/clients.zh.html"><strong aria-hidden="true">21.4.</strong> 客户端</a></li><li><ol class="section"><li><a href="web/clients/requests.zh.html"><strong aria-hidden="true">21.4.1.</strong> 提出请求</a></li><li><a href="web/clients/apis.zh.html"><strong aria-hidden="true">21.4.2.</strong> 调用 Web API</a></li><li><a href="web/clients/download.zh.html"><strong aria-hidden="true">21.4.3.</strong> 下载</a></li></ol></li></ol></li></ol>
    </nav>

    <div id="page-wrapper" class="page-wrapper">

        <div class="page">
            
            <div id="menu-bar" class="menu-bar">
                <div id="menu-bar-sticky-container">
                    <div class="left-buttons">
                        <button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents"
                            aria-label="Toggle Table of Contents" aria-controls="sidebar">
                            <i class="fa fa-bars"></i>
                        </button>
                        <!-- START - Rust Cookbook customization -->
                        <button id="edit-button" class="icon-button" type="button" title="Fork and edit" aria-label="Fork and edit"
                            aria-haspopup="true" aria-expanded="false" aria-controls="edit">
                            <i class="fa fa-edit">Edit</i>
                        </button>
                        <!-- END - Rust Cookbook customization -->
                        <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 <span class="default">(default)</span></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 烹饪书</h1>
                    
                        <div class="right-buttons">
                            <a href="print.html" title="Print this book" aria-label="Print this book">
                                <i id="print-button" class="fa fa-print"></i>
                            </a>
                            
                        </div>
                    </div>
                </div>

            
            <div id="search-wrapper" class="hidden">
                <form id="searchbar-outer" class="searchbar-outer">
                    <input type="search" name="search" id="searchbar" name="searchbar" placeholder="Search this book ..."
                        aria-controls="searchresults-outer" aria-describedby="searchresults-header">
                </form>
                <div id="searchresults-outer" class="searchresults-outer hidden">
                    <div id="searchresults-header" class="searchresults-header"></div>
                    <ul id="searchresults">
                    </ul>
                </div>
            </div>
            

            <!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
            <script type="text/javascript">
                document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
                document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
                Array.from(document.querySelectorAll('#sidebar a')).forEach(function (link) {
                    link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
                });
            </script>

            <!-- // START - Rust Cookbook customization -->
            <script>
                document.getElementById("edit-button").addEventListener("click", function () {
                    var editWindow = window.open("https://github.com/chinanf-boy/rust-cookbook-zh/edit/master/src/print.md");
                });</script>
            <!-- // END - Rust Cookbook customization -->

            <div id="content" class="content">
                <main>
                    <a class="header" href="#rust-烹饪书" id="rust-烹饪书"><h1>Rust 烹饪书</h1></a>
<p>这个<em>Rust 烹饪书</em>是一套简单的例子，它演示了如何使用 Rust 生态系统的箱子，作为完成常见编程任务的良好实践。</p>
<p><a href="about.zh.html">了解 <em>Rust 烹饪书</em> 更多</a>，包括如何阅读这本书的提示、如何使用示例，以及约定好的注释风格。</p>
<a class="header" href="#贡献" id="贡献"><h2>贡献</h2></a>
<p>这个项目的目的是，让新的 Rust 程序员能够容易做出贡献，帮个小忙，并且是一个与 Rust 社区接触的简单方法。本库十分欢迎帮助。详情见<a href="https://github.com/rust-lang-nursery/rust-cookbook/blob/master/CONTRIBUTING.md">CONTRIBUTING.md</a>.</p>
<a class="header" href="#算法" id="算法"><h1>算法</h1></a>
<table><thead><tr><th> 食谱                                                 </th><th> 箱子                  </th><th> 分类                                </th></tr></thead><tbody>
<tr><td> <a href="algorithms/randomness.zh.html#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.zh.html#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.zh.html#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> </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.zh.html#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.zh.html#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.zh.html#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.zh.html#sort-a-vector-of-integers">排序一个，整数的 vector</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.zh.html#sort-a-vector-of-floats">排序一个，浮点的 vector</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.zh.html#sort-a-vector-of-structs">排序一个，结构的 vector</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 -->
<a class="header" href="#命令行" id="命令行"><h1>命令行</h1></a>
<table><thead><tr><th> 食谱                            </th><th> 箱子                            </th><th> 分类                                          </th></tr></thead><tbody>
<tr><td> <a href="cli/arguments.zh.html#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.zh.html#ansi-terminal">ANSI 终端</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 -->
<a class="header" href="#压缩" id="压缩"><h1>压缩</h1></a>
<table><thead><tr><th> 食谱                                                          </th><th> 箱子                                          </th><th> 分类                                        </th></tr></thead><tbody>
<tr><td> <a href="compression/tar.zh.html#decompress-a-tarball">解压缩 一个 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.zh.html#compress-a-directory-into-tarball">将一个目录压缩为 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.zh.html#decompress-a-tarball-while-removing-a-prefix-from-the-paths">从路径中删除前缀时，解压缩一个 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>
</tbody></table>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<a class="header" href="#并发性" id="并发性"><h1>并发性</h1></a>
<table><thead><tr><th> 食谱                                                                   </th><th> 箱子                                                                                                              </th><th> 类别                                                                                                                  </th></tr></thead><tbody>
<tr><td> <a href="concurrency/threads.zh.html#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.zh.html#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.zh.html#calculate-sha1-sum-of-iso-files-concurrently">并发计算所有 <code>*.iso</code> 文件的 SHA1 和</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.zh.html#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.zh.html#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.zh.html#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.zh.html#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.zh.html#sort-a-vector-in-parallel">并行，排序 vector</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.zh.html#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.zh.html#generate-jpg-thumbnails-in-parallel">并行，生成 JPG 缩略图</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 -->
<a class="header" href="#密码学" id="密码学"><h1>密码学</h1></a>
<table><thead><tr><th> 食谱                                                        </th><th> 箱子                                                          </th><th> 类别                                          </th></tr></thead><tbody>
<tr><td> <a href="cryptography/hashing.zh.html#calculate-the-sha-256-digest-of-a-file">计算文件的 SHA-256 码</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.zh.html#sign-and-verify-a-message-with-hmac-digest">使用 HMAC 码，签名并验证消息</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.zh.html#salt-and-hash-a-password-with-pbkdf2">用 PBKDF2 对密码，进行 加盐(Salt) 和 哈希 操作</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 -->
<a class="header" href="#数据结构" id="数据结构"><h1>数据结构</h1></a>
<table><thead><tr><th> 食谱                                          </th><th> 箱子                          </th><th> 类别                              </th></tr></thead><tbody>
<tr><td> <a href="data_structures/bitfield.zh.html#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 -->
<a class="header" href="#数据库" id="数据库"><h1>数据库</h1></a>
<table><thead><tr><th> 食谱                                                      </th><th> 箱子                          </th><th> 类别                                  </th></tr></thead><tbody>
<tr><td> <a href="database/sqlite.zh.html#create-a-sqlite-database">创建 sqlite 数据库</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.zh.html#insert-and-select-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.zh.html#create-tables-in-a-postgres-database">在 Postgres 数据库中，创建表</a> </td><td> [![postgres-badge]][postgres] </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.zh.html#insert-and-query-data">插入和查询数据</a>           </td><td> [![postgres-badge]][postgres] </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.zh.html#aggregate-data">综合数据</a>                    </td><td> [![postgres-badge]][postgres] </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 -->
<a class="header" href="#日期和时间" id="日期和时间"><h1>日期和时间</h1></a>
<table><thead><tr><th> 食谱                                                              </th><th> 箱子                      </th><th> 类别                                            </th></tr></thead><tbody>
<tr><td> <a href="datetime/duration.zh.html#measure-the-elapsed-time-between-two-code-sections">测量已用时间</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.zh.html#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.zh.html#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.zh.html#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.zh.html#convert-date-to-unix-timestamp-and-vice-versa">将日期转换为 Unix 时间戳，或相反</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.zh.html#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.zh.html#parse-string-into-datetime-struct">将字符串解析为 DateTime 结构</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 -->
<a class="header" href="#开发工具" id="开发工具"><h1>开发工具</h1></a>
<a class="header" href="#调试" id="调试"><h2>调试</h2></a>
<table><thead><tr><th> 食谱                                                    </th><th> 箱子                                                                            </th><th> 类别                                    </th></tr></thead><tbody>
<tr><td> <a href="development_tools/debugging/log.zh.html#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.zh.html#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.zh.html#log-to-stdout-instead-of-stderr">记录到 stdout ，而不是 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.zh.html#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.zh.html#log-to-the-unix-syslog">记录到 Unix 系统日志</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.zh.html#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.zh.html#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.zh.html#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.zh.html#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 -->
<a class="header" href="#版本控制" id="版本控制"><h2>版本控制</h2></a>
<table><thead><tr><th> 食谱                                                   </th><th> 箱子                      </th><th> 类别                                                                          </th></tr></thead><tbody>
<tr><td> <a href="development_tools/versioning.zh.html#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.zh.html#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.zh.html#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.zh.html#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.zh.html#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>
<a class="header" href="#构建时" id="构建时"><h2>构建时</h2></a>
<table><thead><tr><th> 食谱                                                   </th><th> 箱子              </th><th> 类别                                                    </th></tr></thead><tbody>
<tr><td> <a href="development_tools/build_tools.zh.html#compile-and-link-statically-to-a-bundled-c-library">静态编译，并链接到捆绑的 C 库</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.zh.html#compile-and-link-statically-to-a-bundled-c-library-1">编译，并链接到捆绑的 C++库</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.zh.html#compile-a-c-library-while-setting-custom-defines">自定义设置时，编译 C 库</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 -->
<a class="header" href="#编码" id="编码"><h1>编码</h1></a>
<table><thead><tr><th> 食谱                                                                </th><th> 箱子                                        </th><th> 类别                                  </th></tr></thead><tbody>
<tr><td> <a href="encoding/strings.zh.html#percent-encode-a-string">百分比编码(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/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.zh.html#encode-a-string-as-applicationx-www-form-urlencoded">将字符串，编码为 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.zh.html#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.zh.html#encode-and-decode-base64">对 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.zh.html#read-csv-records">读取 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.zh.html#read-csv-records-with-different-delimiter">读取具有不同分隔符的 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.zh.html#filter-csv-records-matching-a-predicate">筛选与断言匹配的 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.zh.html#handle-invalid-csv-data-with-serde">使用 serde ，处理无效的 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> <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.zh.html#serialize-records-to-csv">将记录序列化为 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.zh.html#serialize-records-to-csv-using-serde">使用 serde ，将记录序列化为 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> <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.zh.html#transform-csv-column">转换 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> <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.zh.html#serialize-and-deserialize-unstructured-json">序列化和反序列化，非结构化 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.zh.html#deserialize-a-toml-configuration-file">反序列化，一个 Toml 配置文件</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.zh.html#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 -->
<a class="header" href="#文件系统" id="文件系统"><h1>文件系统</h1></a>
<table><thead><tr><th> 食谱                                                         </th><th> 箱子                            </th><th> 类别                                                                </th></tr></thead><tbody>
<tr><td> <a href="file/read-write.zh.html#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.zh.html#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.zh.html#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.zh.html#file-names-that-have-been-modified-in-the-last-24-hours">过去 24 小时内，修改过的文件名</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.zh.html#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.zh.html#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.zh.html#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.zh.html#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.zh.html#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.zh.html#find-all-png-files-recursively">递归查找，所有 PNG 文件</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.zh.html#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 -->
<a class="header" href="#硬件支持" id="硬件支持"><h1>硬件支持</h1></a>
<table><thead><tr><th> 食谱                                      </th><th> 箱子                          </th><th> 类别                                                  </th></tr></thead><tbody>
<tr><td> <a href="hardware/processor.zh.html#check-number-of-logical-cpu-cores">检查逻辑 CPU 的核数</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 -->
<a class="header" href="#内存管理" id="内存管理"><h1>内存管理</h1></a>
<table><thead><tr><th> 食谱                                     </th><th> 箱子                                </th><th> 类别                                                                                </th></tr></thead><tbody>
<tr><td> <a href="mem/global_static.zh.html#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 -->
<a class="header" href="#网络" id="网络"><h1>网络</h1></a>
<table><thead><tr><th> 食谱                                            </th><th> 箱子                </th><th> 类别                        </th></tr></thead><tbody>
<tr><td> <a href="net/server.zh.html#listen-on-unused-port-tcpip">侦听，未使用的端口 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 -->
<a class="header" href="#操作系统" id="操作系统"><h1>操作系统</h1></a>
<table><thead><tr><th> 食谱                                                                                  </th><th> 箱子                    </th><th> 类别                                                                          </th></tr></thead><tbody>
<tr><td> <a href="os/external.zh.html#run-an-external-command-and-process-stdout">运行外部命令，并处理 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.zh.html#run-an-external-command-passing-it-stdin-and-check-for-an-error-code">运行传递到 stdin 的外部命令，并检查错误代码</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.zh.html#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.zh.html#redirect-both-stdout-and-stderr-of-child-process-to-the-same-file">将子进程的 stdout 和 stderr ，重定向到同一文件</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.zh.html#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>
</tbody></table>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<a class="header" href="#科学类" id="科学类"><h1>科学类</h1></a>
<a class="header" href="#数学" id="数学"><h2>数学</h2></a>
<table><thead><tr><th> 食谱                                                            </th><th> 箱子                          </th><th> 类别                                </th></tr></thead><tbody>
<tr><td> <a href="science/mathematics/linear_algebra.zh.html#vector-sum">vector 和</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.zh.html#vector-norm">vector 范数</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.zh.html#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.zh.html#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.zh.html#multiply-a-scalar-with-a-vector-with-a-matrix">用 vector 和矩阵，相乘一个标量</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.zh.html#invert-matrix">反转矩阵</a>                                       </td><td> [![nalgebra-badge]][nalgebra] </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.zh.html#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.zh.html#verifying-tan-is-equal-to-sin-divided-by-cos">验证 tan 等于 sin 除以 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.zh.html#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.zh.html#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.zh.html#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.zh.html#mathematical-functions">复数的数学函数</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.zh.html#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.zh.html#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.zh.html#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 -->
<a class="header" href="#文本处理" id="文本处理"><h1>文本处理</h1></a>
<table><thead><tr><th> 食谱                                                                     </th><th> 箱子                                                        </th><th> 类别                                                </th></tr></thead><tbody>
<tr><td> <a href="text/string_parsing.zh.html#collect-unicode-graphemes">收集 Unicode 字形</a>                                </td><td> [![unicode-segmentation-badge]][unicode-segmentation]       </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.zh.html#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.zh.html#extract-a-list-of-unique-hashtags-from-a-text">从文本中，提取独一的<code>#</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> <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.zh.html#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.zh.html#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.zh.html#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.zh.html#implement-the-fromstr-trait-for-a-custom-struct">为一个自定义<code>struct</code>，实现<code>FromStr</code>trait</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 -->
<a class="header" href="#网页编程" id="网页编程"><h1>网页编程</h1></a>
<a class="header" href="#刮擦网页" id="刮擦网页"><h2>刮擦网页</h2></a>
<table><thead><tr><th> 食谱                                                                   </th><th> 箱子                                                                      </th><th> 类别                        </th></tr></thead><tbody>
<tr><td> <a href="web/scraping.zh.html#extract-all-links-from-a-webpage-html">从网页 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.zh.html#check-a-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.zh.html#extract-all-unique-links-from-a-mediawiki-markup">从 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>
<a class="header" href="#统一资源位置url" id="统一资源位置url"><h2>统一资源位置（URL）</h2></a>
<table><thead><tr><th> 食谱                                                </th><th> 箱子                </th><th> 类别                        </th></tr></thead><tbody>
<tr><td> <a href="web/url.zh.html#parse-a-url-from-a-string-to-a-url-type">将字符串的一个 URL，解析为<code>Url</code>类型</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.zh.html#create-a-base-url-by-removing-path-segments">通过移除路径段，创建一个 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.zh.html#create-new-urls-from-a-base-url">从 base URL ，创建新的 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.zh.html#extract-the-url-origin-scheme--host--port">提取 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.zh.html#remove-fragment-identifiers-and-query-pairs-from-a-url">从 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>
<a class="header" href="#媒体类型mime" id="媒体类型mime"><h2>媒体类型（MIME）</h2></a>
<table><thead><tr><th> 食谱                                                     </th><th> 箱子                                              </th><th> 类别                                                              </th></tr></thead><tbody>
<tr><td> <a href="web/mime.zh.html#get-mime-type-from-string">从字符串，获取 MIME 类型</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.zh.html#get-mime-type-from-filename">从文件名，获取 MIME 类型</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.zh.html#parse-the-mime-type-of-a-http-response">解析 HTTP 响应的 MIME 类型</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>
<a class="header" href="#客户端" id="客户端"><h2>客户端</h2></a>
<table><thead><tr><th> 食谱                                                         </th><th> 箱子                                                    </th><th> 类别                                                                  </th></tr></thead><tbody>
<tr><td> <a href="web/clients/requests.zh.html#make-a-http-get-request">发出 HTTP GET 请求</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.zh.html#query-the-github-api">查询 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.zh.html#check-if-an-api-resource-exists">检查 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>                             </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.zh.html#create-and-delete-gist-with-github-api">使用 GitHub API ，创建和删除 Gist</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.zh.html#consume-a-paginated-restful-api">使用一个（具备）分页的 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.zh.html#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.zh.html#make-a-partial-download-with-http-range-headers">使用 HTTP range 标头，进行部分下载</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.zh.html#post-a-file-to-paste-rs">POST 文件，到 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 -->
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<a class="header" href="#关于rust-烹饪" id="关于rust-烹饪"><h1>关于“Rust 烹饪”</h1></a>
<a class="header" href="#目录" id="目录"><h2>目录</h2></a>
<!-- START doctoc -->
<!-- END doctoc -->
<a class="header" href="#这本书的目标受众" id="这本书的目标受众"><h2>这本书的目标受众</h2></a>
<p>本手册适用于新的 Rust 程序员，因此他们可以快速了解 Rust crate(箱子) 生态系统的能力。它也适用于经验丰富的 Rust 程序员，他们应该在食谱中，找到如何完成常见任务的简单提示。</p>
<a class="header" href="#如何阅读本书" id="如何阅读本书"><h2>如何阅读本书</h2></a>
<p>烹饪书的<a href="intro.zh.html">索引页</a>包含完整的食谱列表，分为几个部分：“基础”，“编码”，“并发”等。这些部分本身或多或少地按顺序排列，后面的部分，更先进，偶尔是在前面部分的概念之上构建。</p>
<p>在索引中，每个部分都包含一个食谱列表。食谱是要完成任务的简单陈述，例如“生成范围内的随机数”；并且每个食谱都标有徽章，表明哪个<em>箱子</em>是他们所使用的，像<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">crates.io</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>新的 Rust 程序员，应该从第一部分开始，按顺序到最后一部分，这样阅读起来会很舒服，这样做可以让人们对 crate 生态系统，有一个很好的大菊观。单击，索引中的章节标题，或单击，侧栏以导航到某章节页面。</p>
<p>如果，您只是在寻找简单任务的解决方案，那么今时今日的烹饪书，还较难导航。查找特定食谱的最简单方法是扫描索引，查找感兴趣的箱子和类别。从那里，单击食谱名称进行查看。这导航方面在未来会改善的。</p>
<a class="header" href="#如何使用食谱" id="如何使用食谱"><h2>如何使用食谱</h2></a>
<p>食谱旨在让您即时访问到，能工作的代码，并全面解释其正在执行的操作，并指导您获取更多信息。</p>
<p>烹饪书中的所有食谱都是完整的，自包含(自给自足)的程序，因此可以将它们直接复制到，您自己的项目中进行实验。为此，请按照以下说明，进行操作。</p>
<p>考虑这个例子：“生成一个范围内的随机数”：</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="playpen"><code class="language-rust">extern crate rand;
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>要在本地使用它，我们可以运行以下命令，来创建一个新的货物(cargo)项目，并切换到该目录：</p>
<pre><code class="language-sh">cargo new my-example --bin
cd my-example
</code></pre>
<p>现在，我们还需要添加必要的箱子到<a href="http://doc.crates.io/manifest.html">Cargo.toml</a>，如箱子徽章所示，在这种情况下只是“rand”。为此，我们将使用<code>cargo add</code>命令，这是由<a href="https://github.com/killercup/cargo-edit"><code>cargo-edit</code></a>箱子提供的(自定义)命令，我们需要先安装：</p>
<pre><code class="language-sh">cargo install cargo-edit
cargo add rand
</code></pre>
<p>现在，你可以把<code>src/main.rs</code>，替换成，用例中的完整内容并运行：</p>
<pre><code class="language-sh">cargo run
</code></pre>
<p>示例附带的箱子徽章，链接到箱子的完整<a href="https://docs.rs">docs.rs</a>文档(一个专放Rust项目文档的官方托管网站)，并且通常，在你决定哪个箱子套件后，您应该阅读相关文档。</p>
<a class="header" href="#关于错误处理的说明" id="关于错误处理的说明"><h2>关于错误处理的说明</h2></a>
<p>如果做得正确，Rust 中的错误处理是健壮的，但对今时今日的 Rust 来说，就需要相当多的模版。正是这个原因，你经常看到 Rust 的例子，充满了<code>unwrap</code>调用，而不是正确的错误处理。</p>
<p>由于这些食谱，具有原样复用的目标，并鼓励最佳实践，因此当涉及<code>Result</code>类型，它们就会正确设置错误处理。</p>
<p>我们使用的基本模式是，具备一个<code>fn run() -&gt; Result</code>，让它像“真正的”main 函数行动。我们用的是<a href="https://docs.rs/error-chain/">error-chain</a>箱子，使<code>?</code>在<code>run</code>里面工作。</p>
<p>错误处理的结构，通常如下：</p>
<pre><pre class="playpen"><code class="language-rust">#[macro_use]
extern crate error_chain;

use std::net::IpAddr;
use std::str;

error_chain! {
    foreign_links {
        Utf8(std::str::Utf8Error);
        AddrParse(std::net::AddrParseError);
    }
}

fn run() -&gt; Result&lt;()&gt; {
    let bytes = b&quot;2001:db8::1&quot;;

    // Bytes 到 string.
    let s = str::from_utf8(bytes)?;

    // String 到 IP address.
    let addr: IpAddr = s.parse()?;

    println!(&quot;{:?}&quot;, addr);
    Ok(())
}

quick_main!(run);
</code></pre></pre>
<p>这是使用<code>error_chain!</code>宏，自定义一个<code>Error</code>和<code>Result</code>类型，以及来自<strong>两个标准库的错误类型</strong>的自动转换。自动转换使<code>?</code>操作符工作。该<code>quick_main!</code>宏生成，实际<code>main</code>，并在发生错误时，打印出错误。</p>
<p>为了便于阅读，错误处理模版，默认隐藏，如下所示。要阅读完整内容，请单击“展开”（<i class="fa fa-expand"></i>）按钮，它位于代码段的右上角。</p>
<pre><pre class="playpen"><code class="language-rust"># #[macro_use]
# extern crate error_chain;
extern crate url;

use url::{Url, Position};
#
# error_chain! {
#     foreign_links {
#         UrlParse(url::ParseError);
#     }
# }

fn run() -&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(())
}
#
# quick_main!(run);
</code></pre></pre>
<p>有关 Rust 中错误处理的更多背景知识，请阅读<a href="https://doc.rust-lang.org/book/error-handling.html">这本 Rust 书</a>和<a href="https://brson.github.io/2016/11/30/starting-with-error-chain">这篇博文</a>。</p>
<a class="header" href="#关于箱子表示的说明" id="关于箱子表示的说明"><h2>关于箱子表示的说明</h2></a>
<p>这本烹饪书，最终的目标，是提供对 Rust crate 生态系统的广泛认知，但是，今天我们在它的引导下，进行演示时，范围还很有限。希望从小范围开始，缓慢扩展(认知)，将有助于烹饪书，更快地成为高质量的资源，常话说：不要急，最重要快！并在增长时，保持一致的质量水平。</p>
<p>目前，烹饪书专注于标准库，以及“核心”或“基础”，箱子 - 都是构成最常见的编程任务的那些箱子，其余的，就是生态系统的部分构建。</p>
<p>这本烹饪书与<a href="https://internals.rust-lang.org/t/rust-libz-blitz/5184">Rust Libz Blitz</a>密切相关，一个识别和提高此类箱子质量的项目，因此该项目在很大程度上，延迟箱子入选的问题。该过程的一部分，作为已经评估的任何箱子，都在烹饪书的(书写)范围内，而正在等待评估的箱子也是如此。</p>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<a class="header" href="#算法-1" id="算法-1"><h1>算法</h1></a>
<table><thead><tr><th> 食谱                                                 </th><th> 箱子                  </th><th> 分类                                </th></tr></thead><tbody>
<tr><td> <a href="algorithms/randomness.zh.html#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.zh.html#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.zh.html#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> </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.zh.html#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.zh.html#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.zh.html#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.zh.html#sort-a-vector-of-integers">排序一个，整数的 vector</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.zh.html#sort-a-vector-of-floats">排序一个，浮点的 vector</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.zh.html#sort-a-vector-of-structs">排序一个，结构的 vector</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 -->
<a class="header" href="#生成随机值" id="生成随机值"><h1>生成随机值</h1></a>
<a class="header" href="#生成随机数" id="生成随机数"><h2>生成随机数</h2></a>
<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>通过<a href="https://docs.rs/rand/*/rand/fn.thread_rng.html"><code>rand::thread_rng</code></a>，在随机数生成器<a href="https://docs.rs/rand/*/rand/trait.Rng.html"><code>rand::Rng</code></a>的帮助下，生成随机数。每个线程都有一个初始化的生成器。整数在该类型的范围（最大值 ～ 最小值）内，均匀分布，还有，浮点数是从 0 到 1，但不包括 1 的 均匀分布。</p>
<pre><pre class="playpen"><code class="language-rust">extern crate rand;

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>
<a class="header" href="#生成范围内的随机数" id="生成范围内的随机数"><h2>生成范围内的随机数</h2></a>
<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>用<a href="https://doc.rust-lang.org/rand/*/rand/trait.Rng.html#method.gen_range"><code>Rng::gen_range</code></a>，在半开放<code>[0, 10)</code>范围（不包括<code>10</code>）生成随机值。</p>
<pre><pre class="playpen"><code class="language-rust">extern crate rand;

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>可以用来获得<a href="https://en.wikipedia.org/wiki/Uniform_distribution_(continuous)">均匀分布</a>的值。下面的代码是相同作用，但是当在相同范围内，重复生成数字时可能更快。</p>
<pre><pre class="playpen"><code class="language-rust">extern crate rand;


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>
<a class="header" href="#生成给定分布的随机数" id="生成给定分布的随机数"><h2>生成给定分布的随机数</h2></a>
<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>默认情况下，随机数有<a href="https://en.wikipedia.org/wiki/Uniform_distribution_(continuous)">均匀(Uniform) 分布</a>。要使用其他（概率/类型的）分布生成数字，您需要实例化一个分布(distribution)，然后用分布下的<a href="https://docs.rs/rand/*/rand/distributions/trait.Distribution.html#tymethod.sample"><code>Distribution::sample</code></a>方法，在随机数生成器<a href="https://docs.rs/rand/*/rand/trait.Rng.html"><code>rand::Rng</code></a>的帮助下，进行采样。</p>
<p>关于<a href="https://docs.rs/rand/*/rand/distributions/index.html">可用分布的文档，在此</a>。下面是，一个使用<a href="https://docs.rs/rand/*/rand/distributions/normal/struct.Normal.html"><code>Normal</code></a>分布的的例子。</p>
<pre><pre class="playpen"><code class="language-rust">extern crate rand;

use rand::distributions::{Normal, Distribution};

fn main() {
  let mut rng = rand::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)
}
</code></pre></pre>
<a class="header" href="#生成自定义类型的随机值" id="生成自定义类型的随机值"><h2>生成自定义类型的随机值</h2></a>
<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>随机生成一个元组<code>(i32, bool, f64)</code>，和用户定义类型的变量<code>Point</code>。在 <code>Point</code> 类型之上，对<a href="https://docs.rs/rand/*/rand/distributions/struct.Standard.html"><code>Standard</code></a>实现<a href="https://docs.rs/rand/*/rand/distributions/trait.Distribution.html"><code>Distribution</code></a> trait，为了(<code>Point</code>)允许随机生成(<code>gen</code>)。</p>
<blockquote>
<p>这里，用得是，具象化泛型类型。</p>
</blockquote>
<pre><pre class="playpen"><code class="language-rust">extern crate rand;

use rand::Rng;
use rand::distributions::{Distribution, Standard};

#[derive(Debug)]
struct Point {
    x: i32,
    y: i32,
}

// 把 泛型 具象化为 Point， (定义实现)
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(); 
    // 主要是 : Point，类型标签，让编译器知道 (调用上面的实现定义)
    println!(&quot;Random tuple: {:?}&quot;, rand_tuple);
    println!(&quot;Random Point: {:?}&quot;, rand_point);
}
</code></pre></pre>
<a class="header" href="#从一组字母数字的字符创建随机密码" id="从一组字母数字的字符创建随机密码"><h2>从一组字母+数字的字符，创建随机密码</h2></a>
<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>随机生成，给定长度的 ASCII 字符串，字符范围是<code>A-Z, a-z, 0-9</code>，运用<a href="https://docs.rs/rand/*/rand/distributions/struct.Alphanumeric.html"><code>Alphanumeric</code></a> （字母+数字）样品。</p>
<pre><pre class="playpen"><code class="language-rust">extern crate rand;

use rand::{thread_rng, Rng};
use rand::distributions::Alphanumeric;

fn main() {
    let rand_string: String = thread_rng()
        .sample_iter(&amp;Alphanumeric)
        .take(30)
        .collect();

    println!(&quot;{}&quot;, rand_string);
}
</code></pre></pre>
<a class="header" href="#从一组用户定义的字符创建随机密码" id="从一组用户定义的字符创建随机密码"><h2>从一组用户定义的字符，创建随机密码</h2></a>
<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>使用用户自定义的字节字符串，随机生成给定长度的 ASCII 字符串，运用<a href="https://docs.rs/rand/*/rand/trait.Rng.html#method.gen_range"><code>gen_range</code></a>。</p>
<pre><pre class="playpen"><code class="language-rust">extern crate rand;

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());
            // 这是安全的，因为 `idx` 会在 `CHARSET` 的范围内。
            char::from(unsafe { *CHARSET.get_unchecked(idx) }) // 来自用户的所有输入，最好都定义为不安全的。
        })
        .collect();

    println!(&quot;{:?}&quot;, password);
}
</code></pre></pre>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<a class="header" href="#排序-vector" id="排序-vector"><h1>排序 vector</h1></a>
<a class="header" href="#排序整数-vector" id="排序整数-vector"><h2>排序整数 vector</h2></a>
<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 href="https://doc.rust-lang.org/std/vec/struct.Vec.html#method.sort"><code>vec::sort</code></a>对整数 vector 进行排序。替代方案是使用<a href="https://doc.rust-lang.org/std/vec/struct.Vec.html#method.sort_unstable"><code>vec::sort_unstable</code></a>，它可以更快，但不保留相等元素的顺序。</p>
<pre><pre class="playpen"><code class="language-rust">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>
<a class="header" href="#排序浮点数-vector" id="排序浮点数-vector"><h2>排序浮点数 vector</h2></a>
<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 href="https://doc.rust-lang.org/std/primitive.slice.html#method.sort_by"><code>vec::sort_by</code></a>和<a href="https://doc.rust-lang.org/std/cmp/trait.PartialOrd.html#tymethod.partial_cmp"><code>PartialOrd::partial_cmp</code></a>，对 <code>f32</code> 或 <code>f64</code> 的 vector 进行排序。</p>
<pre><pre class="playpen"><code class="language-rust">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>
<a class="header" href="#排序结构的-vector" id="排序结构的-vector"><h2>排序结构的 vector</h2></a>
<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>对 Person 结构的 Vector 进行排序，通过属性<code>name</code>和<code>age</code>的自然顺序（按名称和年龄）。为了使 Person 可排序，你需要四个 trait<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>和<a href="https://doc.rust-lang.org/std/cmp/trait.PartialOrd.html"><code>PartialOrd</code></a>。可以简单地<code>derive</code>出这些特征。您还可以使用一个<a href="https://doc.rust-lang.org/std/vec/struct.Vec.html#method.sort_by"><code>vec:sort_by</code></a>方法，提供自定义比较函数：只按年龄排序。</p>
<pre><pre class="playpen"><code class="language-rust">#[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),
    ];

    // 自然顺序，排序 people  (名字 和 年龄)
    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),
        ]);

    // 用 年龄 排序
    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 -->
<a class="header" href="#命令行-1" id="命令行-1"><h1>命令行</h1></a>
<table><thead><tr><th> 食谱                            </th><th> 箱子                            </th><th> 分类                                          </th></tr></thead><tbody>
<tr><td> <a href="cli/arguments.zh.html#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.zh.html#ansi-terminal">ANSI 终端</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 -->
<a class="header" href="#拍手clap基本" id="拍手clap基本"><h1>拍手(clap)基本</h1></a>
<a class="header" href="#解析命令行参数" id="解析命令行参数"><h2>解析命令行参数</h2></a>
<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>通过使用<code>clap</code>的构建样式，该应用程序描述了其命令行界面的结构。该<a href="https://docs.rs/clap/">文档</a>提供了，另外两种可能的方法，去实例化应用程序。</p>
<p>在构建样式中，<code>with_name</code>是唯一标识符，而<code>value_of</code>则用于检索传递的值。该<code>short</code>和<code>long</code>选项控制用户将要键入的标志; <code>short</code>标志<code>-f</code>和<code>long</code>标志<code>--file</code>是同个标志。</p>
<pre><pre class="playpen"><code class="language-rust">extern crate clap;

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><code>help</code>信息，由<code>clap</code>生成。该示例应用程序的用法，如下所示。</p>
<pre><code class="language-bash">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>我们可以通过运行如下命令，来测试应用程序。</p>
<pre><code>$ cargo run -- -f myfile.txt -n 251
</code></pre>
<p>输出是：</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 -->
<a class="header" href="#ansi-终端" id="ansi-终端"><h1>ANSI 终端</h1></a>
<a class="header" href="#ansi终端" id="ansi终端"><h2>ANSI终端</h2></a>
<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>这个程序描述了[<code>ansi_term</code>箱子]的用法，以及它是如何用于控制ANSI终端上的颜色和格式，例如，蓝色粗体文本或带黄色下划线的文本。</p>
<p>[<code>ansi_term</code>]有两个主要的数据结构：<a href="https://docs.rs/ansi_term/*/ansi_term/type.ANSIString.html"><code>ANSIString</code></a>和<a href="https://docs.rs/ansi_term/*/ansi_term/struct.Style.html"><code>Style</code></a>。一个<a href="https://docs.rs/ansi_term/*/ansi_term/struct.Style.html"><code>Style</code></a>保存风格信息：颜色，文本应该是粗体，还是闪烁，或者其他什么的。还有<code>Colour</code>变体代表简单的前景色样式。一个<a href="https://docs.rs/ansi_term/*/ansi_term/type.ANSIString.html"><code>ANSIString</code></a>是与一个<a href="https://docs.rs/ansi_term/*/ansi_term/struct.Style.html"><code>Style</code></a>配对的字符串。</p>
<p><em><em>注意：<em><em>英国英语，要使用</em>Colour</em>代替</em>Color</em>，不要混淆</p>
<a class="header" href="#将彩色文本打印到终端" id="将彩色文本打印到终端"><h3>将彩色文本打印到终端</h3></a>
<pre><pre class="playpen"><code class="language-rust">extern crate ansi_term;

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>
<a class="header" href="#终端中的粗体文字" id="终端中的粗体文字"><h3>终端中的粗体文字</h3></a>
<p>比普通前景色更改更复杂的事情，相关代码需要构造<code>Style</code>结构。用<a href="https://docs.rs/ansi_term/0.11.0/ansi_term/struct.Style.html#method.new"><code>Style::new()</code></a>创建结构，和要链接的属性。</p>
<pre><pre class="playpen"><code class="language-rust">extern crate ansi_term;

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>
<a class="header" href="#终端中的粗体和彩色文本" id="终端中的粗体和彩色文本"><h3>终端中的粗体和彩色文本</h3></a>
<p><code>Colour</code>实现了许多与<code>Style</code>类似的函数，并且可以链式方法。</p>
<pre><pre class="playpen"><code class="language-rust">extern crate ansi_term;

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 -->
<a class="header" href="#压缩-1" id="压缩-1"><h1>压缩</h1></a>
<table><thead><tr><th> 食谱                                                          </th><th> 箱子                                          </th><th> 分类                                        </th></tr></thead><tbody>
<tr><td> <a href="compression/tar.zh.html#decompress-a-tarball">解压缩 一个 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.zh.html#compress-a-directory-into-tarball">将一个目录压缩为 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.zh.html#decompress-a-tarball-while-removing-a-prefix-from-the-paths">从路径中删除前缀时，解压缩一个 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>
</tbody></table>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<a class="header" href="#使用-tarballs" id="使用-tarballs"><h1>使用 Tarballs</h1></a>
<a class="header" href="#解压缩-一个-tarball" id="解压缩-一个-tarball"><h2>解压缩 一个 tarball</h2></a>
<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>解压缩（<a href="https://docs.rs/flate2/*/flate2/read/struct.GzDecoder.html"><code>GzDecoder</code></a>）和提取（<a href="https://docs.rs/tar/*/tar/struct.Archive.html#method.unpack"><code>Archive::unpack</code></a>）当前工作目录中的压缩包<code>archive.tar.gz</code>的所有文件，并放在同一位置。</p>
<pre><pre class="playpen"><code class="language-rust no_run">extern crate flate2;
extern crate tar;

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>
<a class="header" href="#将目录压缩为一个-tarball" id="将目录压缩为一个-tarball"><h2>将目录压缩为一个 tarball</h2></a>
<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>把<code>/var/log</code>目录压缩，为<code>archive.tar.gz</code>。</p>
<p>创建一个<a href="https://doc.rust-lang.org/std/fs/struct.File.html"><code>File</code></a>，包进<a href="https://docs.rs/flate2/*/flate2/write/struct.GzEncoder.html"><code>GzEncoder</code></a>，在包入<a href="https://docs.rs/tar/*/tar/struct.Builder.html"><code>tar::Builder</code></a>。</p>
<ul>
<li>用<a href="https://docs.rs/tar/*/tar/struct.Builder.html#method.append_dir_all"><code>Builder::append_dir_all</code></a>递归添加<code>/var/log</code>目录中的内容，归档到<code>backup/logs</code>路径下。</li>
<li><a href="https://docs.rs/flate2/*/flate2/write/struct.GzEncoder.html"><code>GzEncoder</code></a>负责在数据写入<code>archive.tar.gz</code>之前，透明地压缩数据。</li>
</ul>
<pre><pre class="playpen"><code class="language-rust no_run">extern crate tar;
extern crate flate2;

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>
<a class="header" href="#从路径中删除前缀时解压缩一个-tarball" id="从路径中删除前缀时解压缩一个-tarball"><h2>从路径中删除前缀时，解压缩一个 tarball</h2></a>
<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>迭代<a href="https://docs.rs/tar/*/tar/struct.Archive.html#method.entries"><code>Archive::entries</code></a>。使用<a href="https://doc.rust-lang.org/std/path/struct.Path.html#method.strip_prefix"><code>Path::strip_prefix</code></a>删除指定的路径前缀（<code>bundle/logs</code>）。最后，通过<a href="https://docs.rs/tar/*/tar/struct.Entry.html#method.unpack"><code>Entry::unpack</code></a>，提取出<a href="https://docs.rs/tar/*/tar/struct.Entry.html"><code>tar::Entry</code></a> - 压缩中的项。</p>
<pre><pre class="playpen"><code class="language-rust no_run"># #[macro_use]
# extern crate error_chain;
extern crate flate2;
extern crate tar;

use std::fs::File;
use std::path::PathBuf;
use flate2::read::GzDecoder;
use tar::Archive;
#
# error_chain! {
#   foreign_links {
#     Io(std::io::Error);
#     StripPrefixError(::std::path::StripPrefixError);
#   }
# }

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 -->
<a class="header" href="#并发性-1" id="并发性-1"><h1>并发性</h1></a>
<table><thead><tr><th> 食谱                                                                   </th><th> 箱子                                                                                                              </th><th> 类别                                                                                                                  </th></tr></thead><tbody>
<tr><td> <a href="concurrency/threads.zh.html#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.zh.html#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.zh.html#calculate-sha1-sum-of-iso-files-concurrently">并发计算所有 <code>*.iso</code> 文件的 SHA1 和</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.zh.html#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.zh.html#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.zh.html#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.zh.html#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.zh.html#sort-a-vector-in-parallel">并行，排序 vector</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.zh.html#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.zh.html#generate-jpg-thumbnails-in-parallel">并行，生成 JPG 缩略图</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 -->
<a class="header" href="#线程" id="线程"><h1>线程</h1></a>
<a class="header" href="#生成一个短命的线程" id="生成一个短命的线程"><h2>生成一个短命的线程</h2></a>
<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>该示例使用了<a href="https://docs.rs/crossbeam/">crossbeam</a>箱子，为并发和并行编程，提供数据结构和函数。<a href="https://docs.rs/crossbeam/*/crossbeam/thread/struct.Scope.html#method.spawn"><code>Scope::spawn</code></a>生成一个新的作用域线程，保证<a href="https://docs.rs/crossbeam/*/crossbeam/fn.scope.html"><code>crossbeam::scope</code></a>函数的闭包(参数)返回之前终止，意味着，您可以从调用的函数中，引用数据。</p>
<p>此示例将数组拆分为一半，并在单独的线程中，执行工作。</p>
<pre><pre class="playpen"><code class="language-rust">extern crate crossbeam;

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 min_l = thread_l.join().unwrap()?;
        let min_r = thread_r.join().unwrap()?;

        Some(min_l.max(min_r))
    }).unwrap()
}
</code></pre></pre>
<a class="header" href="#保持全球可变状态" id="保持全球可变状态"><h2>保持全球可变状态</h2></a>
<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>使用<a href="https://docs.rs/lazy_static/">lazy_static</a>声明全局状态。<a href="https://docs.rs/lazy_static/">lazy_static</a>创建一个全局可用<code>static ref</code>，这需要一个<a href="https://doc.rust-lang.org/std/sync/struct.Mutex.html"><code>Mutex</code></a>，来决定可变许可（也参见<a href="https://doc.rust-lang.org/std/sync/struct.RwLock.html"><code>RwLock</code></a>）。受<a href="https://doc.rust-lang.org/std/sync/struct.Mutex.html"><code>Mutex</code></a>包裹，能确保多个线程，不能同时访问（<code>FRUIT</code>）状态，从而防止竞争条件。必须获取一个<a href="https://doc.rust-lang.org/std/sync/struct.MutexGuard.html"><code>MutexGuard</code></a>，才能读取或改变存储在<a href="https://doc.rust-lang.org/std/sync/struct.Mutex.html"><code>Mutex</code></a>中的值。</p>
<pre><pre class="playpen"><code class="language-rust"># #[macro_use]
# extern crate error_chain;
#[macro_use]
extern crate lazy_static;

use std::sync::Mutex;
#
# error_chain!{ }

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 run() -&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(())
}
#
# quick_main!(run);
</code></pre></pre>
<a class="header" href="#并发计算所有-iso-文件的-sha1-和" id="并发计算所有-iso-文件的-sha1-和"><h2>并发计算，所有 iso 文件的 SHA1 和</h2></a>
<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>本示例：对当前目录中，具有 ISO 扩展名的每个文件，合计它们的 SHA1。线程池生成的线程数，等于系统(CPU)核心数，这个能通过<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>迭代当前目录，并调用<a href="https://docs.rs/threadpool/*/threadpool/struct.ThreadPool.html#method.execute"><code>execute</code></a>执行读取和计算 SHA1 哈希的操作。</p>
<pre><pre class="playpen"><code class="language-rust no_run">extern crate walkdir;
extern crate ring;
extern crate num_cpus;
extern crate threadpool;

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, SHA1};

# // Verify the iso extension
# fn is_iso(entry: &amp;Path) -&gt; bool {
#     match entry.extension() {
#         Some(e) if e.to_string_lossy().to_lowercase() == &quot;iso&quot; =&gt; true,
#         _ =&gt; false,
#     }
# }

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;SHA1);
    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>
<a class="header" href="#将绘制分形工作分派到线程池" id="将绘制分形工作分派到线程池"><h2>将绘制分形工作，分派到线程池</h2></a>
<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>本示例：绘制[朱利亚集合]的一个分形，生成一个图像，会用到分布式计算的线程池。</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>通过<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>计算 RGB 像素值。创建<a href="https://docs.rs/threadpool/*/threadpool/struct.ThreadPool.html"><code>ThreadPool</code></a>线程数，等于<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>收到的每个像素，都作为一个单独的工作。</p>
<p><a href="https://doc.rust-lang.org/std/sync/mpsc/fn.channel.html"><code>mpsc::channel</code></a>收到工作，还有<a href="https://doc.rust-lang.org/std/sync/mpsc/struct.Receiver.html#method.recv"><code>Receiver::recv</code></a>会检索它们。<a href="https://docs.rs/image/*/image/struct.ImageBuffer.html#method.put_pixel"><code>ImageBuffer::put_pixel</code></a>使用数据，设置像素颜色。<a href="https://docs.rs/image/*/image/struct.ImageBuffer.html#method.save"><code>ImageBuffer::save</code></a>就将图像写入<code>output.png</code>。</p>
<pre><pre class="playpen"><code class="language-rust no_run"># #[macro_use]
# extern crate error_chain;
extern crate threadpool;
extern crate num;
extern crate num_cpus;
extern crate image;

use std::sync::mpsc::{channel, RecvError};
use threadpool::ThreadPool;
use num::complex::Complex;
use image::{ImageBuffer, Pixel, Rgb};
#
# error_chain! {
#     foreign_links {
#         MpscRecv(RecvError);
#         Io(std::io::Error);
#     }
# }
#
# // Function converting intensity values to RGB
# // Based on http://www.efg2.com/Lab/ScienceAndEngineering/Spectra.htm
# fn wavelength_to_rgb(wavelength: u32) -&gt; Rgb&lt;u8&gt; {
#     let wave = wavelength as f32;
#
#     let (r, g, b) = match wavelength {
#         380...439 =&gt; ((440. - wave)/(440. - 380.), 0.0, 1.0),
#         440...489 =&gt; (0.0, (wave - 440.)/(490. - 440.), 1.0),
#         490...509 =&gt; (0.0, 1.0, (510. - wave)/(510. - 490.)),
#         510...579 =&gt; ((wave - 510.)/(580. - 510.), 1.0, 0.0),
#         580...644 =&gt; (1.0, (645. - wave)/(645. - 580.), 0.0),
#         645...780 =&gt; (1.0, 0.0, 0.0),
#         _ =&gt; (0.0, 0.0, 0.0),
#     };
#
#     let factor = match wavelength {
#         380...419 =&gt; 0.3 + 0.7 * (wave - 380.)/(420. - 380.),
#         701...780 =&gt; 0.3 + 0.7 * (780. - wave)/(780. - 700.),
#         _ =&gt; 1.0,
#     };
#
#     let (r, g, b) = (normalize(r, factor), normalize(g, factor), normalize(b, factor));
#     Rgb::from_channels(r, g, b, 0)
# }
#
# // Maps Julia set distance estimation to intensity values
# fn julia(c: Complex&lt;f32&gt;, x: u32, y: u32, width: u32, height: u32, max_iter: u32) -&gt; u32 {
#     let width = width as f32;
#     let height = height as f32;
#
#     let mut z = Complex {
#         // scale and translate the point to image coordinates
#         re: 3.0 * (x as f32 - 0.5 * width)/width,
#         im: 2.0 * (y as f32 - 0.5 * height)/height,
#     };
#
#     let mut i = 0;
#     for t in 0..max_iter {
#         if z.norm() &gt;= 2.0 {
#             break;
#         }
#         z = z * z + c;
#         i = t;
#     }
#     i
# }
#
# // Normalizes color intensity values within RGB range
# fn normalize(color: f32, factor: f32) -&gt; u8 {
#     ((color * factor).powf(0.8) * 255.) as u8
# }

fn run() -&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(())
}
#
# quick_main!(run);
</code></pre></pre>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<a class="header" href="#并行任务" id="并行任务"><h1>并行任务</h1></a>
<a class="header" href="#并行变换数组的元素" id="并行变换数组的元素"><h2>并行，变换数组的元素</h2></a>
<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>该示例使用了<code>rayon</code>箱子，这是 Rust 的数据并行库。<code>rayon</code>提供了<a href="https://docs.rs/rayon/*/rayon/iter/trait.IntoParallelRefMutIterator.html#tymethod.par_iter_mut"><code>par_iter_mut</code></a>方法，给任何的并行可迭代数据类型使用。这是一个类似迭代器的链，(潜在地)并行执行。</p>
<pre><pre class="playpen"><code class="language-rust">extern crate rayon;

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>
<a class="header" href="#并行测试集合的任何或所有元素是否与给定断言匹配" id="并行测试集合的任何或所有元素是否与给定断言匹配"><h2>并行测试，集合的任何或所有元素是否与给定断言匹配</h2></a>
<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>这个例子演示了如何使用<a href="https://docs.rs/rayon/*/rayon/iter/trait.ParallelIterator.html#method.any"><code>rayon::any</code></a>和<a href="https://docs.rs/rayon/*/rayon/iter/trait.ParallelIterator.html#method.all"><code>rayon::all</code></a>方法，是与<a href="https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.any"><code>std::any</code></a>和<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>并行检查迭代器的任何元素，是否与断言匹配，并在找到一个元素后立即返回。<a href="https://docs.rs/rayon/*/rayon/iter/trait.ParallelIterator.html#method.all"><code>rayon::all</code></a>并行检查迭代器的所有元素，是否与断言匹配，并在找到非匹配元素后，立即返回。</p>
<pre><pre class="playpen"><code class="language-rust">extern crate rayon;

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>
<a class="header" href="#使用给定断言并行搜索项目" id="使用给定断言并行搜索项目"><h2>使用给定断言，并行搜索项目</h2></a>
<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>这个例子使用<a href="https://docs.rs/rayon/*/rayon/iter/trait.ParallelIterator.html#method.find_any"><code>rayon::find_any</code></a>和<a href="https://docs.rs/rayon/*/rayon/iter/trait.IntoParallelRefIterator.html#tymethod.par_iter"><code>par_iter</code></a>获得一个，通过并行搜索，满足给定闭包中断言的元素 vector。</p>
<p>如果，有多个元素满足<a href="https://docs.rs/rayon/*/rayon/iter/trait.ParallelIterator.html#method.find_any"><code>rayon::find_any</code></a>闭包参数中，定义的断言，<code>rayon</code>返回找到的第一个，但不一定是(顺序上的)第一个。</p>
<p>另请注意，闭包的参数是对一个引用的一个引用（<code>&amp;&amp;x</code>）。请查阅<a href="https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.find"><code>std::find</code></a>的讨论，了解更多细节。</p>
<pre><pre class="playpen"><code class="language-rust">extern crate rayon;

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>
<a class="header" href="#并行排序-vector" id="并行排序-vector"><h2>并行，排序 vector</h2></a>
<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>此示例：并行排序字符串 vector。</p>
<p>分配一个空字符串的 vector。<code>par_iter_mut().for_each</code>会并发填充随机值。虽然存在<a href="https://docs.rs/rayon/*/rayon/slice/trait.ParallelSliceMut.html">多种选择</a>，可以对可枚举数据类型进行排序，<a href="https://docs.rs/rayon/*/rayon/slice/trait.ParallelSliceMut.html#method.par_sort_unstable"><code>par_sort_unstable</code></a>通常比<a href="https://docs.rs/rayon/*/rayon/slice/trait.ParallelSliceMut.html#method.par_sort">稳定排序</a>算法快。</p>
<pre><pre class="playpen"><code class="language-rust">extern crate rand;
extern crate rayon;

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>
<a class="header" href="#map-reduce-并行" id="map-reduce-并行"><h2>Map-reduce 并行</h2></a>
<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>这个例子使用<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>，和<a href="https://docs.rs/rayon/*/rayon/iter/trait.ParallelIterator.html#method.reduce"><code>rayon::reduce</code></a>，计算<code>Person</code>对象的平均年龄，哪个年龄超过 30 。</p>
<p><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>对每个元素执行一个操作，创建一个新的迭代，然后<a href="https://docs.rs/rayon/*/rayon/iter/trait.ParallelIterator.html#method.reduce"><code>rayon::reduce</code></a>：执行带有一个当前元素，和前一个(执行结果)的操作。还显示了使用<a href="https://docs.rs/rayon/*/rayon/iter/trait.ParallelIterator.html#method.sum"><code>rayon::sum</code></a>，与本例中的 reduce 操作，具有相同的结果。</p>
<pre><pre class="playpen"><code class="language-rust">extern crate rayon;

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>
<a class="header" href="#并行生成-jpg-缩略图" id="并行生成-jpg-缩略图"><h2>并行，生成 jpg 缩略图</h2></a>
<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>此示例：帮当前目录中的所有<code>.jpg</code> 文件生成缩略图，然后将其保存在名为<code>thumbnails</code>的新文件夹中。</p>
<p><a href="https://docs.rs/glob/*/glob/fn.glob_with.html"><code>glob::glob_with</code></a>在当前目录中，查找 jpeg 文件。<code>rayon</code>使用<a href="https://docs.rs/rayon/*/rayon/iter/trait.IntoParallelRefIterator.html#tymethod.par_iter"><code>par_iter</code></a>，并发调整图像大小，每次都调用<a href="https://docs.rs/image/*/image/enum.DynamicImage.html#method.resize"><code>DynamicImage::resize</code></a>。</p>
<pre><pre class="playpen"><code class="language-rust no_run"># #[macro_use]
# extern crate error_chain;
extern crate glob;
extern crate image;
extern crate rayon;

use std::path::Path;
use std::fs::create_dir_all;

# use error_chain::ChainedError;
use glob::{glob_with, MatchOptions};
use image::{FilterType, ImageError};
use rayon::prelude::*;

# error_chain! {
#     foreign_links {
#         Image(ImageError);
#         Io(std::io::Error);
#         Glob(glob::PatternError);
#     }
# }

fn run() -&gt; Result&lt;()&gt; {
    let options: MatchOptions = Default::default();
    let files: Vec&lt;_&gt; = glob_with(&quot;*.jpg&quot;, &amp;options)?
        .filter_map(|x| x.ok())
        .collect();

    if files.len() == 0 {
        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)?)
}
#
# quick_main!(run);
</code></pre></pre>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<a class="header" href="#密码学-1" id="密码学-1"><h1>密码学</h1></a>
<table><thead><tr><th> 食谱                                                        </th><th> 箱子                                                          </th><th> 类别                                          </th></tr></thead><tbody>
<tr><td> <a href="cryptography/hashing.zh.html#calculate-the-sha-256-digest-of-a-file">计算文件的 SHA-256 码</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.zh.html#sign-and-verify-a-message-with-hmac-digest">使用 HMAC 码，签名并验证消息</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.zh.html#salt-and-hash-a-password-with-pbkdf2">用 PBKDF2 对密码，进行 加盐(Salt) 和 哈希 操作</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 -->
<a class="header" href="#哈希" id="哈希"><h1>哈希</h1></a>
<a class="header" href="#计算文件的-sha-256-码" id="计算文件的-sha-256-码"><h2>计算文件的 SHA-256 码</h2></a>
<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>将一些数据写入文件，然后获得文件的内容，再用使用<a href="https://briansmith.org/rustdoc/ring/digest/struct.Context.html"><code>digest::Context</code></a>，<a href="https://briansmith.org/rustdoc/ring/digest/struct.Digest.html"><code>digest::Digest</code></a>计算 SHA-256 码。</p>
<pre><pre class="playpen"><code class="language-rust"># #[macro_use]
# extern crate error_chain;
extern crate data_encoding;
extern crate ring;

use data_encoding::HEXUPPER;
use ring::digest::{Context, Digest, SHA256};
use std::fs::File;
use std::io::{BufReader, Read, Write};
#
# error_chain! {
#     foreign_links {
#         Io(std::io::Error);
#         Decode(data_encoding::DecodeError);
#     }
# }

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 run() -&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(())
}
#
# quick_main!(run);
</code></pre></pre>
<a class="header" href="#与-hmac-码签署并验证消息" id="与-hmac-码签署并验证消息"><h2>与 HMAC 码，签署并验证消息</h2></a>
<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>使用<a href="https://briansmith.org/rustdoc/ring/hmac/"><code>ring::hmac</code></a>创建一个<a href="https://briansmith.org/rustdoc/ring/hmac/struct.Signature.html"><code>hmac::Signature</code></a>，然后验证签名是否正确。</p>
<pre><pre class="playpen"><code class="language-rust">extern crate ring;

use ring::{digest, 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::SigningKey::new(&amp;digest::SHA256, &amp;key_value);

    let message = &quot;Legitimate and important message.&quot;;
    let signature = hmac::sign(&amp;key, message.as_bytes());
    hmac::verify_with_own_key(&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 -->
<a class="header" href="#加密" id="加密"><h1>加密</h1></a>
<p><a name="ex-pbkdf2"></a></p>
<a class="header" href="#用-pbkdf2-对密码进行-加盐-和-哈希-操作" id="用-pbkdf2-对密码进行-加盐-和-哈希-操作"><h2>用 PBKDF2 对密码，进行 加盐 和 哈希 操作</h2></a>
<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><a href="https://briansmith.org/rustdoc/ring/pbkdf2/index.html"><code>ring::pbkdf2</code></a>的用法是，使用 PBKDF2 密钥派生函数<a href="https://briansmith.org/rustdoc/ring/pbkdf2/fn.derive.html"><code>pbkdf2::derive</code></a>，哈希 腌制的密码。 用<a href="https://briansmith.org/rustdoc/ring/pbkdf2/fn.verify.html"><code>pbkdf2::verify</code></a>验证哈希是否正确。 盐是用<a href="https://briansmith.org/rustdoc/ring/rand/trait.SecureRandom.html#tymethod.fill"><code>SecureRandom::fill</code></a>生成的，它用安全生成的随机数，填充 salt 字节数组。</p>
<blockquote>
<p>这个在哈希中加入字符串的方式称为“加盐”。其作用是让加盐后的哈希结果和没有加盐的结果不相同，在不同的应用情景中，这个处理可以增加额外的安全性。</p>
</blockquote>
<pre><pre class="playpen"><code class="language-rust">extern crate ring;
extern crate data_encoding;

use data_encoding::HEXUPPER;
use ring::error::Unspecified;
use ring::rand::SecureRandom;
use ring::{digest, pbkdf2, rand};

fn main() -&gt; Result&lt;(), Unspecified&gt; {
    const CREDENTIAL_LEN: usize = digest::SHA512_OUTPUT_LEN;
    const N_ITER: u32 = 100_000;
    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(
        &amp;digest::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(
        &amp;digest::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(
        &amp;digest::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 -->
<a class="header" href="#数据结构-1" id="数据结构-1"><h1>数据结构</h1></a>
<table><thead><tr><th> 食谱                                          </th><th> 箱子                          </th><th> 类别                              </th></tr></thead><tbody>
<tr><td> <a href="data_structures/bitfield.zh.html#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 -->
<a class="header" href="#自定义" id="自定义"><h1>自定义</h1></a>
<a class="header" href="#定义表示为位字段的类型并操作" id="定义表示为位字段的类型并操作"><h2>定义表示为位字段的类型，并操作</h2></a>
<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>创建，类型安全位字段的类型<code>MyFlags</code>，这是借助于<a href="https://docs.rs/bitflags/*/bitflags/macro.bitflags.html"><code>bitflags!</code></a>宏，和实现元素的<code>clear</code>操作，还有<a href="https://doc.rust-lang.org/std/fmt/trait.Display.html"><code>Display</code></a>。随后，显示基本的位操作和格式设置。</p>
<pre><pre class="playpen"><code class="language-rust">#[macro_use]
extern crate 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 -->
<a class="header" href="#数据库-1" id="数据库-1"><h1>数据库</h1></a>
<table><thead><tr><th> 食谱                                                      </th><th> 箱子                          </th><th> 类别                                  </th></tr></thead><tbody>
<tr><td> <a href="database/sqlite.zh.html#create-a-sqlite-database">创建 sqlite 数据库</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.zh.html#insert-and-select-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.zh.html#create-tables-in-a-postgres-database">在 Postgres 数据库中，创建表</a> </td><td> [![postgres-badge]][postgres] </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.zh.html#insert-and-query-data">插入和查询数据</a>           </td><td> [![postgres-badge]][postgres] </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.zh.html#aggregate-data">综合数据</a>                    </td><td> [![postgres-badge]][postgres] </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 -->
<a class="header" href="#数据库-2" id="数据库-2"><h1>数据库</h1></a>
<a class="header" href="#创建-sqlite-数据库" id="创建-sqlite-数据库"><h2>创建 sqlite 数据库</h2></a>
<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>使用<code>rusqlite</code>箱子，打开 sqlite 数据库。见<a href="https://github.com/jgallagher/rusqlite#user-content-notes-on-building-rusqlite-and-libsqlite3-sys">箱子文档</a>中 Windows 的编译。</p>
<p><a href="https://docs.rs/rusqlite/*/rusqlite/struct.Connection.html#method.open"><code>Connection::open</code></a>：如果数据库不存在，将创建该数据库。</p>
<pre><pre class="playpen"><code class="language-rust no_run">extern crate rusqlite;

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>
<a class="header" href="#插入并查询数据" id="插入并查询数据"><h2>插入并查询数据</h2></a>
<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>将打开在早期食谱中，创建的数据库<code>cats</code>。此食谱将数据插入到<code>cat_colors</code>，还有和<code>cats</code>表用到<code>Connection</code>的<a href="https://docs.rs/rusqlite/*/rusqlite/struct.Connection.html#method.execute"><code>execute</code></a>方法。 首先，将数据插入<code>cat_colors</code>表。插入颜色(color)记录后，<code>Connection</code>的<a href="https://docs.rs/rusqlite/*/rusqlite/struct.Connection.html#method.last_insert_rowid"><code>last_insert_rowid</code></a>方法，能获取最后插入(color)的<code>id</code>。这个<code>id</code>能用来，把数据插入到<code>cats</code>表。然后，使用<a href="https://docs.rs/rusqlite/*/rusqlite/struct.Connection.html#method.prepare"><code>prepare</code></a>方法准备查询，它会返回<a href="https://docs.rs/rusqlite/*/rusqlite/struct.Statement.html"><code>statement</code></a>结构。然后，再使用<a href="https://docs.rs/rusqlite/*/rusqlite/struct.Statement.html"><code>statement</code></a>的<a href="https://docs.rs/rusqlite/*/rusqlite/struct.Statement.html#method.query_map"><code>query_map</code></a>方法（进行查询）.</p>
<pre><pre class="playpen"><code class="language-rust">extern crate rusqlite;

use rusqlite::{Connection, Result};
use rusqlite::NO_PARAMS;
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>
<a class="header" href="#使用事务" id="使用事务"><h2>使用事务</h2></a>
<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>将打开<code>cats.db</code> —— 来自之前食谱的数据库。</p>
<p>用<a href="https://docs.rs/rusqlite/*/rusqlite/struct.Connection.html#method.transaction"><code>Connection::transaction</code></a>开始一个事务（transaction）。事务将回滚，除非明确使用<a href="https://docs.rs/rusqlite/*/rusqlite/struct.Transaction.html#method.commit"><code>Transaction::commit</code></a>提交。</p>
<blockquote>
<p>一次事务，就是一系列对数据库的操作，且明确<code>commit</code>后才会执行。</p>
</blockquote>
<p>在下面的示例中，将颜色添加表，该表对颜色名称要唯一，进行约束。当尝试插入重复的颜色时，事务将回滚。</p>
<pre><pre class="playpen"><code class="language-rust no_run">extern crate rusqlite;

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 -->
<a class="header" href="#与-postgres-合作" id="与-postgres-合作"><h1>与 Postgres 合作</h1></a>
<a class="header" href="#在-postgres-数据库中创建表" id="在-postgres-数据库中创建表"><h2>在 Postgres 数据库中，创建表</h2></a>
<p>[![postgres-badge]][postgres] <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/postgres/0.15.2/postgres/"><code>postgres</code></a>在 Postgres 数据库中，创建表。</p>
<p><a href="https://docs.rs/postgres/0.15.2/postgres/struct.Connection.html#method.connect"><code>Connection::connect</code></a>帮助连接到现有数据库。该食谱的<code>Connection::connect</code>使用一个 URL 字符串格式。 它假定一个名为<code>library</code>，用户名是<code>postgres</code>，密码是<code>postgres</code>.</p>
<pre><pre class="playpen"><code class="language-rust no_run">extern crate postgres;

use postgres::{Connection, TlsMode, Error};

fn main() -&gt; Result&lt;(), Error&gt; {
    let conn = Connection::connect(&quot;postgresql://postgres:postgres@localhost/library&quot;,
                                    TlsMode::None)?;

     conn.execute(&quot;CREATE TABLE IF NOT EXISTS author (
                    id              SERIAL PRIMARY KEY,
                    name            VARCHAR NOT NULL,
                    country         VARCHAR NOT NULL
                  )&quot;, &amp;[])?;

    conn.execute(&quot;CREATE TABLE IF NOT EXISTS book  (
                    id              SERIAL PRIMARY KEY,
                    title           VARCHAR NOT NULL,
                    author_id       INTEGER NOT NULL REFERENCES author
                )&quot;, &amp;[])?;

    Ok(())

}
</code></pre></pre>
<a class="header" href="#插入和查询数据" id="插入和查询数据"><h2>插入和查询数据</h2></a>
<p>[![postgres-badge]][postgres] <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>该食谱，用<code>Connection</code>的<a href="https://docs.rs/postgres/0.15.2/postgres/struct.Connection.html#method.execute"><code>execute</code></a>方法，将数据插入<code>author</code>表。 然后，用<code>Connection</code>的<a href="https://docs.rs/postgres/0.15.2/postgres/struct.Connection.html#method.query"><code>query</code></a>方法，显示<code>author</code>表。</p>
<pre><pre class="playpen"><code class="language-rust no_run">extern crate postgres;

use postgres::{Connection, TlsMode, Error};
use std::collections::HashMap;

struct Author {
    id: i32,
    name: String,
    country: String
}

fn main() -&gt; Result&lt;(), Error&gt; {
    let conn = Connection::connect(&quot;postgresql://postgres:postgres@localhost/library&quot;,
                                    TlsMode::None)?;

    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()
        };

        conn.execute(&quot;INSERT INTO author (name, country) VALUES ($1, $2)&quot;,
                 &amp;[&amp;author.name, &amp;author.country])?;
    }

    for row in &amp;conn.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>
<a class="header" href="#汇总数据" id="汇总数据"><h2>汇总数据</h2></a>
<p>[![postgres-badge]][postgres] <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://github.com/MuseumofModernArt/collection/blob/master/Artists.csv">现代艺术博物馆</a>的前 7999 名艺术家的国籍，按降序排列。</p>
<pre><pre class="playpen"><code class="language-rust no_run">extern crate postgres;
use postgres::{Connection, Error, TlsMode};

struct Nation {
    nationality: String,
    count: i64,
}

fn main() -&gt; Result&lt;(), Error&gt; {
    let conn = Connection::connect(
        &quot;postgresql://postgres:postgres@127.0.0.1/moma&quot;,
        TlsMode::None,
    )?;

    for row in &amp;conn.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 -->
<a class="header" href="#日期和时间-1" id="日期和时间-1"><h1>日期和时间</h1></a>
<table><thead><tr><th> 食谱                                                              </th><th> 箱子                      </th><th> 类别                                            </th></tr></thead><tbody>
<tr><td> <a href="datetime/duration.zh.html#measure-the-elapsed-time-between-two-code-sections">测量已用时间</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.zh.html#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.zh.html#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.zh.html#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.zh.html#convert-date-to-unix-timestamp-and-vice-versa">将日期转换为 Unix 时间戳，或相反</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.zh.html#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.zh.html#parse-string-into-datetime-struct">将字符串解析为 DateTime 结构</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 -->
<a class="header" href="#持续时间和计算" id="持续时间和计算"><h1>持续时间和计算</h1></a>
<a class="header" href="#measure-the-elapsed-time-between-two-code-sections" id="measure-the-elapsed-time-between-two-code-sections"><h2>Measure the elapsed time between two code sections</h2></a>
<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="playpen"><code class="language-rust">use std::time::{Duration, Instant};
# use std::thread;
#
# fn expensive_function() {
#     thread::sleep(Duration::from_secs(1));
# }

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>
<a class="header" href="#perform-checked-date-and-time-calculations" id="perform-checked-date-and-time-calculations"><h2>Perform checked date and time calculations</h2></a>
<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="playpen"><code class="language-rust">extern crate chrono;
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>
<a class="header" href="#convert-a-local-time-to-another-timezone" id="convert-a-local-time-to-another-timezone"><h2>Convert a local time to another timezone</h2></a>
<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="playpen"><code class="language-rust">extern crate chrono;

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 -->
<a class="header" href="#解析和显示" id="解析和显示"><h1>解析和显示</h1></a>
<a class="header" href="#检查日期和时间" id="检查日期和时间"><h2>检查日期和时间</h2></a>
<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><a href="https://docs.rs/chrono/*/chrono/struct.DateTime.html"><code>DateTime</code></a>获取当前的 UTC，还有<a href="https://docs.rs/chrono/*/chrono/trait.Timelike.html"><code>Timelike</code></a>，能得到它的小时/分钟/秒（hour/minute/second），通过<a href="https://docs.rs/chrono/*/chrono/trait.Datelike.html"><code>Datelike</code></a>，则能获得它的年/月/日/周末（year/month/day/weekday）。</p>
<pre><pre class="playpen"><code class="language-rust">extern crate chrono;
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>
<a class="header" href="#将日期转换为-unix-时间戳反之亦然" id="将日期转换为-unix-时间戳反之亦然"><h2>将日期转换为 Unix 时间戳，反之亦然</h2></a>
<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><a href="https://docs.rs/chrono/*/chrono/naive/struct.NaiveDate.html#method.from_ymd"><code>NaiveDate::from_ymd</code></a>和<a href="https://docs.rs/chrono/*/chrono/naive/struct.NaiveTime.html#method.from_hms"><code>NaiveTime::from_hms</code></a>给出一个日期，用<a href="https://docs.rs/chrono/*/chrono/naive/struct.NaiveDateTime.html#method.timestamp"><code>NaiveDateTime::timestamp</code></a>转换到<a href="https://en.wikipedia.org/wiki/Unix_time">UNIX 时间戳</a>。然后使用<a href="https://docs.rs/chrono/*/chrono/naive/struct.NaiveDateTime.html#method.from_timestamp"><code>NaiveDateTime::from_timestamp</code></a>，它计算从 1970 1，01 0:00:00 UTC 开始，10 亿秒后的日期。</p>
<pre><pre class="playpen"><code class="language-rust">extern crate chrono;

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>
<a class="header" href="#显示格式化的日期和时间" id="显示格式化的日期和时间"><h2>显示格式化的日期和时间</h2></a>
<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>使用<a href="https://docs.rs/chrono/*/chrono/offset/struct.Utc.html#method.now"><code>Utc::now</code></a>，获取并显示当前时间（以 UTC 为单位）。以众所周知的格式<a href="https://www.ietf.org/rfc/rfc2822.txt">RFC 2822</a>，格式化当前时间，通过<a href="https://docs.rs/chrono/*/chrono/struct.DateTime.html#method.to_rfc2822"><code>DateTime::to_rfc2822</code></a>。还有<a href="https://www.ietf.org/rfc/rfc3339.txt">RFC 3339</a>格式，可以使用<a href="https://docs.rs/chrono/*/chrono/struct.DateTime.html#method.to_rfc3339"><code>DateTime::to_rfc3339</code></a>，除此之外，用<a href="https://docs.rs/chrono/*/chrono/struct.DateTime.html#method.format"><code>DateTime::format</code></a>可以自定义格式。</p>
<pre><pre class="playpen"><code class="language-rust">extern crate chrono;
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>
<a class="header" href="#将字符串解析为-datetime-结构" id="将字符串解析为-datetime-结构"><h2>将字符串解析为 datetime 结构</h2></a>
<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>解析已知的字符串表达格式<a href="https://www.ietf.org/rfc/rfc2822.txt">RFC 2822</a>，<a href="https://www.ietf.org/rfc/rfc3339.txt">RFC 3339</a>和自定义格式，将其变为一个<a href="https://docs.rs/chrono/*/chrono/struct.DateTime.html"><code>DateTime</code></a>结构，可以分别使用<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>和<a href="https://docs.rs/chrono/*/chrono/struct.DateTime.html#method.parse_from_str"><code>DateTime::parse_from_str</code></a>。</p>
<p>可以在<a href="https://docs.rs/chrono/*/chrono/format/strftime/index.html"><code>chrono::format::strftime</code></a>找到，转义序列，让其可用于<a href="https://docs.rs/chrono/*/chrono/struct.DateTime.html#method.format"><code>DateTime::format</code></a>。 请注意<a href="https://docs.rs/chrono/*/chrono/struct.DateTime.html#method.parse_from_str"><code>DateTime::parse_from_str</code></a>要求一个 DateTime 结构，必须是创建的，唯一标识的日期和时间。请使用<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>和<a href="https://docs.rs/chrono/*/chrono/naive/struct.NaiveDateTime.html"><code>NaiveDateTime</code></a>，分析没有时区的日期和时间。</p>
<pre><pre class="playpen"><code class="language-rust">extern crate chrono;
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 -->
<a class="header" href="#开发工具-1" id="开发工具-1"><h1>开发工具</h1></a>
<a class="header" href="#调试-1" id="调试-1"><h2>调试</h2></a>
<table><thead><tr><th> 食谱                                                    </th><th> 箱子                                                                            </th><th> 类别                                    </th></tr></thead><tbody>
<tr><td> <a href="development_tools/debugging/log.zh.html#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.zh.html#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.zh.html#log-to-stdout-instead-of-stderr">记录到 stdout ，而不是 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.zh.html#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.zh.html#log-to-the-unix-syslog">记录到 Unix 系统日志</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.zh.html#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.zh.html#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.zh.html#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.zh.html#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 -->
<a class="header" href="#版本控制-1" id="版本控制-1"><h2>版本控制</h2></a>
<table><thead><tr><th> 食谱                                                   </th><th> 箱子                      </th><th> 类别                                                                          </th></tr></thead><tbody>
<tr><td> <a href="development_tools/versioning.zh.html#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.zh.html#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.zh.html#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.zh.html#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.zh.html#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>
<a class="header" href="#构建时-1" id="构建时-1"><h2>构建时</h2></a>
<table><thead><tr><th> 食谱                                                   </th><th> 箱子              </th><th> 类别                                                    </th></tr></thead><tbody>
<tr><td> <a href="development_tools/build_tools.zh.html#compile-and-link-statically-to-a-bundled-c-library">静态编译，并链接到捆绑的 C 库</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.zh.html#compile-and-link-statically-to-a-bundled-c-library-1">编译，并链接到捆绑的 C++库</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.zh.html#compile-a-c-library-while-setting-custom-defines">自定义设置时，编译 C 库</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 -->
<a class="header" href="#调试-2" id="调试-2"><h2>调试</h2></a>
<table><thead><tr><th> 食谱                                                    </th><th> 箱子                                                                            </th><th> 类别                                    </th></tr></thead><tbody>
<tr><td> <a href="development_tools/debugging/log.zh.html#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.zh.html#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.zh.html#log-to-stdout-instead-of-stderr">记录到 stdout ，而不是 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.zh.html#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.zh.html#log-to-the-unix-syslog">记录到 Unix 系统日志</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.zh.html#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.zh.html#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.zh.html#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.zh.html#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 -->
<a class="header" href="#日志消息" id="日志消息"><h1>日志消息</h1></a>
<a class="header" href="#将调试消息记录到控制台" id="将调试消息记录到控制台"><h2>将调试消息，记录到控制台</h2></a>
<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>这个<code>log</code>箱子提供记录工具。这个<code>env_logger</code>箱子能通过环境变量，配置日志记录。这个<a href="https://docs.rs/log/*/log/macro.debug.html"><code>debug!</code></a>宏的工作，与其他<a href="https://doc.rust-lang.org/std/fmt/"><code>std::fmt</code></a>格式化字符串一样。</p>
<pre><pre class="playpen"><code class="language-rust">#[macro_use]
extern crate log;
extern crate env_logger;

fn execute_query(query: &amp;str) {
    debug!(&quot;Executing query: {}&quot;, query);
}

fn main() {
    env_logger::init();

    execute_query(&quot;DROP TABLE students&quot;);
}
</code></pre></pre>
<p>运行此代码时，没有输出。默认情况下，日志级别为<code>error</code>，任何低于此的级别，都将被删除。</p>
<p>设置打印消息的<code>RUST_LOG</code>环境变量：</p>
<pre><code>$ RUST_LOG=debug cargo run
</code></pre>
<p>货物(cargo)打印调试信息，然后在输出的最后一行，打印以下内容：</p>
<pre><code>DEBUG:main: Executing query: DROP TABLE students
</code></pre>
<a class="header" href="#将错误消息记录到控制台" id="将错误消息记录到控制台"><h2>将错误消息，记录到控制台</h2></a>
<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>正确的错误处理，会异常情况，视为错误。此处，<code>log</code>的方便宏<a href="https://docs.rs/log/*/log/macro.error.html"><code>error!</code></a>，把错误日志记录到 stderr。</p>
<pre><pre class="playpen"><code class="language-rust">#[macro_use]
extern crate log;
extern crate env_logger;

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 {
        error!(&quot;Failed to execute query: {}&quot;, err);
    }
}
</code></pre></pre>
<a class="header" href="#登录到-stdout-而不是-stderr" id="登录到-stdout-而不是-stderr"><h2>登录到 stdout 而不是 stderr</h2></a>
<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#method.target"><code>Builder::target</code></a>创建一个自定义记录器配置，将日志输出的目标设置为<a href="https://docs.rs/env_logger/*/env_logger/fmt/enum.Target.html"><code>Target::Stdout</code></a>。</p>
<pre><pre class="playpen"><code class="language-rust">#[macro_use]
extern crate log;
extern crate env_logger;

use env_logger::{Builder, Target};

fn main() {
    Builder::new()
        .target(Target::Stdout)
        .init();

    error!(&quot;This error has been printed to Stdout&quot;);
}
</code></pre></pre>
<a class="header" href="#使用自定义记录器记录消息" id="使用自定义记录器记录消息"><h2>使用自定义记录器，记录消息</h2></a>
<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>实现一个自定义记录器<code>ConsoleLogger</code>，它打印到 stdout。为了使用记录的宏，<code>ConsoleLogger</code>实现<a href="https://docs.rs/log/*/log/trait.Log.html"><code>log::Log</code></a> trait，那么<a href="https://docs.rs/log/*/log/fn.set_logger.html"><code>log::set_logger</code></a>就能安装它了。</p>
<pre><pre class="playpen"><code class="language-rust">#[macro_use]
extern crate log;

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);

    info!(&quot;hello log&quot;);
    warn!(&quot;warning&quot;);
    error!(&quot;oops&quot;);
    Ok(())
}
</code></pre></pre>
<a class="header" href="#登录到-unix-系统日志" id="登录到-unix-系统日志"><h2>登录到 Unix 系统日志</h2></a>
<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>将消息记录到<a href="https://www.gnu.org/software/libc/manual/html_node/Overview-of-Syslog.html">UNIX 系统日志</a>。用<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>表明该程序，添加的日志条目分类，<a href="https://docs.rs/log/*/log/enum.LevelFilter.html"><code>log::LevelFilter</code></a>表示允许的日志等级，和<code>Option&lt;&amp;str&gt;</code>持有可选的应用程序名称。</p>
<pre><pre class="playpen"><code class="language-rust">#[macro_use]
extern crate log;
# #[cfg(target_os = &quot;linux&quot;)]
extern crate syslog;

# #[cfg(target_os = &quot;linux&quot;)]
use syslog::{Facility, Error};

# #[cfg(target_os = &quot;linux&quot;)]
fn main() -&gt; Result&lt;(), Error&gt; {
    syslog::init(Facility::LOG_USER,
                 log::LevelFilter::Debug,
                 Some(&quot;My app name&quot;))?;
    debug!(&quot;this is a debug {}&quot;, &quot;message&quot;);
    error!(&quot;this is an error!&quot;);
    Ok(())
}

# #[cfg(not(target_os = &quot;linux&quot;))]
# fn main() {
#     println!(&quot;So far, only Linux systems are supported.&quot;);
# }
</code></pre></pre>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<a class="header" href="#配置日志记录" id="配置日志记录"><h1>配置日志记录</h1></a>
<a class="header" href="#启用每个模块的日志级别" id="启用每个模块的日志级别"><h2>启用每个模块的日志级别</h2></a>
<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>创建两个模块：<code>foo</code>，以及嵌套的<code>foo::bar</code>，它们的记录指令，单独用<a href="https://docs.rs/env_logger/*/env_logger/#enabling-logging"><code>RUST_LOG</code></a>环境变量控制。</p>
<pre><pre class="playpen"><code class="language-rust">#[macro_use]
extern crate log;
extern crate env_logger;

mod foo {
    mod bar {
        pub fn run() {
            warn!(&quot;[bar] warn&quot;);
            info!(&quot;[bar] info&quot;);
            debug!(&quot;[bar] debug&quot;);
        }
    }

    pub fn run() {
        warn!(&quot;[foo] warn&quot;);
        info!(&quot;[foo] info&quot;);
        debug!(&quot;[foo] debug&quot;);
        bar::run();
    }
}

fn main() {
    env_logger::init();
    warn!(&quot;[root] warn&quot;);
    info!(&quot;[root] info&quot;);
    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>环境变量，控制<a href="https://docs.rs/env_logger/"><code>env_logger</code></a>输出。模块声明采用逗号分隔项，格式如下<code>path::to::module=log_level</code>。 运行<code>test</code>应用如下：</p>
<pre><code class="language-bash">RUST_LOG=&quot;warn,test::foo=info,test::foo::bar=debug&quot; ./test
</code></pre>
<p>设置默认值<a href="https://docs.rs/log/*/log/enum.Level.html"><code>log::Level</code></a>为<code>warn</code>，而模块<code>foo</code>和模块<code>foo::bar</code>则分别为<code>info</code>和<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>
<a class="header" href="#使用自定义环境变量设置日志记录" id="使用自定义环境变量设置日志记录"><h2>使用自定义环境变量，设置日志记录</h2></a>
<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>配置日志记录。</p>
<p><a href="https://docs.rs/env_logger/*/env_logger/struct.Builder.html#method.parse"><code>Builder::parse</code></a>解析<code>MY_APP_LOG</code>环境变量内容，变为<a href="https://docs.rs/env_logger/*/env_logger/#enabling-logging"><code>RUST_LOG</code></a>语法形式。然后，<a href="https://docs.rs/env_logger/*/env_logger/struct.Builder.html#method.init"><code>Builder::init</code></a>初始化记录器。所有这些步骤，通常都是由<a href="https://docs.rs/env_logger/*/env_logger/fn.init.html"><code>env_logger::init</code></a>内部完成。</p>
<pre><pre class="playpen"><code class="language-rust">#[macro_use]
extern crate log;
extern crate env_logger;

use std::env;
use env_logger::Builder;

fn main() {
    Builder::new()
        .parse(&amp;env::var(&quot;MY_APP_LOG&quot;).unwrap_or_default())
        .init();

    info!(&quot;informational message&quot;);
    warn!(&quot;warning message&quot;);
    error!(&quot;this is an error {}&quot;, &quot;message&quot;);
}
</code></pre></pre>
<a class="header" href="#在日志消息中包含时间戳" id="在日志消息中包含时间戳"><h2>在日志消息中，包含时间戳</h2></a>
<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>使用<a href="https://docs.rs/env_logger/*/env_logger/struct.Builder.html"><code>Builder</code></a>创建一个自定义记录器配置。 每次记录都调用<a href="https://docs.rs/chrono/*/chrono/offset/struct.Local.html#method.now"><code>Local::now</code></a>，获取在本地时区的当前<a href="https://docs.rs/chrono/*/chrono/datetime/struct.DateTime.html"><code>DateTime</code></a>，和使用<a href="https://docs.rs/chrono/*/chrono/struct.DateTime.html#method.format"><code>DateTime::format</code></a>带上<a href="https://docs.rs/chrono/*/chrono/format/strftime/index.html#specifiers"><code>strftime::specifiers</code></a>，在最终记录中，格式化使用的时间戳。</p>
<p>示例：调用<a href="https://docs.rs/env_logger/*/env_logger/struct.Builder.html#method.format"><code>Builder::format</code></a>，它需要设置一个闭包函数，对每个消息文本格式化，添加时间戳，<a href="https://docs.rs/log/*/log/struct.Record.html#method.level"><code>Record::level</code></a>和主体<a href="https://docs.rs/log/*/log/struct.Record.html#method.args"><code>Record::args</code></a>）。</p>
<pre><pre class="playpen"><code class="language-rust">#[macro_use]
extern crate log;
extern crate chrono;
extern crate env_logger;

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();

    warn!(&quot;warn&quot;);
    info!(&quot;info&quot;);
    debug!(&quot;debug&quot;);
}
</code></pre></pre>
<p>stderr 输出，将包含</p>
<pre><code>2017-05-22T21:57:06 [WARN] - warn
2017-05-22T21:57:06 [INFO] - info
</code></pre>
<a class="header" href="#将消息记录到自定义位置" id="将消息记录到自定义位置"><h2>将消息记录，到自定义位置</h2></a>
<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>能配置日志记录，输出到自定义的位置。<a href="https://docs.rs/log4rs/">log4rs</a>可以使用外部 yaml 文件，或一个生成器配置。</p>
<p>使用<a href="https://docs.rs/log4rs/*/log4rs/append/file/struct.FileAppender.html"><code>log4rs::append::file::FileAppender</code></a>创建一个日志配置。该配置继续使用来自<a href="https://docs.rs/log4rs/*/log4rs/encode/pattern/index.html"><code>log4rs::encode::pattern</code></a>的自定义模式，进行编码，要知道，这个配置其实是定义日录记录目标的附加项。待会，还要将附加项配置，分配给<a href="https://docs.rs/log4rs/*/log4rs/config/struct.Config.html"><code>log4rs::config::Config</code></a>，并设置默认值<a href="https://docs.rs/log/*/log/enum.LevelFilter.html"><code>log::LevelFilter</code></a>。</p>
<pre><pre class="playpen"><code class="language-rust no_run"># #[macro_use]
# extern crate error_chain;
#[macro_use]
extern crate log;
extern crate log4rs;

use log::LevelFilter;
use log4rs::append::file::FileAppender;
use log4rs::encode::pattern::PatternEncoder;
use log4rs::config::{Appender, Config, Root};
#
# error_chain! {
#     foreign_links {
#         Io(std::io::Error);
#         LogConfig(log4rs::config::Errors);
#         SetLogger(log::SetLoggerError);
#     }
# }

fn run() -&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)?;

    info!(&quot;Hello, world!&quot;);

    Ok(())
}
#
# quick_main!(run);
</code></pre></pre>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<a class="header" href="#版本控制-2" id="版本控制-2"><h1>版本控制</h1></a>
<a class="header" href="#分析并增加版本字符串" id="分析并增加版本字符串"><h2>分析并增加版本字符串。</h2></a>
<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>构建一个<a href="https://docs.rs/semver/*/semver/struct.Version.html"><code>semver::Version</code></a>从字符串文本使用<a href="https://docs.rs/semver/*/semver/struct.Version.html#method.parse"><code>Version::parse</code></a>，然后逐个递增补丁、次要版本和主要版本号。</p>
<p>注意，根据[语义版本规范]，递增次要版本号将补丁版本号重置为0，递增主要版本号将次要版本号和补丁版本号重置为0。</p>
<pre><pre class="playpen"><code class="language-rust">extern crate semver;

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>
<a class="header" href="#分析复杂的版本字符串" id="分析复杂的版本字符串"><h2>分析复杂的版本字符串。</h2></a>
<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>使用<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.Version.html"><code>semver::Version</code></a>。 该字符串包含预发布和构建的元数据，正如[语义版本规范]所定义的。</p>
<p>注意，根据规范，构建元数据虽然解析了，但在比较版本时，不考虑。换句话说，即使构建字符串不同，两个版本也可能相同。</p>
<pre><pre class="playpen"><code class="language-rust">extern crate semver;

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>
<a class="header" href="#检查给定版本是否为预发布版本" id="检查给定版本是否为预发布版本"><h2>检查给定版本，是否为预发布版本。</h2></a>
<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>给出两个版本，<a href="https://docs.rs/semver/*/semver/struct.Version.html#method.is_prerelease"><code>is_prerelease</code></a>断言一个是预发布，另一个不是。</p>
<pre><pre class="playpen"><code class="language-rust">extern crate semver;

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>
<a class="header" href="#查找满足给定范围的最新版本" id="查找满足给定范围的最新版本"><h2>查找满足给定范围的最新版本</h2></a>
<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>给定版本 <code>&amp;str</code> 的一个列表，查找最新的<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>能用<a href="https://docs.rs/semver/*/semver/struct.VersionReq.html#method.matches"><code>VersionReq::matches</code></a>筛选列表。还可以，给出预发布<code>semver</code>的首选项。</p>
<pre><pre class="playpen"><code class="language-rust"># #[macro_use]
# extern crate error_chain;
extern crate semver;

use semver::{Version, VersionReq};
#
# error_chain! {
#     foreign_links {
#         SemVer(semver::SemVerError);
#         SemVerReq(semver::ReqParseError);
#     }
# }

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 run() -&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(())
}
#
# quick_main!(run);
</code></pre></pre>
<a class="header" href="#检查外部命令版本的兼容性" id="检查外部命令版本的兼容性"><h2>检查外部命令版本的兼容性</h2></a>
<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>使用<a href="https://doc.rust-lang.org/std/process/struct.Command.html"><code>Command</code></a>运行<code>git --version</code>，然后用<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.Version.html"><code>semver::Version</code></a>。 <a href="https://docs.rs/semver/*/semver/struct.VersionReq.html#method.matches"><code>VersionReq::matches</code></a>会比较<a href="https://docs.rs/semver/*/semver/struct.VersionReq.html"><code>semver::VersionReq</code></a>与已解析的版本。命令输出，类似于”git version x.y.z”。</p>
<pre><pre class="playpen"><code class="language-rust no_run"># #[macro_use]
# extern crate error_chain;
extern crate semver;

use std::process::Command;
use semver::{Version, VersionReq};
#
# error_chain! {
#     foreign_links {
#         Io(std::io::Error);
#         Utf8(std::string::FromUtf8Error);
#         SemVer(semver::SemVerError);
#         SemVerReq(semver::ReqParseError);
#     }
# }

fn run() -&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() {
        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) {
        bail!(&quot;Command version lower than minimum supported version (found {}, need {})&quot;,
            parsed_version, version_constraint);
    }

    Ok(())
}
#
# quick_main!(run);
</code></pre></pre>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<a class="header" href="#构建时工具" id="构建时工具"><h1>构建时工具</h1></a>
<p>本节介绍在编译箱子源代码之前，运行的“构建时”工具或代码。通常，构建时代码，位于<strong>build.rs</strong>文件，通常称为“构建脚本”。常见的用例，包括：Rust 代码生成，和捆绑的 C/C++/ASM 代码的编译。查看 crates.io 的 <a href="http://doc.crates.io/build-script.html">主分支文档</a>，了解更多信息。</p>
<a class="header" href="#编译并静态链接到捆绑的-c-库" id="编译并静态链接到捆绑的-c-库"><h2>编译，并静态链接到捆绑的 C 库</h2></a>
<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>为了适应项目，需要附加 C、C++ 或 ASM 的场景，<a href="https://docs.rs/cc"><strong>cc</strong></a>箱子，提供了一个简单的 API，用于将捆绑的 C/C++/ASM 代码编译成静态库（<strong>.a</strong>），这样就可以静态链接到<strong>rustc</strong>.</p>
<p>下面的示例，包含一些绑定的 C 代码（<strong>src/hello.c</strong>），会用在 Rust 上。在编译 rust 源代码之前，“构建”文件（<strong>build.rs</strong>）可通过<strong>Cargo.toml</strong>指定运行。若使用<a href="https://docs.rs/cc"><strong>cc</strong></a>箱子，一个静态库文件将被生成（在这情况下，就是<strong>libhello.a</strong>，若想知道更多，请看<a href="https://docs.rs/cc/*/cc/struct.Build.html#method.compile"><code>compile</code>文档</a>）然后，在 Rust 中想使用该库，可以通过在<code>extern</code>块中，定义外部函数签名。</p>
<p>由于绑定的 C 非常简单，因此只需要将一个源文件，传递给<a href="https://docs.rs/cc/*/cc/struct.Build.html"><code>cc::Build</code></a>。 对于更复杂的构建需求，<a href="https://docs.rs/cc/*/cc/struct.Build.html"><code>cc::Build</code></a>为指定的<a href="https://docs.rs/cc/*/cc/struct.Build.html#method.include"><code>include</code></a>的路径，和额外的编译器<a href="https://docs.rs/cc/*/cc/struct.Build.html#method.flag"><code>flag</code></a>标志们，提供了一整套构建器方法。</p>
<a class="header" href="#cargotoml" id="cargotoml"><h3><code>Cargo.toml</code></h3></a>
<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>
<a class="header" href="#buildrs" id="buildrs"><h3><code>build.rs</code></h3></a>
<pre><pre class="playpen"><code class="language-rust no_run">extern crate cc;

fn main() {
    cc::Build::new()
        .file(&quot;src/hello.c&quot;)
        .compile(&quot;hello&quot;);   // outputs `libhello.a`
}
</code></pre></pre>
<a class="header" href="#srchelloc" id="srchelloc"><h3><code>src/hello.c</code></h3></a>
<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>
<a class="header" href="#srcmainrs" id="srcmainrs"><h3><code>src/main.rs</code></h3></a>
<pre><code class="language-rust ignore"># #[macro_use] extern crate 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 run() -&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(())
}
#
# quick_main!(run);
</code></pre>
<a class="header" href="#编译并静态链接到捆绑的-c库" id="编译并静态链接到捆绑的-c库"><h2>编译，并静态链接到捆绑的 C++库</h2></a>
<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>链接捆绑的 C++库，非常类似于链接捆绑的 C 库。编译和静态链接捆绑的 C++库的两个核心区别，是通过构建器方法<a href="https://docs.rs/cc/*/cc/struct.Build.html#method.cpp"><code>cpp(true)</code></a>指定 C++编译器。通过在我们的 C++源文件的顶部，添加<code>extern &quot;C&quot;</code>部分，防止 C++编译器的名称篡改。</p>
<a class="header" href="#cargotoml-1" id="cargotoml-1"><h3><code>Cargo.toml</code></h3></a>
<pre><code class="language-toml">[package]
...
build = &quot;build.rs&quot;

[build-dependencies]
cc = &quot;1&quot;
</code></pre>
<a class="header" href="#buildrs-1" id="buildrs-1"><h3><code>build.rs</code></h3></a>
<pre><pre class="playpen"><code class="language-rust no_run">extern crate cc;

fn main() {
    cc::Build::new()
        .cpp(true)
        .file(&quot;src/foo.cpp&quot;)
        .compile(&quot;foo&quot;);
}
</code></pre></pre>
<a class="header" href="#srcfoocpp" id="srcfoocpp"><h3><code>src/foo.cpp</code></h3></a>
<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>
<a class="header" href="#srcmainrs-1" id="srcmainrs-1"><h3><code>src/main.rs</code></h3></a>
<pre><code class="language-rust ignore">extern {
    fn multiply(x : i32, y : i32) -&gt; i32;
}

fn main(){
    unsafe {
        println!(&quot;{}&quot;, multiply(5,7));
    }
}
</code></pre>
<a class="header" href="#带自定义设置编译-c-库" id="带自定义设置编译-c-库"><h2>带自定义设置，编译 C 库</h2></a>
<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>使用<a href="https://docs.rs/cc/*/cc/struct.Build.html#method.define"><code>cc::Build::define</code></a>自定义构建，捆绑的 C 代码很简单。 该方法采用<a href="https://doc.rust-lang.org/std/option/enum.Option.html"><code>Option</code></a>值，因此可以创建如下定义：<code>#define APP_NAME &quot;foo&quot;</code>，以及<code>#define WELCOME</code>（传递 <code>None</code>作为一个缺乏值的定义）。这个例子构建了一个动态定义集的捆绑 C 文件，而定义集在<code>build.rs</code>中，并会在运行使，打印<strong>欢迎使用 foo-版本 1.0.2</strong>“。Cargo 会设置一些<a href="https://doc.rust-lang.org/cargo/reference/environment-variables.html">环境变量</a>，这对于某些自定义设置可能很有用。</p>
<a class="header" href="#cargotoml-2" id="cargotoml-2"><h3><code>Cargo.toml</code></h3></a>
<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>
<a class="header" href="#buildrs-2" id="buildrs-2"><h3><code>build.rs</code></h3></a>
<pre><pre class="playpen"><code class="language-rust no_run">extern crate cc;

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>
<a class="header" href="#srcfooc" id="srcfooc"><h3><code>src/foo.c</code></h3></a>
<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>
<a class="header" href="#srcmainrs-2" id="srcmainrs-2"><h3><code>src/main.rs</code></h3></a>
<pre><code class="language-rust 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 -->
<a class="header" href="#编码-1" id="编码-1"><h1>编码</h1></a>
<table><thead><tr><th> 食谱                                                                </th><th> 箱子                                        </th><th> 类别                                  </th></tr></thead><tbody>
<tr><td> <a href="encoding/strings.zh.html#percent-encode-a-string">百分比编码(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/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.zh.html#encode-a-string-as-applicationx-www-form-urlencoded">将字符串，编码为 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.zh.html#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.zh.html#encode-and-decode-base64">对 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.zh.html#read-csv-records">读取 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.zh.html#read-csv-records-with-different-delimiter">读取具有不同分隔符的 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.zh.html#filter-csv-records-matching-a-predicate">筛选与断言匹配的 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.zh.html#handle-invalid-csv-data-with-serde">使用 serde ，处理无效的 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> <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.zh.html#serialize-records-to-csv">将记录序列化为 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.zh.html#serialize-records-to-csv-using-serde">使用 serde ，将记录序列化为 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> <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.zh.html#transform-csv-column">转换 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> <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.zh.html#serialize-and-deserialize-unstructured-json">序列化和反序列化，非结构化 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.zh.html#deserialize-a-toml-configuration-file">反序列化，一个 Toml 配置文件</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.zh.html#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 -->
<a class="header" href="#字符集" id="字符集"><h1>字符集</h1></a>
<a class="header" href="#url-编码字符串" id="url-编码字符串"><h2>URL 编码字符串</h2></a>
<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>编码一个输入字符串，编码方式为<a href="https://en.wikipedia.org/wiki/Percent-encoding">URL 编码</a>，可通过使用来自<code>url</code>箱子的<a href="https://docs.rs/percent-encoding/*/percent_encoding/fn.utf8_percent_encode.html"><code>utf8_percent_encode</code></a>函数完成。然后再使用<a href="https://docs.rs/percent-encoding/*/percent_encoding/fn.percent_decode.html"><code>percent_decode</code></a>函数。</p>
<pre><pre class="playpen"><code class="language-rust">extern crate url;

use url::percent_encoding::{utf8_percent_encode, percent_decode, DEFAULT_ENCODE_SET};
use std::str::Utf8Error;

fn main() -&gt; Result&lt;(), Utf8Error&gt; {
    let input = &quot;confident, productive systems programming&quot;;

    let iter = utf8_percent_encode(input, DEFAULT_ENCODE_SET);
    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>该编码集定义哪些字节（除了非 ASCII 和控制键位之外）需要 URL 编码。此集合的选择取决于上下文。例如，<code>url</code>会编码 URL 路径中的<code>?</code>，但不会在查询字符串。</p>
<p>编码的返回值是，<code>&amp;str</code>切片的迭代器，这能收集（collect）成一个<code>String</code>。</p>
<a class="header" href="#将字符串编码为-applicationx-www-form-urlencoded" id="将字符串编码为-applicationx-www-form-urlencoded"><h2>将字符串编码为 application/x-www-form-urlencoded</h2></a>
<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>将字符串，编码为<a href="https://url.spec.whatwg.org/#application/x-www-form-urlencoded">application/x-www-form-urlencoded</a>语法，通过<a href="https://docs.rs/url/*/url/form_urlencoded/fn.byte_serialize.html"><code>form_urlencoded::byte_serialize</code></a>，然后用<a href="https://docs.rs/url/*/url/form_urlencoded/fn.parse.html"><code>form_urlencoded::parse</code></a>完成。 两个函数都返回迭代器，这些迭代器能收集成一个<code>String</code>。</p>
<pre><pre class="playpen"><code class="language-rust">extern crate url;
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>
<a class="header" href="#编码和解码十六进制" id="编码和解码十六进制"><h2>编码和解码十六进制</h2></a>
<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>这个<a href="https://docs.rs/data-encoding/*/data_encoding/"><code>data_encoding</code></a>箱子提供一个<code>HEXUPPER::encode</code>方法，它会获取一个<code>&amp;[u8]</code>，并返回一个<code>String</code>，其中包含数据的十六进制表示形式。</p>
<p>类似地，一个<code>HEXUPPER::decode</code>提供的方法，也获取一个<code>&amp;[u8]</code>，并如果输入数据解码成功的话，就返回一个<code>Vec&lt;u8&gt;</code>。</p>
<p>下面的例子，将<code>&amp;[u8]</code>数据转换为等效十六进制。将此值与预期值，进行比较。</p>
<pre><pre class="playpen"><code class="language-rust">extern crate data_encoding;

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>
<a class="header" href="#对-base64-进行编码和解码" id="对-base64-进行编码和解码"><h2>对 base64 进行编码和解码</h2></a>
<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>将字节切片编码为<code>base64</code>字符串，通过<a href="https://docs.rs/base64/*/base64/fn.encode.html"><code>encode</code></a>完成，还能用<a href="https://docs.rs/base64/*/base64/fn.decode.html"><code>decode</code></a>解码。</p>
<pre><pre class="playpen"><code class="language-rust"># #[macro_use]
# extern crate error_chain;
extern crate base64;

use std::str;
use base64::{encode, decode};
#
# error_chain! {
#     foreign_links {
#         Base64(base64::DecodeError);
#         Utf8Error(str::Utf8Error);
#     }
# }

fn run() -&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(())
}
#
# quick_main!(run);
</code></pre></pre>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<a class="header" href="#csv-处理" id="csv-处理"><h1>CSV 处理</h1></a>
<a class="header" href="#读取-csv-记录" id="读取-csv-记录"><h2>读取 csv 记录</h2></a>
<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>将标准 csv 记录，读取到<a href="https://docs.rs/csv/*/csv/struct.StringRecord.html"><code>csv::StringRecord</code></a>：一种弱类型数据表示形式，这需要有效的 UTF-8 行。或者，<a href="https://docs.rs/csv/*/csv/struct.ByteRecord.html"><code>csv::ByteRecord</code></a>，它不会对 UTF-8 有任何假设。</p>
<pre><pre class="playpen"><code class="language-rust">extern crate csv;
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><code>serde</code> 将数据反序列化，为强类型结构。见<a href="https://docs.rs/csv/*/csv/struct.Reader.html#method.deserialize"><code>csv::Reader::deserialize</code></a>方法。</p>
<pre><pre class="playpen"><code class="language-rust">extern crate csv;
# #[macro_use]
# extern crate error_chain;
#[macro_use]
extern crate serde_derive;

# error_chain! {
#     foreign_links {
#         Reader(csv::Error);
#     }
# }
#
#[derive(Deserialize)]
struct Record {
    year: u16,
    make: String,
    model: String,
    description: String,
}

fn run() -&gt; Result&lt;()&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(())
}
#
# quick_main!(run);
</code></pre></pre>
<a class="header" href="#读取具有不同分隔符的-csv-记录" id="读取具有不同分隔符的-csv-记录"><h2>读取具有不同分隔符的 csv 记录</h2></a>
<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>用一个 tab(分隔符) <a href="https://docs.rs/csv/1.0.0-beta.3/csv/struct.ReaderBuilder.html#method.delimiter"><code>delimiter</code></a> 读取 csv 记录。</p>
<pre><pre class="playpen"><code class="language-rust">extern crate csv;
use csv::Error;
#[macro_use]
extern crate serde_derive;

#[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>
<a class="header" href="#筛选与断言匹配的-csv-记录" id="筛选与断言匹配的-csv-记录"><h2>筛选与断言匹配的 csv 记录</h2></a>
<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><em>只</em>返回<code>data</code>中字段(field)行，匹配<code>query</code>的。</p>
<pre><pre class="playpen"><code class="language-rust"># #[macro_use]
# extern crate error_chain;
extern crate csv;

use std::io;
#
# error_chain!{
#     foreign_links {
#         Io(std::io::Error);
#         CsvError(csv::Error);
#     }
# }

fn run() -&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(())
}
#
# quick_main!(run);
</code></pre></pre>
<p>_免责声明：本示例改编自<a href="https://docs.rs/csv/_/csv/tutorial/index.html#filter-by-search">the csv crate tutorial</a>*.</p>
<a class="header" href="#使用-serde-处理无效的-csv-数据" id="使用-serde-处理无效的-csv-数据"><h2>使用 <code>serde</code> 处理无效的 csv 数据</h2></a>
<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 文件通常包含无效数据。对于这些情况，<code>csv</code>箱子提供一个自定义反序列化程序，<a href="https://docs.rs/csv/*/csv/fn.invalid_option.html"><code>csv::invalid_option</code></a>，自动将无效数据转换为 <code>None</code>值。</p>
<pre><pre class="playpen"><code class="language-rust">extern crate csv;
use csv::Error;
#[macro_use]
extern crate serde_derive;

#[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>
<a class="header" href="#将记录序列化为-csv" id="将记录序列化为-csv"><h2>将记录，序列化为 csv</h2></a>
<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>这个例子：演示了如何序列化一个 Rust 元组。<a href="https://docs.rs/csv/*/csv/struct.Writer.html"><code>csv::writer</code></a>支持从 Rust 类型，到 csv 记录的自动序列化。<a href="https://docs.rs/csv/*/csv/struct.Writer.html#method.write_record"><code>write_record</code></a>只写入包含字符串数据的简单记录。对于具有更复杂值（如数字、浮点数和选项）的数据，请使用<a href="https://docs.rs/csv/*/csv/struct.Writer.html#method.serialize"><code>serialize</code></a>。因为 csv 编写器使用内部缓冲区，所以在做完之后，始终要显式<a href="https://docs.rs/csv/*/csv/struct.Writer.html#method.flush"><code>flush</code></a>。</p>
<pre><pre class="playpen"><code class="language-rust"># #[macro_use]
# extern crate error_chain;
extern crate csv;

use std::io;
#
# error_chain! {
#     foreign_links {
#         CSVError(csv::Error);
#         IOError(std::io::Error);
#    }
# }

fn run() -&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(())
}
#
# quick_main!(run);
</code></pre></pre>
<a class="header" href="#使用-serde-将记录序列化为-csv" id="使用-serde-将记录序列化为-csv"><h2>使用 serde 将记录序列化为 csv</h2></a>
<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>下面的示例，演示如何使用<a href="https://docs.rs/serde/">serde</a>箱子。</p>
<pre><pre class="playpen"><code class="language-rust"># #[macro_use]
# extern crate error_chain;
extern crate csv;
#[macro_use]
extern crate serde_derive;

use std::io;
#
# error_chain! {
#    foreign_links {
#        IOError(std::io::Error);
#        CSVError(csv::Error);
#    }
# }

#[derive(Serialize)]
struct Record&lt;'a&gt; {
    name: &amp;'a str,
    place: &amp;'a str,
    id: u64,
}

fn run() -&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(())
}
#
# quick_main!(run);
</code></pre></pre>
<a class="header" href="#转换-csv-列" id="转换-csv-列"><h2>转换 csv 列</h2></a>
<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 文件，转换为具有颜色名称和 RGB 颜色的文件。利用<a href="https://docs.rs/csv/">csv</a>箱子，读取和写入 csv 文件，以及<a href="https://docs.rs/serde/">serde</a>对文件的一行，在字节之间进行反序列化和序列化。</p>
<p>见<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>和<a href="https://doc.rust-lang.org/std/str/trait.FromStr.html"><code>std::str::FromStr</code></a></p>
<pre><pre class="playpen"><code class="language-rust">extern crate csv;
# #[macro_use]
# extern crate error_chain;
#[macro_use]
extern crate serde_derive;
extern crate serde;

use csv::{Reader, Writer};
use serde::{de, Deserialize, Deserializer};
use std::str::FromStr;
#
# error_chain! {
#    foreign_links {
#        CsvError(csv::Error);
#        ParseInt(std::num::ParseIntError);
#        CsvInnerError(csv::IntoInnerError&lt;Writer&lt;Vec&lt;u8&gt;&gt;&gt;);
#        IO(std::fmt::Error);
#        UTF8(std::string::FromUtf8Error);
#    }
# }

#[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 run() -&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(())
}
#
# quick_main!(run);
</code></pre></pre>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<a class="header" href="#结构化数据" id="结构化数据"><h1>结构化数据</h1></a>
<a class="header" href="#序列化和反序列化非结构化-json" id="序列化和反序列化非结构化-json"><h2>序列化和反序列化，非结构化 JSON</h2></a>
<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>这个<a href="https://docs.serde.rs/serde_json/"><code>serde_json</code></a>箱子提供<a href="https://docs.serde.rs/serde_json/fn.from_str.html"><code>from_str</code></a>这个解析函数，它需要 JSON 的<code>&amp;str</code>。</p>
<p>非结构化 JSON 可以解析为，一个通用的<a href="https://docs.serde.rs/serde_json/enum.Value.html"><code>serde_json::Value</code></a>类型，它能够表示任何有效 JSON 数据的类型。</p>
<p>下面的示例显示，正在解析 JSON 的 <code>&amp;str</code>。使用<a href="https://docs.serde.rs/serde_json/macro.json.html"><code>json!</code></a>宏：</p>
<pre><pre class="playpen"><code class="language-rust">#[macro_use]
extern crate serde_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>
<a class="header" href="#反序列化toml-配置文件" id="反序列化toml-配置文件"><h2>反序列化，toml 配置文件</h2></a>
<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>把一些 toml 解析成，一个通用的<code>toml::Value</code>类型，它能够表示任何有效的 TOML 数据。</p>
<pre><pre class="playpen"><code class="language-rust">extern crate toml;

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>使用<a href="https://docs.rs/serde/">serde</a>，将 toml 解析为您自己的结构。</p>
<pre><pre class="playpen"><code class="language-rust"># #[macro_use]
# extern crate error_chain;
#[macro_use]
extern crate serde_derive;
extern crate toml;

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;,
}
#
# error_chain! {
#     foreign_links {
#         Toml(toml::de::Error);
#     }
# }

fn run() -&gt; Result&lt;()&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(())
}
#
# quick_main!(run);
</code></pre></pre>
<a class="header" href="#以小端序读取和写入整数" id="以小端序读取和写入整数"><h2>以小端序，读取和写入整数</h2></a>
<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>可以反转，结构化数据的有效字节。这对网络上的信息接收，还有类似另一个系统的字节来说，可能会有必要。</p>
<pre><pre class="playpen"><code class="language-rust">extern crate byteorder;

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 -->
<a class="header" href="#错误处理" id="错误处理"><h1>错误处理</h1></a>
<table><thead><tr><th> 食谱                                                            </th><th> 箱子                                </th><th> 类别                                            </th></tr></thead><tbody>
<tr><td> <a href="errors/handle.zh.html#handle-errors-correctly-in-main">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.zh.html#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.zh.html#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 -->
<a class="header" href="#错误处理-1" id="错误处理-1"><h1>错误处理</h1></a>
<a class="header" href="#main-中的正确处理错误" id="main-中的正确处理错误"><h2>main 中的正确处理错误</h2></a>
<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>要处理尝试打开不存在的文件时，发生的错误。我们会用到<a href="https://docs.rs/error-chain/">error-chain</a>，这是一个大量样板代码的库，用来[处理 Rust 的错误]。</p>
<p><a href="https://docs.rs/error-chain/*/error_chain/#foreign-links"><code>foreign_links</code></a>里面的<code>Io(std::io::Error)</code>，允许从<a href="https://doc.rust-lang.org/std/io/struct.Error.html"><code>std::io::Error</code></a>到<a href="https://docs.rs/error-chain/*/error_chain/macro.error_chain.html"><code>error_chain!</code></a>所定义类型的自动转换，这些类型会实现<a href="https://doc.rust-lang.org/std/error/trait.Error.html"><code>Error</code></a> trait。</p>
<p>下面的食谱是，在打开 unix 文件<code>/proc/uptime</code>，然后分析内容得到第一个数字期间，告诉我们系统运行了多长时间。要返回 uptime，除非出现错误。</p>
<p>本书中的其他食谱，会隐藏<a href="https://docs.rs/error-chain/">error-chain</a>样板文件，可以通过按钮（展开代码）来查看。</p>
<pre><pre class="playpen"><code class="language-rust">#[macro_use]
extern crate 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>
<a class="header" href="#避免在错误转换期间丢掉了错误" id="避免在错误转换期间丢掉了错误"><h2>避免在错误转换期间，丢掉了错误</h2></a>
<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>这个<a href="https://docs.rs/error-chain/">error-chain</a>箱子，能<a href="https://docs.rs/error-chain/*/error_chain/#matching-errors">匹配</a>函数返回的不同错误类型，可能是相对紧凑的。<a href="https://docs.rs/error-chain/*/error_chain/example_generated/enum.ErrorKind.html"><code>ErrorKind</code></a>能确定错误类型。</p>
<p>使用<a href="https://docs.rs/reqwest/">reqwest</a>查询一个随机整数生成器的 Web 服务。将响应的字符串，转换为整数。我们有 Rust 标准库，<a href="https://docs.rs/reqwest/">reqwest</a>，并且 Web 服务的全部错误都会(可能)发生。要明确定义的 Rust 错误，请使用<a href="https://docs.rs/error-chain/*/error_chain/#foreign-links"><code>foreign_links</code></a>。 对于额外的 Web 服务错误<a href="https://docs.rs/error-chain/*/error_chain/example_generated/enum.ErrorKind.html"><code>ErrorKind</code></a>变种，使用<code>error_chain!</code>宏的<code>errors</code>代码块。</p>
<pre><pre class="playpen"><code class="language-rust">#[macro_use]
extern crate error_chain;
extern crate reqwest;

use std::io::Read;

error_chain! {
    foreign_links {
        Io(std::io::Error);
        Reqwest(reqwest::Error);
        ParseIntError(std::num::ParseIntError);
    }

    errors { RandomResponseError(t: String) }
}

fn parse_response(mut response: reqwest::Response) -&gt; Result&lt;u32&gt; {
    let mut body = String::new();
    response.read_to_string(&amp;mut body)?;
    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::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>
<a class="header" href="#获取复杂的错误场景的回溯" id="获取复杂的错误场景的回溯"><h2>获取复杂的错误场景的回溯</h2></a>
<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>这个食谱，演示了如何处理复杂的错误场景，然后打印回溯。它依赖<a href="https://docs.rs/error-chain/*/error_chain/index.html#chaining-errors"><code>chain_err</code></a>附加新错误，来扩展错误(信息)。错误(信息)栈可以展开，从而提供更好的上下文，来理解引发错误的原因。</p>
<p>以下食谱，尝试将值<code>256</code>反序列化成一个<code>u8</code>。一个错误从 serde 开始冒泡，然后是 csv，最后到达，用户代码。</p>
<pre><pre class="playpen"><code class="language-rust"># extern crate csv;
#[macro_use]
extern crate error_chain;
# #[macro_use]
# extern crate serde_derive;
#
# use std::fmt;
#
# error_chain! {
#     foreign_links {
#         Reader(csv::Error);
#     }
# }

#[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)
    }
}

# impl fmt::UpperHex for Rgb {
#     fn fmt(&amp;self, f: &amp;mut fmt::Formatter) -&gt; fmt::Result {
#         let hexa = u32::from(self.red) &lt;&lt; 16 | u32::from(self.blue) &lt;&lt; 8 | u32::from(self.green);
#         write!(f, &quot;{:X}&quot;, hexa)
#     }
# }
#
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);
        }
#
#         // In a real use case, errors should handled. For example:
#         // ::std::process::exit(1);
    }
}
</code></pre></pre>
<p>已呈现的错误回溯：</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>使用<code>RUST_BACKTRACE=1</code>，显示与此错误关联的<a href="https://docs.rs/error-chain/*/error_chain/trait.ChainedError.html#tymethod.backtrace"><code>backtrace</code></a>的详细信息。</p>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<a class="header" href="#文件系统-1" id="文件系统-1"><h1>文件系统</h1></a>
<table><thead><tr><th> 食谱                                                         </th><th> 箱子                            </th><th> 类别                                                                </th></tr></thead><tbody>
<tr><td> <a href="file/read-write.zh.html#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.zh.html#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.zh.html#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.zh.html#file-names-that-have-been-modified-in-the-last-24-hours">过去 24 小时内，修改过的文件名</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.zh.html#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.zh.html#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.zh.html#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.zh.html#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.zh.html#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.zh.html#find-all-png-files-recursively">递归查找，所有 PNG 文件</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.zh.html#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 -->
<a class="header" href="#读和写" id="读和写"><h1>读和写</h1></a>
<a class="header" href="#从文件中读取字符串行" id="从文件中读取字符串行"><h2>从文件中，读取字符串行</h2></a>
<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>将一份三行的消息写入文件，然后由<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/io/struct.Lines.html"><code>Lines</code></a>迭代器，用来一次读取一行。 <a href="https://doc.rust-lang.org/std/fs/struct.File.html"><code>File</code></a>实现了<a href="https://doc.rust-lang.org/std/io/trait.Read.html"><code>Read</code></a>，也就是提供<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>会打开一个<a href="https://doc.rust-lang.org/std/fs/struct.File.html"><code>File</code></a>，用于写入(文件)，而<a href="https://doc.rust-lang.org/std/fs/struct.File.html#method.open"><code>File::open</code></a>用来读取。</p>
<pre><pre class="playpen"><code class="language-rust">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>
<a class="header" href="#避免写入和读取同一文件" id="避免写入和读取同一文件"><h2>避免写入和读取，同一文件</h2></a>
<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>使用<a href="https://docs.rs/same-file/*/same_file/struct.Handle.html"><code>same_file::Handle</code></a> 控制一个文件，这样，该文件可以测试是否与其他 Handle(控制)的文件相等。在这个例子中，要读取和写入的文件 handle，被测试是否相等。</p>
<pre><pre class="playpen"><code class="language-rust">extern crate same_file;

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>显示文件 <code>new.txt</code> 的内容。</p>
<pre><code class="language-bash">cargo run &gt;&gt; ./new.txt
</code></pre>
<p>错误，因为两个文件相同。</p>
<a class="header" href="#使用内存映射随机访问文件" id="使用内存映射随机访问文件"><h2>使用内存映射，随机访问文件</h2></a>
<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>使用<a href="https://docs.rs/memmap/">memmap</a>创建文件的内存映射，并模拟一些文件的非顺序读取。使用内存映射，意味着您只需要索引到一个切片，而不是处理导航文件的<a href="https://doc.rust-lang.org/std/fs/struct.File.html#method.seek"><code>seek</code></a>。</p>
<p>这个<a href="https://docs.rs/memmap/*/memmap/struct.Mmap.html#method.map"><code>Mmap::map</code></a>函数假定内存映射后面的文件，不会同时被另一个进程修改，或者<a href="https://en.wikipedia.org/wiki/Race_condition#File_systems">竞争条件</a>发生。</p>
<pre><pre class="playpen"><code class="language-rust">extern crate memmap;

use memmap::Mmap;
use std::fs::File;
use std::io::{Write, Error};

fn main() -&gt; Result&lt;(), Error&gt; {
#     write!(File::create(&quot;content.txt&quot;)?, &quot;My hovercraft is full of eels!&quot;)?;
#
    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 -->
<a class="header" href="#目录穿梭" id="目录穿梭"><h1>目录穿梭</h1></a>
<a class="header" href="#过去-24-小时内修改过的文件名" id="过去-24-小时内修改过的文件名"><h2>过去 24 小时内，修改过的文件名</h2></a>
<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>通过调用<a href="https://doc.rust-lang.org/std/env/fn.current_dir.html"><code>env::current_dir</code></a>，获得当前工作目录，然后针对<a href="https://doc.rust-lang.org/std/fs/fn.read_dir.html"><code>fs::read_dir</code></a>中的每个条目，提取<a href="https://doc.rust-lang.org/std/fs/struct.DirEntry.html#method.path"><code>DirEntry::path</code></a>，并通过<a href="https://doc.rust-lang.org/std/fs/struct.Metadata.html"><code>fs::Metadata</code></a>得到元信息。 这个<a href="https://doc.rust-lang.org/std/fs/struct.Metadata.html#method.modified"><code>Metadata::modified</code></a>返回上次修改后的<a href="https://doc.rust-lang.org/std/time/struct.SystemTime.html#method.elapsed"><code>SystemTime::elapsed</code></a>时间。<a href="https://doc.rust-lang.org/std/time/struct.Duration.html#method.as_secs"><code>Duration::as_secs</code></a>会将时间转换为秒，并与 24 小时（24 _ 60 _ 60 秒）比较。<a href="https://doc.rust-lang.org/std/fs/struct.Metadata.html#method.is_file"><code>Metadata::is_file</code></a>则是筛选出目录。</p>
<pre><pre class="playpen"><code class="language-rust"># #[macro_use]
# extern crate error_chain;
#
use std::{env, fs};

# error_chain! {
#     foreign_links {
#         Io(std::io::Error);
#         SystemTimeError(std::time::SystemTimeError);
#     }
# }
#
fn run() -&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(())
}
#
# quick_main!(run);
</code></pre></pre>
<a class="header" href="#查找给定路径的循环" id="查找给定路径的循环"><h2>查找给定路径的循环</h2></a>
<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>使用<a href="https://docs.rs/same-file/*/same_file/fn.is_same_file.html"><code>same_file::is_same_file</code></a>检测给定路径的循环。例如，可以通过符号链接，在 UNIX 系统上，创建一个循环：</p>
<pre><code class="language-bash">mkdir -p /tmp/foo/bar/baz
ln -s /tmp/foo/  /tmp/foo/bar/baz/qux
</code></pre>
<blockquote>
<p>/tmp/foo/bar/baz/qux == /tmp/foo/ =&gt; /tmp/foo/bar/baz =&gt; /tmp/foo/bar/baz/qux (重复循环)</p>
</blockquote>
<p>下面将断言，存在一个循环。</p>
<pre><pre class="playpen"><code class="language-rust no_run">extern crate same_file;

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>
<a class="header" href="#递归查找重复的文件名" id="递归查找重复的文件名"><h2>递归查找，重复的文件名</h2></a>
<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>在当前目录中，递归查找重复的文件名，只打印一次。</p>
<pre><pre class="playpen"><code class="language-rust no_run">extern crate walkdir;

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>
<a class="header" href="#递归查找所有文件匹配给定断言" id="递归查找所有文件匹配给定断言"><h2>递归查找所有文件，匹配给定断言</h2></a>
<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>在当前目录中查找，在前一天内有修改的 JSON 文件。使用<a href="https://docs.rs/walkdir/*/walkdir/struct.WalkDir.html#method.follow_links"><code>follow_links</code></a>确保，符号链接像普通目录和文件一样被遵循。</p>
<pre><pre class="playpen"><code class="language-rust no_run"># #[macro_use]
# extern crate error_chain;
extern crate walkdir;

use walkdir::WalkDir;
#
# error_chain! {
#     foreign_links {
#         WalkDir(walkdir::Error);
#         Io(std::io::Error);
#         SystemTime(std::time::SystemTimeError);
#     }
# }

fn run() -&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(())
}
#
# quick_main!(run);
</code></pre></pre>
<a class="header" href="#跳过点隐藏文件时遍历目录" id="跳过点隐藏文件时遍历目录"><h2>跳过点(隐藏)文件时，遍历目录</h2></a>
<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>使用<a href="https://docs.rs/walkdir/*/walkdir/struct.IntoIter.html#method.filter_entry"><code>filter_entry</code></a>深度递归，传递的是<code>is_not_hidden</code>断言，因此跳过隐藏的文件和目录。<a href="https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.filter"><code>Iterator::filter</code></a>应用到每个<a href="https://docs.rs/walkdir/*/walkdir/struct.DirEntry.html"><code>WalkDir::DirEntry</code></a>，即使父目录是隐藏目录。</p>
<p>根目录<code>&quot;.&quot;</code>的结果输出，是通过<code>is_not_hidden</code>断言中<a href="https://docs.rs/walkdir/*/walkdir/struct.DirEntry.html#method.depth"><code>WalkDir::depth</code></a>的使用。</p>
<pre><pre class="playpen"><code class="language-rust no_run">extern crate walkdir;

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>
<a class="header" href="#在给定深度目录递归计算文件大小" id="在给定深度目录递归计算文件大小"><h2>在给定深度(目录)，递归计算文件大小</h2></a>
<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>递归一定深度的目录，可以通过以下方式灵活设置：<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>方法。 3 个子文件夹深度的所有文件，其总和大小的计算，忽略根文件夹中的文件。</p>
<pre><pre class="playpen"><code class="language-rust">extern crate walkdir;

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>
<a class="header" href="#递归查找所有-png-文件" id="递归查找所有-png-文件"><h2>递归查找所有 PNG 文件</h2></a>
<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>递归查找，当前目录中的所有 PNG 文件。在这种情况下，<code>**</code>模式匹配当前目录和所有子目录。</p>
<p>可在任何路径部分，使用<code>**</code>模式。例如，<code>/media/**/*.png</code>，会匹配<code>media</code>下的所有 PNG，且是子目录。</p>
<pre><pre class="playpen"><code class="language-rust no_run"># #[macro_use]
# extern crate error_chain;
extern crate glob;

use glob::glob;
#
# error_chain! {
#     foreign_links {
#         Glob(glob::GlobError);
#         Pattern(glob::PatternError);
#     }
# }

fn run() -&gt; Result&lt;()&gt; {
    for entry in glob(&quot;**/*.png&quot;)? {
        println!(&quot;{}&quot;, entry?.display());
    }

    Ok(())
}
#
# quick_main!(run);
</code></pre></pre>
<a class="header" href="#查找具有给定模式的所有文件忽略文件名大小写" id="查找具有给定模式的所有文件忽略文件名大小写"><h2>查找具有给定模式的所有文件，忽略文件名大小写。</h2></a>
<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>在<code>/media/</code>目录中查找所有图像文件，要匹配<code>img_[0-9]*.png</code>模式。</p>
<p>一个自定义的<a href="https://docs.rs/glob/*/glob/struct.MatchOptions.html"><code>MatchOptions</code></a>结构，传递给<a href="https://docs.rs/glob/*/glob/fn.glob_with.html"><code>glob_with</code></a>函数，可以使全局模式不区分大小写，同时保留其他选项的默认<a href="https://doc.rust-lang.org/std/default/trait.Default.html"><code>Default</code></a>。</p>
<pre><pre class="playpen"><code class="language-rust no_run"># #[macro_use]
# extern crate error_chain;
extern crate glob;

use glob::{glob_with, MatchOptions};
#
# error_chain! {
#     foreign_links {
#         Glob(glob::GlobError);
#         Pattern(glob::PatternError);
#     }
# }

fn run() -&gt; Result&lt;()&gt; {
    let options = MatchOptions {
        case_sensitive: false,
        ..Default::default()
    };

    for entry in glob_with(&quot;/media/img_[0-9]*.png&quot;, &amp;options)? {
        println!(&quot;{}&quot;, entry?.display());
    }

    Ok(())
}
#
# quick_main!(run);
</code></pre></pre>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<a class="header" href="#硬件支持-1" id="硬件支持-1"><h1>硬件支持</h1></a>
<table><thead><tr><th> 食谱                                      </th><th> 箱子                          </th><th> 类别                                                  </th></tr></thead><tbody>
<tr><td> <a href="hardware/processor.zh.html#check-number-of-logical-cpu-cores">检查逻辑 CPU 的核数</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 -->
<a class="header" href="#处理器" id="处理器"><h1>处理器</h1></a>
<a class="header" href="#检查逻辑-cpu-的核数" id="检查逻辑-cpu-的核数"><h2>检查逻辑 CPU 的核数</h2></a>
<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>[<code>num_cpus::get</code>]会显示当前计算机中，使用的逻辑 CPU 核数。</p>
<pre><pre class="playpen"><code class="language-rust">extern crate num_cpus;

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 -->
<a class="header" href="#内存管理-1" id="内存管理-1"><h1>内存管理</h1></a>
<table><thead><tr><th> 食谱                                     </th><th> 箱子                                </th><th> 类别                                                                                </th></tr></thead><tbody>
<tr><td> <a href="mem/global_static.zh.html#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 -->
<a class="header" href="#常量" id="常量"><h1>常量</h1></a>
<a class="header" href="#声明延迟计算的常量" id="声明延迟计算的常量"><h2>声明，延迟计算的常量</h2></a>
<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>声明一个延迟计算的<a href="https://doc.rust-lang.org/std/collections/struct.HashMap.html"><code>HashMap</code></a>常量。 这个<a href="https://doc.rust-lang.org/std/collections/struct.HashMap.html"><code>HashMap</code></a>会执行一次，在之后，会存储在全局的静态引用（PRIVILEGES）背后。</p>
<pre><pre class="playpen"><code class="language-rust">#[macro_use]
extern crate 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 -->
<a class="header" href="#网络-1" id="网络-1"><h1>网络</h1></a>
<table><thead><tr><th> 食谱                                            </th><th> 箱子                </th><th> 类别                        </th></tr></thead><tbody>
<tr><td> <a href="net/server.zh.html#listen-on-unused-port-tcpip">侦听，未使用的端口 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 -->
<a class="header" href="#服务器" id="服务器"><h1>服务器</h1></a>
<a class="header" href="#侦听未使用的端口-tcpip" id="侦听未使用的端口-tcpip"><h2>侦听，未使用的端口 TCP/IP</h2></a>
<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>在本例中，端口会显示在控制台。且程序会一直监听，直到一个请求发出。<code>SocketAddrV4</code>会在端口(第二参数)设为 0 时，分配一个随机端口。</p>
<pre><pre class="playpen"><code class="language-rust 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 -->
<a class="header" href="#操作系统-1" id="操作系统-1"><h1>操作系统</h1></a>
<table><thead><tr><th> 食谱                                                                                  </th><th> 箱子                    </th><th> 类别                                                                          </th></tr></thead><tbody>
<tr><td> <a href="os/external.zh.html#run-an-external-command-and-process-stdout">运行外部命令，并处理 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.zh.html#run-an-external-command-passing-it-stdin-and-check-for-an-error-code">运行传递到 stdin 的外部命令，并检查错误代码</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.zh.html#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.zh.html#redirect-both-stdout-and-stderr-of-child-process-to-the-same-file">将子进程的 stdout 和 stderr ，重定向到同一文件</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.zh.html#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>
</tbody></table>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<a class="header" href="#外部命令" id="外部命令"><h1>外部命令</h1></a>
<a class="header" href="#运行外部命令并处理-stdout" id="运行外部命令并处理-stdout"><h2>运行外部命令，并处理 stdout</h2></a>
<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>把<code>git log --oneline</code>，作为一个外部<a href="https://doc.rust-lang.org/std/process/struct.Command.html"><code>Command</code></a>，并检查其<a href="https://doc.rust-lang.org/std/process/struct.Output.html"><code>Output</code></a>，和用<a href="https://docs.rs/regex/*/regex/struct.Regex.html"><code>Regex</code></a>获取最后 5 次提交的哈希与消息。</p>
<pre><pre class="playpen"><code class="language-rust no_run"># #[macro_use]
# extern crate error_chain;
extern crate regex;

use std::process::Command;
use regex::Regex;
#
# error_chain!{
#     foreign_links {
#         Io(std::io::Error);
#         Regex(regex::Error);
#         Utf8(std::string::FromUtf8Error);
#     }
# }

#[derive(PartialEq, Default, Clone, Debug)]
struct Commit {
    hash: String,
    message: String,
}

fn run() -&gt; Result&lt;()&gt; {
    let output = Command::new(&quot;git&quot;).arg(&quot;log&quot;).arg(&quot;--oneline&quot;).output()?;

    if !output.status.success() {
        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(())
}
#
# quick_main!(run);
</code></pre></pre>
<a class="header" href="#运行传递-stdin-的外部命令并检查错误代码" id="运行传递-stdin-的外部命令并检查错误代码"><h2>运行传递 stdin 的外部命令，并检查错误代码</h2></a>
<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>使用外部<a href="https://doc.rust-lang.org/std/process/struct.Command.html"><code>Command</code></a>，打开<code>python</code>解释程序，并将 python (语言)语句传递给它，以供执行。之后的输出<a href="https://doc.rust-lang.org/std/process/struct.Output.html"><code>Output</code></a>会被解析。</p>
<pre><pre class="playpen"><code class="language-rust no_run"># #[macro_use]
# extern crate error_chain;
#
use std::collections::HashSet;
use std::io::Write;
use std::process::{Command, Stdio};
#
# error_chain!{
#     errors { CmdError }
#     foreign_links {
#         Io(std::io::Error);
#         Utf8(std::string::FromUtf8Error);
#     }
# }

fn run() -&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)?;
        bail!(&quot;External command failed:\n {}&quot;, err)
    }
}
#
# quick_main!(run);
</code></pre></pre>
<a class="header" href="#运行管道的外部命令" id="运行管道的外部命令"><h2>运行管道的外部命令</h2></a>
<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>显示，当前工作目录中，10<sup>个</sup>最大的文件和子目录。它相当于运行：<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>们代表一个过程。一个子进程的输出用<a href="https://doc.rust-lang.org/std/process/struct.Stdio.html"><code>Stdio::piped</code></a>，在父级和子级之间捕获。</p>
<pre><pre class="playpen"><code class="language-rust no_run"># #[macro_use]
# extern crate error_chain;
#
use std::process::{Command, Stdio};
#
# error_chain! {
#     foreign_links {
#         Io(std::io::Error);
#         Utf8(std::string::FromUtf8Error);
#     }
# }

fn run() -&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(())
}
#
# quick_main!(run);
</code></pre></pre>
<a class="header" href="#将子进程的-stdout-和-stderr-重定向到同一文件" id="将子进程的-stdout-和-stderr-重定向到同一文件"><h2>将子进程的 stdout 和 stderr ，重定向到同一文件</h2></a>
<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）一个子进程，并重定向<code>stdout</code>和<code>stderr</code>到同一个文件。它与<a href="#run-piped-external-commands">运行管道的外部命令</a>差不多的想法，但会用<a href="https://doc.rust-lang.org/std/process/struct.Stdio.html"><code>process::Stdio</code></a>，把输出写入到指定的文件。<a href="https://doc.rust-lang.org/std/fs/struct.File.html#method.try_clone"><code>File::try_clone</code></a>引用相同文件的<code>stdout</code>和<code>stderr</code>控制（Handle）。它将确保两个 Handles 使用相同的光标位置写入。</p>
<p>下面的食谱，相当于运行 unix shell 命令：<code>ls . oops &gt;out.txt 2&gt;&amp;1</code>.</p>
<pre><pre class="playpen"><code class="language-rust 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>
<a class="header" href="#连续处理子进程的输出" id="连续处理子进程的输出"><h2>连续处理，子进程的输出</h2></a>
<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>在<a href="#run-an-external-command-and-process-stdout">运行外部命令，并处理 stdout</a>食谱中，<code>stdout</code>的处理会在外部<a href="https://doc.rust-lang.org/std/process/struct.Command.html"><code>Command</code></a>完成之后执行。而本食谱接下来的方法是，调用<a href="https://doc.rust-lang.org/std/process/struct.Stdio.html"><code>Stdio::piped</code></a>创建一个管道，并在<a href="https://doc.rust-lang.org/std/io/struct.BufReader.html"><code>BufReader</code></a>每次更新，都读取<code>stdout</code>(连续)。</p>
<p>下面的食谱，相当于 unix shell 命令：<code>journalctl | grep usb</code>.</p>
<pre><pre class="playpen"><code class="language-rust 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>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<a class="header" href="#科学类-1" id="科学类-1"><h1>科学类</h1></a>
<a class="header" href="#数学-1" id="数学-1"><h2>数学</h2></a>
<table><thead><tr><th> 食谱                                                            </th><th> 箱子                          </th><th> 类别                                </th></tr></thead><tbody>
<tr><td> <a href="science/mathematics/linear_algebra.zh.html#vector-sum">vector 和</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.zh.html#vector-norm">vector 范数</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.zh.html#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.zh.html#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.zh.html#multiply-a-scalar-with-a-vector-with-a-matrix">用 vector 和矩阵，相乘一个标量</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.zh.html#invert-matrix">反转矩阵</a>                                       </td><td> [![nalgebra-badge]][nalgebra] </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.zh.html#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.zh.html#verifying-tan-is-equal-to-sin-divided-by-cos">验证 tan 等于 sin 除以 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.zh.html#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.zh.html#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.zh.html#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.zh.html#mathematical-functions">复数的数学函数</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.zh.html#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.zh.html#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.zh.html#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 -->
<a class="header" href="#数学-2" id="数学-2"><h2>数学</h2></a>
<table><thead><tr><th> 食谱                                                            </th><th> 箱子                          </th><th> 类别                                </th></tr></thead><tbody>
<tr><td> <a href="science/mathematics/linear_algebra.zh.html#vector-sum">vector 和</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.zh.html#vector-norm">vector 范数</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.zh.html#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.zh.html#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.zh.html#multiply-a-scalar-with-a-vector-with-a-matrix">用 vector 和矩阵，相乘一个标量</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.zh.html#invert-matrix">反转矩阵</a>                                       </td><td> [![nalgebra-badge]][nalgebra] </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.zh.html#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.zh.html#verifying-tan-is-equal-to-sin-divided-by-cos">验证 tan 等于 sin 除以 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.zh.html#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.zh.html#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.zh.html#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.zh.html#mathematical-functions">复数的数学函数</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.zh.html#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.zh.html#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.zh.html#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 -->
<a class="header" href="#线性代数" id="线性代数"><h1>线性代数</h1></a>
<a class="header" href="#vector-总和" id="vector-总和"><h2>vector 总和</h2></a>
<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>这个<a href="https://docs.rs/crate/ndarray/*">ndarray</a>箱子支持多种创建数组的方法 —— 该食谱主要专注<code>std::Vec</code>的<a href="https://docs.rs/ndarray/*/ndarray/struct.ArrayBase.html"><code>ndarray::Array</code></a>的创建，通过<a href="https://docs.rs/ndarray/*/ndarray/struct.ArrayBase.html#method.from_vec"><code>from_vec</code></a>完成。把两个数组加在一起和把两个数字加在一起，没有什么不同。在数组上，使用<code>&amp;</code>符号，能在一次算术运算中，阻止消耗数组的操作。没有<code>&amp;</code>的话，数组会被消耗。</p>
<p>在第一个示例中，数组<code>a</code>和<code>b</code>在 let 语句（<code>z = a + b</code>）中移动：。 在第二个示例中，数组<code>c</code>和<code>d</code>不会移动，而是为<code>w</code>创建一个新的数组。在 vector 总和（<code>w = &amp;c + &amp;d</code>）之后，更新<code>c</code>或<code>d</code>，对<code>w</code>值是没有影响的。另外，在打印<code>c</code>时按预期工作，打印<code>b</code>时出错，因为移动了。见<a href="https://docs.rs/ndarray/*/ndarray/struct.ArrayBase.html#binary-operators-with-two-arrays">两个数组的二元运算符</a>更多细节。</p>
<pre><pre class="playpen"><code class="language-rust">extern crate ndarray;
use ndarray::Array;

fn main() {
  let a = Array::from_vec(vec![1., 2., 3., 4., 5.]);
  let b = Array::from_vec(vec![5., 4., 3., 2., 1.]);
  let mut c = Array::from_vec(vec![1., 2., 3., 4., 5.]);
  let mut d = Array::from_vec(vec![5., 4., 3., 2., 1.]);

  let z = a + b;
  let w =  &amp;c + &amp;d;

  let epsilon = 1e-8;
  for elem in z.iter() {
    let diff: f32 = *elem - 6.;
    assert!(diff.abs() &lt; epsilon);
  }

  println!(&quot;c = {}&quot;, c);
  c[0] = 10.;
  d[1] = 10.;

  for elem in w.iter() {
    let diff: f32 = *elem - 6.;
    assert!(diff.abs() &lt; epsilon);
  }

}
</code></pre></pre>
<a class="header" href="#vector-范数" id="vector-范数"><h2>vector 范数</h2></a>
<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>这个食谱演示了<a href="https://docs.rs/ndarray/*/ndarray/type.Array1.html"><code>Array1</code></a>类型，<a href="https://docs.rs/ndarray/*/ndarray/type.ArrayView1.html"><code>ArrayView1</code></a>类型，<a href="https://docs.rs/ndarray/*/ndarray/struct.ArrayBase.html#method.fold"><code>fold</code></a>方法，以及<a href="https://docs.rs/ndarray/*/ndarray/struct.ArrayBase.html#method.dot"><code>dot</code></a>方法，它计算给定 vector 的<a href="http://mathworld.wolfram.com/L1-Norm.html">l1</a>和<a href="http://mathworld.wolfram.com/L2-Norm.html">l2</a>范数。l2 范数的计算是两者中，比较简单的一个，因为它是一个 vector 的点乘积的平方根，如<code>l2_norm</code>函数所示。而 l1 范数，在<code>l1_norm</code>函数，由<code>fold</code>方法完成，它是元素绝对值的总和。（这也可以用<code>x.mapv(f64::abs).scalar_sum()</code>执行，但这将为<code>mapv</code>的结果分配一个新的数组。）</p>
<p>注意<code>l1_norm</code>和<code>l2_norm</code>都拿了<a href="https://docs.rs/ndarray/*/ndarray/type.ArrayView1.html"><code>ArrayView1</code></a>类型。这个食谱考虑了 vector 范数，因此范数函数，只需要接受一维 view（就是<a href="https://docs.rs/ndarray/*/ndarray/type.ArrayView1.html"><code>ArrayView1</code></a>）。当这个函数换成接受一个<code>&amp;Array1&lt;f64&gt;</code>类型参数，这将要求调用者具有，所有权数组的一个引用，这比仅对一个 view 的访问，更为严格（因为一个 view，是可以通过任何 array 或 view 创建的，而不仅仅是所有权数组）。对调用者来说，最方便的参数类型是<code>&amp;ArrayBase&lt;S, Ix1&gt; where S: Data</code>，因为调用者可以使用<code>&amp;array</code>或<code>&amp;view</code>，而不是<code>x.view()</code>。 如果该函数是你公共 API 的一部分，那么对于用户来说，这可能是一个更好的选择，但是对于内部函数来说，简洁的<code>ArrayView1&lt;f64&gt;</code>可能更好。</p>
<pre><pre class="playpen"><code class="language-rust">#[macro_use(array)]
extern crate ndarray;

use ndarray::{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>
<a class="header" href="#矩阵相加" id="矩阵相加"><h2>矩阵相加</h2></a>
<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><a href="https://docs.rs/ndarray/*/ndarray/fn.arr2.html"><code>ndarray::arr2</code></a>创建两维矩阵，并把它们加在一起。</p>
<pre><pre class="playpen"><code class="language-rust">extern crate ndarray;

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]]);

    println!(&quot;Sum: {}&quot;, a + b);
}
</code></pre></pre>
<a class="header" href="#矩阵乘法" id="矩阵乘法"><h2>矩阵乘法</h2></a>
<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><a href="https://docs.rs/ndarray/*/ndarray/fn.arr2.html"><code>ndarray::arr2</code></a>创建两个矩阵，并用<a href="https://docs.rs/ndarray/*/ndarray/struct.ArrayBase.html#method.dot-1"><code>ndarray::ArrayBase::dot</code></a>对它们执行矩阵乘法。</p>
<pre><pre class="playpen"><code class="language-rust">extern crate ndarray;

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>
<a class="header" href="#用-vector-和-矩阵乘一个标量" id="用-vector-和-矩阵乘一个标量"><h2>用 vector 和 矩阵，乘一个标量</h2></a>
<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>用<a href="https://docs.rs/ndarray/*/ndarray/fn.arr1.html"><code>ndarray::arr1</code></a>创建一个，一维数组（vector），二维数组（矩阵）就用<a href="https://docs.rs/ndarray/*/ndarray/fn.arr2.html"><code>ndarray::arr2</code></a>。 首先，将一个标量乘以 vector ，得到另一个 vector。然后，矩阵用<a href="https://docs.rs/ndarray/*/ndarray/struct.ArrayBase.html#method.dot-1"><code>ndarray::Array2::dot</code></a>，乘以这个新的 vector。 （<code>dot</code>会执行矩阵乘法，而<code>*</code>运算符<code>scalar * vector</code>，执行逐个元素的相乘。）在<code>ndarray</code>中，一维数组根据上下文，可以解释为行或列 vector。如果 vector 表示的方向很重要，则要用二维数组的一行或一列。在本例中，vector 是右手边的一维数组，因此，<code>dot</code>将其作为列 vector 处理。</p>
<pre><pre class="playpen"><code class="language-rust">extern crate ndarray;

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>
<a class="header" href="#反转矩阵" id="反转矩阵"><h2>反转矩阵</h2></a>
<p>[![nalgebra-badge]][nalgebra] <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 href="https://docs.rs/nalgebra/*/nalgebra/base/type.Matrix3.html"><code>nalgebra::Matrix3</code></a>创建 3x3 矩阵，如果可能的话，将其反转。</p>
<pre><pre class="playpen"><code class="language-rust">extern crate nalgebra;

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>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<a class="header" href="#三角法" id="三角法"><h1>三角法</h1></a>
<a class="header" href="#计算一个三角形的边长" id="计算一个三角形的边长"><h2>计算一个三角形的边长</h2></a>
<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>计算直角三角形斜边的长度，斜边的角度为 2 弧度，对边的长度为 80。</p>
<pre><pre class="playpen"><code class="language-rust">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>
<a class="header" href="#验证-tan-等于sin-除以-cos" id="验证-tan-等于sin-除以-cos"><h2>验证 tan 等于，sin 除以 cos</h2></a>
<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>验证 <code>tan(x)</code>是否等于 <code>sin(x)/cos(x)</code>，给出 <code>x=6</code>。</p>
<pre><pre class="playpen"><code class="language-rust">fn main() {
    let x: f64 = 6.0;

    let a = x.tan();
    let b = x.sin()/x.cos();

    assert_eq!(a, b);
}
</code></pre></pre>
<a class="header" href="#地球上两点之间的距离" id="地球上两点之间的距离"><h2>地球上，两点之间的距离</h2></a>
<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>默认情况下，rust 提供数学[浮点数方法]，如三角函数、平方根、弧度和度数之间的转换函数等。</p>
<p>下面的示例使用<a href="https://en.wikipedia.org/wiki/Haversine_formula">半正矢公式</a>，计算地球上两点的公里距离。这两个点用经纬度对表示。然后，<a href="https://doc.rust-lang.org/std/primitive.f64.html#method.to_radians"><code>to_radians</code></a>把它们转换成弧度。<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>和<a href="https://doc.rust-lang.org/std/primitive.f64.html#method.sqrt"><code>sqrt</code></a>计算中心角。最后，就可以计算距离。</p>
<pre><pre class="playpen"><code class="language-rust">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 -->
<a class="header" href="#复数" id="复数"><h1>复数</h1></a>
<a class="header" href="#创建复数" id="创建复数"><h2>创建复数</h2></a>
<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>创建<a href="https://autumnai.github.io/cuticula/num/complex/struct.Complex.html"><code>num::complex::Complex</code></a>类型的复数。复数的实部和虚部必须是同一类型。</p>
<pre><pre class="playpen"><code class="language-rust">extern crate num;

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>
<a class="header" href="#复数相加" id="复数相加"><h2>复数相加</h2></a>
<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>对复数执行数学运算与内置类型相同：涉及的数字必须是同一类型（即浮点数或整数）。</p>
<pre><pre class="playpen"><code class="language-rust">extern crate num;

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>
<a class="header" href="#数学函数" id="数学函数"><h2>数学函数</h2></a>
<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>当涉及如何与其他数学函数交互时，复数有一系列有趣的性质，尤其是类似数字的正弦家族函数。要将这些函数与复数一起使用，复数类型有一些内置函数，所有这些函数都可以找：<a href="https://autumnai.github.io/cuticula/num/complex/struct.Complex.html"><code>num::complex::Complex</code></a>。</p>
<pre><pre class="playpen"><code class="language-rust">extern crate num;

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 -->
<a class="header" href="#统计" id="统计"><h1>统计</h1></a>
<a class="header" href="#集中趋势度量" id="集中趋势度量"><h3>集中趋势度量</h3></a>
<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>这些例子计算了包含在一个 Rust 数组中，数据集的集中趋势度量。对于空数据集，可能没有要计算的平均值、中值或常见值，因此，每个函数都返回一个给调用方处理的[<code>Option</code>]。</p>
<p>第一个示例，计算平均值(集合中，总和/数量)，通过生成对<code>data</code>引用的迭代器，并使用[<code>sum</code>]和[<code>len</code>]分别确定值的总值和计数。</p>
<pre><pre class="playpen"><code class="language-rust">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>第二个示例使用 QuickSelect 算法，计算中间值，这避免了[<code>sort</code>]的完整排序，只对已知可能包含中间值的数据集分区，进行排序。这用到[<code>cmp</code>]和[<code>Ordering</code>]，简洁决定下一个要检查的分区，以及在每个步骤中，[<code>split_at</code>]为下一个分区进行静态选择。</p>
<pre><pre class="playpen"><code class="language-rust">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>最后一个示例是计算常见值，使用可变的[<code>HashMap</code>]，从集合中，收集每个不同整数的计数，会用到一个[<code>fold</code>]以及[<code>entry</code>]API。[<code>HashMap</code>]中，会用[<code>max_by_key</code>]搞到最常见的值。</p>
<pre><pre class="playpen"><code class="language-rust">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>
<a class="header" href="#标准偏差" id="标准偏差"><h3>标准偏差</h3></a>
<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>此示例计算一组测量集合的标准偏差，和 z 分数。</p>
<p>标准偏差，定义为方差的平方根。此处()用 <code>f32</code> 的 [<code>sqrt</code>]计算，方差则是，每次测量与平均值[<code>mean</code>]之间差的平方的总和[<code>sum</code>]。</p>
<p>z 分数是（单个测量值 - 数据集的[<code>mean</code>] / 标准方差）。</p>
<pre><pre class="playpen"><code class="language-rust">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 -->
<a class="header" href="#杂" id="杂"><h1>杂</h1></a>
<a class="header" href="#大整数" id="大整数"><h2>大整数</h2></a>
<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>可以使用<a href="https://docs.rs/num/0.2.0/num/struct.BigInt.html"><code>BigInt</code></a>，计算超过 128 位的整数。</p>
<pre><pre class="playpen"><code class="language-rust">extern crate num;

use num::bigint::{BigInt, ToBigInt};

fn factorial(x: i32) -&gt; BigInt {
    if let Some(mut factorial) = 1.to_bigint() {
        for i in 1..(x+1) {
            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 -->
<a class="header" href="#文本处理-1" id="文本处理-1"><h1>文本处理</h1></a>
<table><thead><tr><th> 食谱                                                                     </th><th> 箱子                                                        </th><th> 类别                                                </th></tr></thead><tbody>
<tr><td> <a href="text/string_parsing.zh.html#collect-unicode-graphemes">收集 Unicode 字形</a>                                </td><td> [![unicode-segmentation-badge]][unicode-segmentation]       </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.zh.html#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.zh.html#extract-a-list-of-unique-hashtags-from-a-text">从文本中，提取独一的<code>#</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> <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.zh.html#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.zh.html#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.zh.html#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.zh.html#implement-the-fromstr-trait-for-a-custom-struct">为一个自定义<code>struct</code>，实现<code>FromStr</code>trait</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 -->
<a class="header" href="#正则表达式" id="正则表达式"><h1>正则表达式</h1></a>
<a class="header" href="#电子邮件地址提取登录名并验证" id="电子邮件地址提取登录名并验证"><h2>电子邮件地址提取登录名，并验证</h2></a>
<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>验证电子邮件地址的格式是否正确，并提取<code>@</code>符号之前的所有内容。</p>
<pre><pre class="playpen"><code class="language-rust">#[macro_use]
extern crate lazy_static;
extern crate regex;

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>
<a class="header" href="#从文本中提取单一的标签的列表" id="从文本中提取单一的标签的列表"><h2>从文本中，提取单一的<code>#</code>标签的列表</h2></a>
<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>从文本中，提取、排序和单个化<code>#</code>标签的列表。</p>
<p>这里给出的<code>#</code>标签 正则式，只捕获以字母开头的<code>#</code>标签。完整的<a href="https://github.com/twitter/twitter-text/blob/c9fc09782efe59af4ee82855768cfaf36273e170/java/src/com/twitter/Regex.java#L255">Twitter #标签 正则式</a>更复杂。</p>
<pre><pre class="playpen"><code class="language-rust">extern crate regex;
#[macro_use]
extern crate 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>
<a class="header" href="#从文本中提取电话号码" id="从文本中提取电话号码"><h2>从文本中，提取电话号码</h2></a>
<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>处理字符串时使，用<a href="https://docs.rs/regex/*/regex/struct.Regex.html#method.captures_iter"><code>Regex::captures_iter</code></a>捕捉多个电话号码。这里的示例是，美国会议电话号码。</p>
<pre><pre class="playpen"><code class="language-rust"># #[macro_use]
# extern crate error_chain;
extern crate regex;

use regex::Regex;
use std::fmt;
#
# error_chain!{
#     foreign_links {
#         Regex(regex::Error);
#         Io(std::io::Error);
#     }
# }

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 run() -&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(())
}
#
# quick_main!(run);
</code></pre></pre>
<a class="header" href="#通过匹配多个正则表达式筛选日志文件" id="通过匹配多个正则表达式筛选日志文件"><h2>通过匹配多个正则表达式，筛选日志文件</h2></a>
<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>读取名为<code>application.log</code>的文件，并且只输出包含“version x.x.x”、或一些 IP 地址跟着端口 443（例如“192.168.0.1:443”）或特殊 warning 的那些行。</p>
<p>一个<a href="https://docs.rs/regex/*/regex/struct.RegexSetBuilder.html"><code>regex::RegexSetBuilder</code></a>组成一个<a href="https://docs.rs/regex/*/regex/struct.RegexSet.html"><code>regex::RegexSet</code></a>。 因为反斜杠在正则表达式中，非常常见，所以使用<a href="https://doc.rust-lang.org/reference/tokens.html#raw-string-literals">原始字符串文本</a>能让它们更具可读性。</p>
<pre><pre class="playpen"><code class="language-rust no_run"># #[macro_use]
# extern crate error_chain;
extern crate regex;

use std::fs::File;
use std::io::{BufReader, BufRead};
use regex::RegexSetBuilder;

# error_chain! {
#     foreign_links {
#         Io(std::io::Error);
#         Regex(regex::Error);
#     }
# }
#
fn run() -&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(())
}
#
# quick_main!(run);
</code></pre></pre>
<a class="header" href="#将一个文本模式的所有出现项替换为另一个模式" id="将一个文本模式的所有出现项替换为另一个模式"><h2>将一个文本模式的所有出现项，替换为另一个模式。</h2></a>
<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>将所有出现的标准 ISO 8601 <em>YYY-MM－DD</em> 的日期模式，替换等效的带斜线美式英文日期。例如<code>2013-01-15</code>变成<code>01/15/2013</code>.</p>
<p>方法<a href="https://docs.rs/regex/*/regex/struct.Regex.html#method.replace_all"><code>Regex::replace_all</code></a>会替换整个正则式的所有出现项。<code>&amp;str</code>实现了<code>Replacer</code>trait，这允许类似<code>$abcde</code>这样的变量，去引用在搜索的正则式中，相应的命名捕获组<code>(?P&lt;abcde&gt;REGEX)</code>。见<a href="https://docs.rs/regex/*/regex/struct.Regex.html#replacement-string-syntax">替换字符串语法</a>示例，和转义的细节。</p>
<pre><pre class="playpen"><code class="language-rust">extern crate regex;
#[macro_use]
extern crate 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 -->
<a class="header" href="#字符串解析" id="字符串解析"><h1>字符串解析</h1></a>
<a class="header" href="#收集-unicode-字形" id="收集-unicode-字形"><h2>收集 Unicode 字形</h2></a>
<p><a href="https://docs.rs/unicode-segmentation/1.2.1/unicode_segmentation/">![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><a href="https://docs.rs/unicode-segmentation/1.2.1/unicode_segmentation/"><code>unicode-segmentation</code></a>箱子的<a href="https://docs.rs/unicode-segmentation/*/unicode_segmentation/trait.UnicodeSegmentation.html#tymethod.graphemes"><code>UnicodeSegmentation::graphemes</code></a>函数，可用来，从 UTF-8 字符串中，收集单个 Unicode 字形。</p>
<pre><pre class="playpen"><code class="language-rust">#[macro_use]
extern crate unicode_segmentation;
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>
<a class="header" href="#为一个自定义struct实现fromstrtrait" id="为一个自定义struct实现fromstrtrait"><h2>为一个自定义<code>struct</code>，实现<code>FromStr</code>trait</h2></a>
<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>创建一个自定义结构<code>RGB</code>，并实现<code>FromStr</code>trait，能将提供的颜色 hex 代码，转换为 RGB 颜色代码。</p>
<pre><pre class="playpen"><code class="language-rust">use std::str::FromStr;

#[derive(Debug, PartialEq)]
struct RGB {
    r: u8,
    g: u8,
    b: u8,
}

impl FromStr for RGB {
    type Err = std::num::ParseIntError;

    // 解析一个颜色 hex 代码，如 '#rRgGbB..' ，将其变为一个'RGB' 实例。
    fn from_str(hex_code: &amp;str) -&gt; Result&lt;Self, Self::Err&gt; {

        // u8::from_str_radix(src: &amp;str, radix: u32) 将一个给予基础的字符串切片，转换到 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);
        }
    }

    // 测试一下， from_str 的执行是否符合期盼。
    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 -->
<a class="header" href="#网页编程-1" id="网页编程-1"><h1>网页编程</h1></a>
<a class="header" href="#刮擦网页-1" id="刮擦网页-1"><h2>刮擦网页</h2></a>
<table><thead><tr><th> 食谱                                                                   </th><th> 箱子                                                                      </th><th> 类别                        </th></tr></thead><tbody>
<tr><td> <a href="web/scraping.zh.html#extract-all-links-from-a-webpage-html">从网页 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.zh.html#check-a-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.zh.html#extract-all-unique-links-from-a-mediawiki-markup">从 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>
<a class="header" href="#统一资源位置url-1" id="统一资源位置url-1"><h2>统一资源位置（URL）</h2></a>
<table><thead><tr><th> 食谱                                                </th><th> 箱子                </th><th> 类别                        </th></tr></thead><tbody>
<tr><td> <a href="web/url.zh.html#parse-a-url-from-a-string-to-a-url-type">将字符串的一个 URL，解析为<code>Url</code>类型</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.zh.html#create-a-base-url-by-removing-path-segments">通过移除路径段，创建一个 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.zh.html#create-new-urls-from-a-base-url">从 base URL ，创建新的 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.zh.html#extract-the-url-origin-scheme--host--port">提取 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.zh.html#remove-fragment-identifiers-and-query-pairs-from-a-url">从 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>
<a class="header" href="#媒体类型mime-1" id="媒体类型mime-1"><h2>媒体类型（MIME）</h2></a>
<table><thead><tr><th> 食谱                                                     </th><th> 箱子                                              </th><th> 类别                                                              </th></tr></thead><tbody>
<tr><td> <a href="web/mime.zh.html#get-mime-type-from-string">从字符串，获取 MIME 类型</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.zh.html#get-mime-type-from-filename">从文件名，获取 MIME 类型</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.zh.html#parse-the-mime-type-of-a-http-response">解析 HTTP 响应的 MIME 类型</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>
<a class="header" href="#客户端-1" id="客户端-1"><h2>客户端</h2></a>
<table><thead><tr><th> 食谱                                                         </th><th> 箱子                                                    </th><th> 类别                                                                  </th></tr></thead><tbody>
<tr><td> <a href="web/clients/requests.zh.html#make-a-http-get-request">发出 HTTP GET 请求</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.zh.html#query-the-github-api">查询 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.zh.html#check-if-an-api-resource-exists">检查 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>                             </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.zh.html#create-and-delete-gist-with-github-api">使用 GitHub API ，创建和删除 Gist</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.zh.html#consume-a-paginated-restful-api">使用一个（具备）分页的 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.zh.html#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.zh.html#make-a-partial-download-with-http-range-headers">使用 HTTP range 标头，进行部分下载</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.zh.html#post-a-file-to-paste-rs">POST 文件，到 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 -->
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<a class="header" href="#提取链接" id="提取链接"><h1>提取链接</h1></a>
<a class="header" href="#从网页-html-中提取所有链接" id="从网页-html-中提取所有链接"><h2>从网页 HTML 中，提取所有链接</h2></a>
<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>使用<a href="https://docs.rs/reqwest/*/reqwest/fn.get.html"><code>reqwest::get</code></a>，去执行一个 HTTP GET 请求，然后使用<a href="https://docs.rs/select/*/select/document/struct.Document.html#method.from_read"><code>Document::from_read</code></a>将响应解析为 HTML 文档。拿<a href="https://docs.rs/select/*/select/document/struct.Document.html#method.find"><code>find</code></a>，配上<a href="https://docs.rs/select/*/select/predicate/struct.Name.html"><code>Name</code></a>标准“a”，检索所有链接。在<a href="https://docs.rs/select/*/select/selection/struct.Selection.html"><code>Selection</code></a>上，调用<a href="https://doc.rust-lang.org/core/iter/trait.Iterator.html#method.filter_map"><code>filter_map</code></a>留下链接中 URL，包含“href”<a href="attribute"><code>attr</code></a>的。</p>
<pre><pre class="playpen"><code class="language-rust no_run"># #[macro_use]
# extern crate error_chain;
extern crate reqwest;
extern crate select;

use select::document::Document;
use select::predicate::Name;
#
# error_chain! {
#    foreign_links {
#        ReqError(reqwest::Error);
#        IoError(std::io::Error);
#    }
# }

fn run() -&gt; Result&lt;()&gt; {
    let res = reqwest::get(&quot;https://www.rust-lang.org/en-US/&quot;)?;

    Document::from_read(res)?
        .find(Name(&quot;a&quot;))
        .filter_map(|n| n.attr(&quot;href&quot;))
        .for_each(|x| println!(&quot;{}&quot;, x));

    Ok(())
}
#
# quick_main!(run);
</code></pre></pre>
<a class="header" href="#检查网页是否有断开的链接" id="检查网页是否有断开的链接"><h2>检查网页是否，有断开的链接</h2></a>
<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>调用<code>get_base_url</code>以检索 base URL。如果文档有 base 标签，从 base 标签获取<a href="https://docs.rs/select/*/select/node/struct.Node.html#method.attr"><code>attr</code></a>。<a href="https://docs.rs/url/*/url/enum.Position.html#variant.BeforePath"><code>Position::BeforePath</code></a>作为 原始 URL 的 默认行为。</p>
<p>遍历文档中的链接，并用<a href="https://docs.rs/url/*/url/struct.ParseOptions.html"><code>url::ParseOptions</code></a>和<a href="https://docs.rs/url/*/url/struct.Url.html#method.parse"><code>Url::parse</code></a>解析。用 <code>reqwest</code> 对链接做请求，并验证<a href="https://docs.rs/reqwest/*/reqwest/struct.StatusCode.html"><code>StatusCode</code></a>。</p>
<pre><pre class="playpen"><code class="language-rust no_run"># #[macro_use]
# extern crate error_chain;
extern crate reqwest;
extern crate select;
extern crate url;

use std::collections::HashSet;

use url::{Url, Position};
use reqwest::StatusCode;
use select::document::Document;
use select::predicate::Name;
#
# error_chain! {
#   foreign_links {
#       ReqError(reqwest::Error);
#       IoError(std::io::Error);
#       UrlParseError(url::ParseError);
#   }
# }

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)
}

fn check_link(url: &amp;Url) -&gt; Result&lt;bool&gt; {
    let res = reqwest::get(url.as_ref())?;

    Ok(res.status() != StatusCode::NOT_FOUND)
}

fn run() -&gt; Result&lt;()&gt; {
    let url = Url::parse(&quot;https://www.rust-lang.org/en-US/&quot;)?;

    let res = reqwest::get(url.as_ref())?;
    let document = Document::from_read(res)?;

    let base_url = get_base_url(&amp;url, &amp;document)?;

    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();

    links
        .iter()
        .filter(|link| check_link(link).ok() == Some(false))
        .for_each(|x| println!(&quot;{} is broken.&quot;, x));

    Ok(())
}
#
# quick_main!(run);
</code></pre></pre>
<a class="header" href="#从-mediawiki-markup-中提取所有独一链接" id="从-mediawiki-markup-中提取所有独一链接"><h2>从 Mediawiki markup 中，提取所有独一链接</h2></a>
<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>使用<a href="https://docs.rs/reqwest/*/reqwest/fn.get.html"><code>reqwest::get</code></a>，拉取 MediaWiki 源页面，然后<a href="https://docs.rs/regex/*/regex/struct.Regex.html#method.captures_iter"><code>Regex::captures_iter</code></a>查找内部和外部链接的所有条目。使用<a href="https://doc.rust-lang.org/std/borrow/enum.Cow.html"><code>Cow</code></a>避免过度<a href="https://doc.rust-lang.org/std/string/struct.String.html"><code>String</code></a>分配 (单一)。</p>
<blockquote>
<p><a href="https://wiki.jikexueyuan.com/project/rust-primer/intoborrow/cow.html">极客学院：Cow</a></p>
</blockquote>
<p>Mediawiki 链接语法，<a href="https://www.mediawiki.org/wiki/Help:Links">在这里</a>有所描述。</p>
<pre><pre class="playpen"><code class="language-rust no_run"># #[macro_use]
# extern crate error_chain;
#[macro_use]
extern crate lazy_static;
extern crate reqwest;
extern crate regex;

use std::io::Read;
use std::collections::HashSet;
use std::borrow::Cow;
use regex::Regex;

# error_chain! {
#     foreign_links {
#         Io(std::io::Error);
#         Reqwest(reqwest::Error);
#         Regex(regex::Error);
#     }
# }
#
fn extract_links(content: &amp;str) -&gt; Result&lt;HashSet&lt;Cow&lt;str&gt;&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();

    Ok(links)
}

fn run() -&gt; Result&lt;()&gt; {
    let mut content = String::new();
    reqwest::get(
        &quot;https://en.wikipedia.org/w/index.php?title=Rust_(programming_language)&amp;action=raw&quot;,
    )?
        .read_to_string(&amp;mut content)?;

    println!(&quot;{:#?}&quot;, extract_links(&amp;content)?);

    Ok(())
}
#
# quick_main!(run);
</code></pre></pre>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<a class="header" href="#统一资源位置" id="统一资源位置"><h1>统一资源位置</h1></a>
<a class="header" href="#将字符串的一个-url解析为url类型" id="将字符串的一个-url解析为url类型"><h2>将字符串的一个 URL，解析为<code>Url</code>类型</h2></a>
<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 href="https://docs.rs/url/*/url/struct.Url.html#method.parse"><code>parse</code></a>方法，它来自<code>url</code>箱子，用来验证并解析一个<code>&amp;str</code>，变为一个<a href="https://docs.rs/url/*/url/struct.Url.html"><code>Url</code></a>结构。输入的字符串，可能格式不正确，因此，该方法返回<code>Result&lt;Url, ParseError&gt;</code>.</p>
<p>一旦解析了 URL，它就可以使用<code>Url</code>类型的所有方法。</p>
<pre><pre class="playpen"><code class="language-rust">extern crate url;

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>
<a class="header" href="#通过移除路径段创建一个-base-url" id="通过移除路径段创建一个-base-url"><h2>通过移除路径段，创建一个 base URL</h2></a>
<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>base URL 包括一个协议和一个域。base URL 没有文件夹、文件或查询字符串。这每一项都将从给定的 URL 中，剥离出来。<a href="https://docs.rs/url/*/url/struct.PathSegmentsMut.html#method.clear"><code>PathSegmentsMut::clear</code></a>会删除路径，和<a href="https://docs.rs/url/*/url/struct.Url.html#method.set_query"><code>Url::set_query</code></a>会删除查询字符串。</p>
<pre><pre class="playpen"><code class="language-rust"># #[macro_use]
# extern crate error_chain;
extern crate url;

use url::Url;
#
# error_chain! {
#     foreign_links {
#         UrlParse(url::ParseError);
#     }
#     errors {
#         CannotBeABase
#     }
# }

fn run() -&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)
}
#
# quick_main!(run);
</code></pre></pre>
<a class="header" href="#从一个-base-url-创建新的-url" id="从一个-base-url-创建新的-url"><h2>从一个 base URL ，创建新的 URL</h2></a>
<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 href="https://docs.rs/url/*/url/struct.Url.html#method.join"><code>join</code></a>方法，用 base 路径和相对路径，创建新的 URL。</p>
<pre><pre class="playpen"><code class="language-rust">extern crate url;

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>
<a class="header" href="#提取-url-的源协议方案名主机端口" id="提取-url-的源协议方案名主机端口"><h2>提取 URL 的源（协议方案名/主机/端口）</h2></a>
<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 href="https://docs.rs/url/*/url/struct.Url.html"><code>Url</code></a>结构，公有了各种方法，用来提取有关它所表示 URL 的信息。</p>
<pre><pre class="playpen"><code class="language-rust">extern crate url;

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>产生相同的结果。</p>
<pre><pre class="playpen"><code class="language-rust"># #[macro_use]
# extern crate error_chain;
extern crate url;

use url::{Url, Origin, Host};

# error_chain! {
#     foreign_links {
#         UrlParse(url::ParseError);
#     }
# }
#
fn run() -&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(())
}
#
# quick_main!(run);
</code></pre></pre>
<a class="header" href="#从-url-中删除片段标识符和查询对" id="从-url-中删除片段标识符和查询对"><h2>从 URL 中，删除片段标识符和查询对</h2></a>
<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 href="https://docs.rs/url/*/url/struct.Url.html"><code>Url</code></a>，并<a href="https://docs.rs/url/*/url/enum.Position.html"><code>url::Position</code></a>把它切成片，删除不需要的 URL 部分。</p>
<pre><pre class="playpen"><code class="language-rust">extern crate url;

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 -->
<a class="header" href="#媒体类型" id="媒体类型"><h1>媒体类型</h1></a>
<a class="header" href="#从字符串获取-mime-类型" id="从字符串获取-mime-类型"><h2>从字符串获取 MIME 类型</h2></a>
<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>下面的示例演示，如何用<a href="https://docs.rs/mime/">mime</a>箱子，从字符串中解析出一个<a href="https://docs.rs/mime/*/mime/struct.Mime.html"><code>MIME</code></a>类型。<a href="https://docs.rs/mime/*/mime/struct.FromStrError.html"><code>FromStrError</code></a>会在<code>unwrap_or</code>作用域，生成一个默认<a href="https://docs.rs/mime/*/mime/struct.Mime.html"><code>MIME</code></a>类型。</p>
<pre><pre class="playpen"><code class="language-rust">extern crate mime;
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>
<a class="header" href="#从文件名获取-mime-类型" id="从文件名获取-mime-类型"><h2>从文件名，获取 MIME 类型</h2></a>
<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>下面的示例演示，如何使用<a href="https://docs.rs/mime/">mime</a>箱子，从给出的文件名中，返回当前 MIME 类型。程序将检查文件扩展名，并与已知列表匹配。返回值为<a href="https://docs.rs/mime/*/mime/struct.Mime.html"><code>mime:Mime</code></a>。</p>
<pre><pre class="playpen"><code class="language-rust">extern crate mime;
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>
<a class="header" href="#分析-http-响应的-mime-类型" id="分析-http-响应的-mime-类型"><h2>分析 HTTP 响应的 mime 类型</h2></a>
<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>从<code>reqwest</code>那里，接收到一个 HTTP 响应的时候，这个<a href="https://developer.mozilla.org/docs/Web/HTTP/Basics_of_HTTP/MIME_types">MIME 类型</a>或是媒体类型，可以在<a href="https://developer.mozilla.org/docs/Web/HTTP/Headers/Content-Type">Content-Type</a>标头中找到。<a href="https://docs.rs/reqwest/*/reqwest/header/struct.HeaderMap.html#method.get"><code>reqwest::header::HeaderMap::get</code></a>将标头检索为<a href="https://docs.rs/reqwest/*/reqwest/header/struct.HeaderValue.html"><code>reqwest::header::HeaderValue</code></a>，这可以转换为一个字符串。这个<code>mime</code>箱子，之后就可以解析它了，并产生一个<a href="https://docs.rs/mime/*/mime/struct.Mime.html"><code>mime::Mime</code></a>值。</p>
<p>这个<code>mime</code>箱子，还定义了一些常用的 MIME 类型。</p>
<p>请注意<a href="https://docs.rs/reqwest/*/reqwest/header/index.html"><code>reqwest::header</code></a>模块，是从<a href="https://docs.rs/http/*/http/"><code>http</code></a>箱子导出的。</p>
<pre><pre class="playpen"><code class="language-rust no_run"># #[macro_use]
# extern crate error_chain;
extern crate mime;
extern crate reqwest;

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);
#    }
# }

fn run() -&gt; Result&lt;()&gt; {
    let response = reqwest::get(&quot;https://www.rust-lang.org/logos/rust-logo-32x32.png&quot;)?;
    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(())
}
#
# quick_main!(run);
</code></pre></pre>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<a class="header" href="#客户端-2" id="客户端-2"><h2>客户端</h2></a>
<table><thead><tr><th> 食谱                                                         </th><th> 箱子                                                    </th><th> 类别                                                                  </th></tr></thead><tbody>
<tr><td> <a href="web/clients/requests.zh.html#make-a-http-get-request">发出 HTTP GET 请求</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.zh.html#query-the-github-api">查询 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.zh.html#check-if-an-api-resource-exists">检查 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>                             </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.zh.html#create-and-delete-gist-with-github-api">使用 GitHub API ，创建和删除 Gist</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.zh.html#consume-a-paginated-restful-api">使用一个（具备）分页的 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.zh.html#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.zh.html#make-a-partial-download-with-http-range-headers">使用 HTTP range 标头，进行部分下载</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.zh.html#post-a-file-to-paste-rs">POST 文件，到 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 -->
<a class="header" href="#提出请求" id="提出请求"><h1>提出请求</h1></a>
<a class="header" href="#发出-http-get-请求" id="发出-http-get-请求"><h2>发出 HTTP GET 请求</h2></a>
<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>解析提供的 URL ，并使用<a href="https://docs.rs/reqwest/*/reqwest/fn.get.html"><code>reqwest::get</code></a>制作一个同步 HTTP 请求。 打印获得的<a href="https://docs.rs/reqwest/*/reqwest/struct.Response.html"><code>reqwest::Response</code></a>的状态和标头。通过使用<a href="https://doc.rust-lang.org/std/io/trait.Read.html#method.read_to_string"><code>read_to_string</code></a>，将 HTTP 响应主体，读取到分配的<a href="https://doc.rust-lang.org/std/string/struct.String.html"><code>String</code></a>。</p>
<pre><pre class="playpen"><code class="language-rust no_run"># #[macro_use]
# extern crate error_chain;
extern crate reqwest;

use std::io::Read;
#
# error_chain! {
#     foreign_links {
#         Io(std::io::Error);
#         HttpRequest(reqwest::Error);
#     }
# }

fn run() -&gt; Result&lt;()&gt; {
    let mut res = reqwest::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(())
}
#
# quick_main!(run);
</code></pre></pre>
<!--
Links, in a few categories. Follow the existing structure.
Keep lines sorted.
-->
<!-- Categories -->
<!-- Crates -->
<a class="header" href="#调用-web-api" id="调用-web-api"><h1>调用 Web API</h1></a>
<a class="header" href="#查询-github-api" id="查询-github-api"><h2>查询 GitHub API</h2></a>
<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><a href="https://docs.rs/reqwest/*/reqwest/fn.get.html"><code>reqwest::get</code></a>查询 Github 的<a href="https://developer.github.com/v3/activity/starring/#list-stargazers">stargazers API v3</a>，获取星号标记项目的所有用户的列表。<a href="https://docs.rs/reqwest/*/reqwest/struct.Response.html"><code>reqwest::Response</code></a>用<a href="https://docs.rs/reqwest/*/reqwest/struct.Response.html#method.json"><code>Response::json</code></a>反序列化为<code>User</code>对象，而这对象实现了<a href="https://docs.rs/serde/*/serde/trait.Deserialize.html"><code>serde::Deserialize</code></a>。</p>
<pre><pre class="playpen"><code class="language-rust no_run">#[macro_use]
extern crate serde_derive;
extern crate reqwest;
use reqwest::Error;

#[derive(Deserialize, Debug)]
struct User {
    login: String,
    id: u32,
}

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 mut response = reqwest::get(&amp;request_url)?;

    let users: Vec&lt;User&gt; = response.json()?;
    println!(&quot;{:?}&quot;, users);
    Ok(())
}
</code></pre></pre>
<a class="header" href="#检查一个-api-资源是否存在" id="检查一个-api-资源是否存在"><h2>检查一个 API 资源是否存在</h2></a>
<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#method.head"><code>Client::head</code></a>），查询 GitHub 用户端点，然后检查响应代码，以确定是否成功。这是一种无需接收主体，即可快速查询 REST 资源的方法。<a href="https://docs.rs/reqwest/*/reqwest/struct.Client.html"><code>reqwest::Client</code></a>与<a href="https://docs.rs/reqwest/*/reqwest/struct.ClientBuilder.html#method.timeout"><code>ClientBuilder::timeout</code></a>合作，确保请求的持续时间不会超时。</p>
<pre><pre class="playpen"><code class="language-rust no_run">extern crate reqwest;

use reqwest::Error;
use std::time::Duration;
use reqwest::ClientBuilder;


fn main() -&gt; Result&lt;(), Error&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()?;

    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>
<a class="header" href="#使用-github-api-创建和删除-gist" id="使用-github-api-创建和删除-gist"><h2>使用 GitHub API ，创建和删除 Gist</h2></a>
<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>向 Github <a href="https://developer.github.com/v3/gists/">gists API v3</a> 发出 POST 请求，创建一个 Gist ，由<a href="https://docs.rs/reqwest/*/reqwest/struct.Client.html#method.post"><code>Client::post</code></a>完成，并使用<a href="https://docs.rs/reqwest/*/reqwest/struct.Client.html#method.delete"><code>Client::delete</code></a> DELETE 请求，将其删除。</p>
<p>这个<a href="https://docs.rs/reqwest/*/reqwest/struct.Client.html"><code>reqwest::Client</code></a>负责两个请求的详细信息，包括 URL、主体和身份验证。POST 主体来自<a href="https://docs.rs/serde_json/*/serde_json/macro.json.html"><code>serde_json::json!</code></a>宏，它能提供任意 JSON 主体。调用<a href="https://docs.rs/reqwest/*/reqwest/struct.RequestBuilder.html#method.json"><code>RequestBuilder::json</code></a>设置请求正文。<a href="https://docs.rs/reqwest/*/reqwest/struct.RequestBuilder.html#method.basic_auth"><code>RequestBuilder::basic_auth</code></a>就处理身份验证。同步调用<a href="https://docs.rs/reqwest/*/reqwest/struct.RequestBuilder.html#method.send"><code>RequestBuilder::send</code></a>执行请求。</p>
<pre><pre class="playpen"><code class="language-rust no_run"># #[macro_use]
# extern crate error_chain;
extern crate reqwest;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate serde_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,
}

fn run() -&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 mut response = Client::new()
        .post(request_url)
        .basic_auth(gh_user.clone(), Some(gh_pass.clone()))
        .json(&amp;gist_body)
        .send()?;

    let gist: Gist = response.json()?;
    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()?;

    println!(&quot;Gist {} deleted! Status code: {}&quot;,gist.id, response.status());
    Ok(())
}
#
# quick_main!(run);
</code></pre></pre>
<p>示例使用<a href="https://tools.ietf.org/html/rfc2617">HTTP 基本 身份验证</a>，这是为了获取<a href="https://developer.github.com/v3/auth/">GitHub API</a>授权访问。典型的用例将使用一个更复杂的<a href="https://oauth.net/getting-started/">OAuth</a>授权流程。</p>
<a class="header" href="#消耗一个分页的-restful-api" id="消耗一个分页的-restful-api"><h2>消耗一个分页的 RESTful API</h2></a>
<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>在方便的 Rust 迭代器中，包装一个分页的 Web API。迭代器在到达每一页的末尾时，从远程服务器惰性地获取下一页的结果。</p>
<pre><pre class="playpen"><code class="language-rust no_run">#[macro_use]
extern crate serde_derive;
extern crate reqwest;
use reqwest::Error;

#[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::Client,
    page: u32,
    per_page: u32,
    total: u32,
}

impl ReverseDependencies {
    fn of(crate_id: &amp;str) -&gt; Result&lt;Self, Error&gt; {
        Ok(ReverseDependencies {
               crate_id: crate_id.to_owned(),
               dependencies: vec![].into_iter(),
               client: reqwest::Client::new(),
               page: 0,
               per_page: 100,
               total: 0,
           })
    }

    fn try_next(&amp;mut self) -&gt; Result&lt;Option&lt;Dependency&gt;, Error&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, Error&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;(), Error&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 -->
<a class="header" href="#下载" id="下载"><h1>下载</h1></a>
<a class="header" href="#将文件下载到临时目录" id="将文件下载到临时目录"><h2>将文件下载到临时目录</h2></a>
<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>创建一个临时目录<a href="https://docs.rs/tempdir/*/tempdir/struct.TempDir.html#method.new"><code>TempDir::new</code></a>，并使用<a href="https://docs.rs/reqwest/*/reqwest/fn.get.html"><code>reqwest::get</code></a>在 HTTP，同步下载一个文件。</p>
<p>创建一个目标<a href="https://doc.rust-lang.org/std/fs/struct.File.html"><code>File</code></a>，姓名来自<a href="https://docs.rs/tempdir/*/tempdir/struct.TempDir.html#method.path"><code>TempDir::path</code></a>内部的<a href="https://docs.rs/reqwest/*/reqwest/struct.Response.html#method.url"><code>Response::url</code></a>，而<a href="https://doc.rust-lang.org/std/io/fn.copy.html"><code>io::copy</code></a>就把下载的数据复制到其中。临时目录，会<code>run</code>函数返回时，自动移除。</p>
<pre><pre class="playpen"><code class="language-rust no_run"># #[macro_use]
# extern crate error_chain;
extern crate reqwest;
extern crate tempdir;

use std::io::copy;
use std::fs::File;
use tempdir::TempDir;
#
# error_chain! {
#     foreign_links {
#         Io(std::io::Error);
#         HttpRequest(reqwest::Error);
#     }
# }

fn run() -&gt; Result&lt;()&gt; {
    let tmp_dir = TempDir::new(&quot;example&quot;)?;
    let target = &quot;https://www.rust-lang.org/logos/rust-logo-512x512.png&quot;;
    let mut response = reqwest::get(target)?;

    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)?
    };
    copy(&amp;mut response, &amp;mut dest)?;
    Ok(())
}
#
# quick_main!(run);
</code></pre></pre>
<a class="header" href="#post-一个文件到-pasters" id="post-一个文件到-pasters"><h2>POST 一个文件，到 paste.rs</h2></a>
<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>建立起到 <a href="https://paste.rs">https://paste.rs</a> 的一个连接，遵循着<a href="https://docs.rs/reqwest/*/reqwest/struct.RequestBuilder.html"><code>reqwest::RequestBuilder</code></a>模式。调用<a href="https://docs.rs/reqwest/*/reqwest/struct.Client.html#method.post"><code>Client::post</code></a>，加上 目标 URL 参数，<a href="https://docs.rs/reqwest/*/reqwest/struct.RequestBuilder.html#method.body"><code>RequestBuilder::body</code></a>通过读取文件，设置要发送的内容，以及<a href="https://docs.rs/reqwest/*/reqwest/struct.RequestBuilder.html#method.send"><code>RequestBuilder::send</code></a>会堵塞，直到文件上载并返回响应。<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="playpen"><code class="language-rust no_run">extern crate reqwest;

# #[macro_use]
# extern crate error_chain;
#
use std::fs::File;
use std::io::Read;
use reqwest::Client;
#
# error_chain! {
#     foreign_links {
#         HttpRequest(reqwest::Error);
#         IoError(::std::io::Error);
#     }
# }

fn run() -&gt; Result&lt;()&gt; {
    let paste_api = &quot;https://paste.rs&quot;;
    let file = File::open(&quot;message&quot;)?;

    let mut response = Client::new().post(paste_api).body(file).send()?;
    let mut response_body = String::new();
    response.read_to_string(&amp;mut response_body)?;
    println!(&quot;Your paste is located at: {}&quot;, response_body);
    Ok(())
}
#
# quick_main!(run);
</code></pre></pre>
<a class="header" href="#使用-http-range-标头进行部分下载" id="使用-http-range-标头进行部分下载"><h2>使用 HTTP range 标头，进行部分下载</h2></a>
<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#method.head"><code>reqwest::Client::head</code></a>，得到响应的<a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Length">内容长度</a>。</p>
<p>然后，代码使用<a href="https://docs.rs/reqwest/*/reqwest/struct.Client.html#method.get"><code>reqwest::Client::get</code></a>，在打印进度消息的同时，下载 10240 字节的内容。这个<a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Range">Range</a> 标头指定块的大小和位置。</p>
<p>Range 标头在<a href="https://tools.ietf.org/html/rfc7233#section-3.1">射频识别芯片</a>中定义。</p>
<pre><pre class="playpen"><code class="language-rust no_run"># #[macro_use]
# extern crate error_chain;
extern crate reqwest;

use std::fs::File;
use std::str::FromStr;
use reqwest::header::{HeaderValue, CONTENT_LENGTH, RANGE};
use reqwest::StatusCode;

#
# 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);
#             // 注意(unwrap): `HeaderValue::from_str` 仅在值不是 有效 ASCII 字符，才会失败
#             // 因为，这个格式字符串是静态的，两个值是整数，
#             // 也就是说，失败不会发生。
#             Some(HeaderValue::from_str(&amp;format!(&quot;bytes={}-{}&quot;, prev_start, self.start - 1)).unwrap())
#         }
#     }
# }

fn run() -&gt; Result&lt;()&gt; {
    let url = &quot;https://httpbin.org/range/102400?duration=2&quot;;
    const CHUNK_SIZE: u32 = 10240;

    let client = reqwest::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) {
            bail!(&quot;Unexpected server response: {}&quot;, status)
        }

        std::io::copy(&amp;mut response, &amp;mut output_file)?;
    }

    println!(&quot;Finished with success!&quot;);
    Ok(())
}
#
# quick_main!(run);
</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>

    

    
    <!-- Google Analytics Tag -->
    <script async src="https://www.googletagmanager.com/gtag/js?id=UA-128555056-1"></script>
    
    <script type="text/javascript">
        var localAddrs = ["localhost", "127.0.0.1", ""];
        if (localAddrs.indexOf(document.location.hostname) === -1) {
            window.dataLayer = window.dataLayer || [];
            function gtag() { dataLayer.push(arguments); }
            gtag('js', new Date());

            gtag('config', 'UA-128555056-1');
        }
    </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>