Full Code of chriskrycho/newrustacean.com for AI

main 0838780a8747 cached
233 files
2.0 MB
541.1k tokens
297 symbols
1 requests
Download .txt
Showing preview only (2,171K chars total). Download the full file or copy to clipboard to get everything.
Repository: chriskrycho/newrustacean.com
Branch: main
Commit: 0838780a8747
Files: 233
Total size: 2.0 MB

Directory structure:
gitextract_cw5hn_qg/

├── .editorconfig
├── .gitignore
├── .travis.yml
├── Cargo.toml
├── LICENSE.md
├── Makefile
├── README.md
├── build.rs
├── docs/
│   ├── bonus/
│   │   ├── 10-script.md
│   │   ├── 13-silly-mistakes.md
│   │   ├── 14-my-workflow.md
│   │   ├── burnout-script.md
│   │   └── translating-between-languages-script.md
│   ├── bonus-2-script.md
│   ├── bonus-3-script.md
│   ├── bonus-4-script.md
│   ├── bonus-5-script.md
│   ├── bonus-6-script.md
│   ├── bonus-7-script.md
│   ├── bonus-8-script.md
│   ├── bonus-9-script.md
│   ├── cysk/
│   │   ├── bindgen-cbindgen-script.md
│   │   ├── serde.md
│   │   └── wasm.md
│   ├── cysk-1.md
│   ├── cysk-2.md
│   ├── cysk-3.md
│   ├── cysk-rayon.md
│   ├── cysk-rocket.md
│   ├── e000-script.md
│   ├── e001-script.md
│   ├── e002-script.md
│   ├── e003-script.md
│   ├── e004-script.md
│   ├── e005-script.md
│   ├── e006-script.md
│   ├── e007-script.md
│   ├── e008-script.md
│   ├── e009-script.md
│   ├── e010-script.md
│   ├── e011-script.md
│   ├── e011-transcript.md
│   ├── e012-script.md
│   ├── e014-script.md
│   ├── e015-script.md
│   ├── e016-script.md
│   ├── e017-script.md
│   ├── e018-script.md
│   ├── e019-script.md
│   ├── e020-script.md
│   ├── e021-script.md
│   ├── e022-script.md
│   ├── e023-script.md
│   ├── e024-script.md
│   ├── e025-script.md
│   ├── e026-script.md
│   ├── e027-script.md
│   ├── e028-script.md
│   ├── e029-script.md
│   ├── e030-script.md
│   ├── e031-script.md
│   ├── interview/
│   │   └── diesel-1.0/
│   │       ├── master.md
│   │       ├── part-1.md
│   │       └── part-2.md
│   ├── interview-1-part-1-script.md
│   ├── interview-1-part-2-script.md
│   ├── interview-3-script.md
│   ├── interview-4-part-1.md
│   ├── interview-4-part-2.md
│   ├── interview-4-part-3.md
│   ├── interview-4-sponsors.md
│   ├── irr_2017/
│   │   ├── anna-liao.md
│   │   ├── lee-baillie.md
│   │   └── matt-gathu.md
│   ├── meta-2.md
│   ├── meta-3.md
│   ├── news/
│   │   ├── 1-script.md
│   │   ├── 2-script.md
│   │   ├── increasing-rusts-reach.md
│   │   ├── rust-1-20.md
│   │   ├── rust-1-21-1-22.md
│   │   ├── rust-1-23.md
│   │   ├── rust-1-24.md
│   │   ├── rust-1-25.md
│   │   ├── rust-1-26.md
│   │   ├── rust-1-27.md
│   │   ├── rust-1-28.md
│   │   ├── rust-1-31/
│   │   │   ├── part-1.md
│   │   │   └── part-2.md
│   │   ├── rust-1-32.md
│   │   ├── rust-1.33-and-1.34.md
│   │   ├── rust-1.35.md
│   │   └── rust_1_29_1_30.md
│   └── rbr_2017/
│       ├── andrew-hobden.md
│       ├── anthony-deschamps.md
│       ├── arun-kulshreshtha.md
│       ├── ben-striegel.md
│       ├── colin-dean.md
│       ├── holden-marcsisin.md
│       ├── jess-saxeter.md
│       ├── master-script.md
│       └── pete-lyons.md
├── landing/
│   ├── index.html
│   ├── landing.css
│   └── sponsors.html
├── resources/
│   ├── .nojekyll
│   ├── CNAME
│   ├── favicon.pxm
│   ├── feed.xml
│   ├── media-playback.css
│   └── media-playback.js
├── rust-toolchain.toml
└── src/
    ├── bonus/
    │   ├── _1.rs
    │   ├── _10.rs
    │   ├── _13.rs
    │   ├── _14.rs
    │   ├── _2.rs
    │   ├── _3.rs
    │   ├── _4.rs
    │   ├── _5.rs
    │   ├── _6.rs
    │   ├── _7.rs
    │   ├── _8.rs
    │   ├── _9.rs
    │   ├── burnout.rs
    │   ├── mod.rs
    │   └── translating_between_languages.rs
    ├── cysk/
    │   ├── _1.rs
    │   ├── _2.rs
    │   ├── _3.rs
    │   ├── bindgen_cbindgen.rs
    │   ├── mod.rs
    │   ├── rayon.rs
    │   ├── rocket.rs
    │   ├── serde.rs
    │   └── wasm.rs
    ├── e000.rs
    ├── e001.rs
    ├── e002.rs
    ├── e003.rs
    ├── e004.rs
    ├── e005.rs
    ├── e006.rs
    ├── e007.rs
    ├── e008.rs
    ├── e009.rs
    ├── e010.rs
    ├── e011.rs
    ├── e012.rs
    ├── e013.rs
    ├── e014.rs
    ├── e015.rs
    ├── e016.rs
    ├── e017.rs
    ├── e018.rs
    ├── e019.rs
    ├── e020.rs
    ├── e021.rs
    ├── e022.rs
    ├── e023.rs
    ├── e024.rs
    ├── e025.rs
    ├── e026.rs
    ├── e027.rs
    ├── e028.rs
    ├── e029/
    │   ├── ffi-demo.c
    │   ├── ffi-demo.h
    │   └── mod.rs
    ├── e030.rs
    ├── e031/
    │   ├── e031.c
    │   ├── e031.h
    │   └── mod.rs
    ├── includes/
    │   └── media-playback-speed.html
    ├── interview/
    │   ├── _1/
    │   │   ├── mod.rs
    │   │   ├── part_1.rs
    │   │   └── part_2.rs
    │   ├── _2/
    │   │   ├── mod.rs
    │   │   ├── part_1.rs
    │   │   └── part_2.rs
    │   ├── _3.rs
    │   ├── _4/
    │   │   ├── mod.rs
    │   │   ├── part_1.rs
    │   │   ├── part_2.rs
    │   │   └── part_3.rs
    │   ├── diesel_1_0/
    │   │   ├── mod.rs
    │   │   ├── part_1.rs
    │   │   └── part_2.rs
    │   ├── integer32.rs
    │   ├── irr_2017/
    │   │   ├── anna_liao.rs
    │   │   ├── lee_baillie.rs
    │   │   ├── matt_gathu.rs
    │   │   └── mod.rs
    │   ├── mod.rs
    │   └── rbr_2017/
    │       ├── andrew_hobden.rs
    │       ├── anthony_deschamps.rs
    │       ├── arun_kulshreshthra.rs
    │       ├── ben_beckwith.rs
    │       ├── ben_striegel.rs
    │       ├── colin_dean.rs
    │       ├── esty_thomas.rs
    │       ├── holden_marcsisin.rs
    │       ├── jess_saxeter.rs
    │       ├── katie_nolan.rs
    │       ├── matthias_endler.rs
    │       ├── mod.rs
    │       ├── parry_wilcox.rs
    │       ├── pete_lyons.rs
    │       ├── thomas_gideon.rs
    │       └── tom_kriezkowski.rs
    ├── lib.rs
    ├── meta/
    │   ├── _1.rs
    │   ├── _2.rs
    │   ├── _3.rs
    │   └── mod.rs
    └── news/
        ├── _1.rs
        ├── _2.rs
        ├── _3.rs
        ├── mod.rs
        ├── rust_1_20.rs
        ├── rust_1_21_1_22.rs
        ├── rust_1_23.rs
        ├── rust_1_24.rs
        ├── rust_1_25.rs
        ├── rust_1_26.rs
        ├── rust_1_27.rs
        ├── rust_1_28.rs
        ├── rust_1_29_1_30.rs
        ├── rust_1_31/
        │   ├── mod.rs
        │   ├── part_1.rs
        │   └── part_2.rs
        ├── rust_1_32.rs
        ├── rust_1_33_1_34.rs
        └── rust_1_35.rs

================================================
FILE CONTENTS
================================================

================================================
FILE: .editorconfig
================================================
root = true
indent_size = 4

[*.{js,html}]
indent_size = 2


================================================
FILE: .gitignore
================================================
# Rust/Cargo bits
target
Cargo.lock
rls

# Website bits
*.mp3
*.m4a
*.logicx
recordings

# Miscellaneous tooling bits
.python-version
.ruby-version

# IDE
.idea
.sublime-*
*.iml
.vscode

# Writing tools
.Ulysses-*

# Vim nonsense
*.swp

# Build output
link-against-Rust

================================================
FILE: .travis.yml
================================================
language: rust
cache: cargo
rust:
- nightly
branches:
  only:
  - master
script:
- make all


================================================
FILE: Cargo.toml
================================================
[package]
edition = "2018"
name = "show-notes"
# Version will match released show number! Episode 12 will be `0.1.2`.
version = "0.3.1"
authors = ["Chris Krycho <chris@chriskrycho.com>"]

[dependencies]
regex = "0.2"
libc = "0.2.54"

[build-dependencies]
cc = "1.0"

[lib]
crate-type = ["cdylib"]


================================================
FILE: LICENSE.md
================================================
License
=======

Technical materials
-------------------

The MIT License (MIT)

Copyright (c) 2015 Chris Krycho

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Content
-------

### Human-friendly

You can do basically whatever you want with the content (the podcast audio
included). Remix to your heart's content. Mash it up, quote it, make a
podcast-jam if you like. The only restriction we have on the use of our content
is that you cite it---that's just being a good neighbor.

The name and logo? Feel free to riff on them. You just can't claim the work as
your own. The design of the logo belongs to my friend [Cameron Morgan][cam].
He's great. If you steal his stuff, I may have to sic the friendly Rust
community on you.

The legalese below just outlines this policy in lawyer-friendly terms.

[cam]: //www.krop.com/spidercam/

### Lawyer-friendly

#### Creative Commons -- Attribution 4.0 International -- CC BY 4.0
##### Section 1 – Definitions.

  1. **Adapted Material** means material subject to Copyright and Similar Rights
     that is derived from or based upon the Licensed Material and in which the
     Licensed Material is translated, altered, arranged, transformed, or
     otherwise modified in a manner requiring permission under the Copyright and
     Similar Rights held by the Licensor. For purposes of this Public License,
     where the Licensed Material is a musical work, performance, or sound
     recording, Adapted Material is always produced where the Licensed Material
     is synched in timed relation with a moving image.
  2. **Adapter's License** means the license You apply to Your Copyright and
     Similar Rights in Your contributions to Adapted Material in accordance with
     the terms and conditions of this Public License.
  3. **Copyright and Similar Rights** means copyright and/or similar rights
     closely related to copyright including, without limitation, performance,
     broadcast, sound recording, and Sui Generis Database Rights, without regard
     to how the rights are labeled or categorized. For purposes of this Public
     License, the rights specified in Section [2(b)(1)-(2)][4] are not Copyright
     and Similar Rights.
  4. **Effective Technological Measures** means those measures that, in the
     absence of proper authority, may not be circumvented under laws fulfilling
     obligations under Article 11 of the WIPO Copyright Treaty adopted on
     December 20, 1996, and/or similar international agreements.
  5. **Exceptions and Limitations** means fair use, fair dealing, and/or any
     other exception or limitation to Copyright and Similar Rights that applies
     to Your use of the Licensed Material.
  6. **Licensed Material** means the artistic or literary work, database, or
     other material to which the Licensor applied this Public License.
  7. **Licensed Rights** means the rights granted to You subject to the terms
     and conditions of this Public License, which are limited to all Copyright
     and Similar Rights that apply to Your use of the Licensed Material and that
     the Licensor has authority to license.
  8. **Licensor** means the individual(s) or entity(ies) granting rights under
     this Public License.
  9. **Share** means to provide material to the public by any means or process
     that requires permission under the Licensed Rights, such as reproduction,
     public display, public performance, distribution, dissemination,
     communication, or importation, and to make material available to the public
     including in ways that members of the public may access the material from a
     place and at a time individually chosen by them.
  10. **Sui Generis Database Rights** means rights other than copyright
      resulting from Directive 96/9/EC of the European Parliament and of the
      Council of 11 March 1996 on the legal protection of databases, as amended
      and/or succeeded, as well as other essentially equivalent rights anywhere
      in the world.
  11. **You** means the individual or entity exercising the Licensed Rights
      under this Public License. **Your** has a corresponding meaning.

##### Section 2 – Scope.

1. **License grant**.
    1. Subject to the terms and conditions of this Public License, the Licensor
       hereby grants You a worldwide, royalty-free, non-sublicensable, non-
       exclusive, irrevocable license to exercise the Licensed Rights in the
       Licensed Material to:
        1. reproduce and Share the Licensed Material, in whole or in part; and
        2. produce, reproduce, and Share Adapted Material.
    2. Exceptions and Limitations. For the avoidance of doubt, where Exceptions
       and Limitations apply to Your use, this Public License does not apply,
       and You do not need to comply with its terms and conditions.
    3. Term. The term of this Public License is specified in Section 6(a).
    4. Media and formats; technical modifications allowed. The Licensor
       authorizes You to exercise the Licensed Rights in all media and formats
       whether now known or hereafter created, and to make technical
       modifications necessary to do so. The Licensor waives and/or agrees not
       to assert any right or authority to forbid You from making technical
       modifications necessary to exercise the Licensed Rights, including
       technical modifications necessary to circumvent Effective Technological
       Measures. For purposes of this Public License, simply making
       modifications authorized by this Section 2(a)(4) never produces Adapted
       Material.
    5. Downstream recipients.
        1. Offer from the Licensor – Licensed Material. Every recipient of the
           Licensed Material automatically receives an offer from the Licensor
           to exercise the Licensed Rights under the terms and conditions of
           this Public License.
        2. No downstream restrictions. You may not offer or impose any
           additional or different terms or conditions on, or apply any
           Effective Technological Measures to, the Licensed Material if doing
           so restricts exercise of the Licensed Rights by any recipient of the
           Licensed Material.
    6. No endorsement. Nothing in this Public License constitutes or may be
       construed as permission to assert or imply that You are, or that Your use
       of the Licensed Material is, connected with, or sponsored, endorsed, or
       granted official status by, the Licensor or others designated to receive
       attribution as provided in Section 3(a)(1)(A)(i).

2. **Other rights**.

    1. Moral rights, such as the right of integrity, are not licensed under this
       Public License, nor are publicity, privacy, and/or other similar
       personality rights; however, to the extent possible, the Licensor waives
       and/or agrees not to assert any such rights held by the Licensor to the
       limited extent necessary to allow You to exercise the Licensed Rights,
       but not otherwise.
    2. Patent and trademark rights are not licensed under this Public License.
    3. To the extent possible, the Licensor waives any right to collect
       royalties from You for the exercise of the Licensed Rights, whether
       directly or through a collecting society under any voluntary or waivable
       statutory or compulsory licensing scheme. In all other cases the Licensor
       expressly reserves any right to collect such royalties.

##### Section 3 – License Conditions.

Your exercise of the Licensed Rights is expressly made subject to the following
conditions.

1. **Attribution**.

    1. If You Share the Licensed Material (including in modified form), You
       must:

        1. retain the following if it is supplied by the Licensor with the
           Licensed Material:
            1. identification of the creator(s) of the Licensed Material and any
               others designated to receive attribution, in any reasonable
               manner requested by the Licensor (including by pseudonym if
               designated);
            2. a copyright notice;
            3. a notice that refers to this Public License;
            4. a notice that refers to the disclaimer of warranties;
            5. a URI or hyperlink to the Licensed Material to the extent
               reasonably practicable;
        2. indicate if You modified the Licensed Material and retain an
           indication of any previous modifications; and
        3. indicate the Licensed Material is licensed under this Public License,
           and include the text of, or the URI or hyperlink to, this Public
           License.
    2. You may satisfy the conditions in Section 3(a)(1) in any reasonable
       manner based on the medium, means, and context in which You Share the
       Licensed Material. For example, it may be reasonable to satisfy the
       conditions by providing a URI or hyperlink to a resource that includes
       the required information.
    3. If requested by the Licensor, You must remove any of the information
       required by Section 3(a)(1)(A) to the extent reasonably practicable.
    4. If You Share Adapted Material You produce, the Adapter's License You
       apply must not prevent recipients of the Adapted Material from complying
       with this Public License.

##### Section 4 – Sui Generis Database Rights.

Where the Licensed Rights include Sui Generis Database Rights that apply to Your
use of the Licensed Material:

  1. for the avoidance of doubt, Section 2(a)(1) grants You the right to
     extract, reuse, reproduce, and Share all or a substantial portion of the
     contents of the database;
  2. if You include all or a substantial portion of the database contents in a
     database in which You have Sui Generis Database Rights, then the database
     in which You have Sui Generis Database Rights (but not its individual
     contents) is Adapted Material; and
  3. You must comply with the conditions in Section 3(a) if You Share all
     or a substantial portion of the contents of the database.

For the avoidance of doubt, this Section 4 supplements and does not replace Your
obligations under this Public License where the Licensed Rights include other
Copyright and Similar Rights.

##### Section 5 – Disclaimer of Warranties and Limitation of Liability.

1. **Unless otherwise separately undertaken by the Licensor, to the extent
   possible, the Licensor offers the Licensed Material as-is and as-available,
   and makes no representations or warranties of any kind concerning the
   Licensed Material, whether express, implied, statutory, or other. This
   includes, without limitation, warranties of title, merchantability, fitness
   for a particular purpose, non-infringement, absence of latent or other
   defects, accuracy, or the presence or absence of errors, whether or not known
   or discoverable. Where disclaimers of warranties are not allowed in full or
   in part, this disclaimer may not apply to You.**
2. **To the extent possible, in no event will the Licensor be liable to You
   on any legal theory (including, without limitation, negligence) or otherwise
   for any direct, special, indirect, incidental, consequential, punitive,
   exemplary, or other losses, costs, expenses, or damages arising out of this
   Public License or use of the Licensed Material, even if the Licensor has been
   advised of the possibility of such losses, costs, expenses, or damages. Where
   a limitation of liability is not allowed in full or in part, this limitation
   may not apply to You.**
3. The disclaimer of warranties and limitation of liability provided above shall
   be interpreted in a manner that, to the extent possible, most closely
   approximates an absolute disclaimer and waiver of all liability.

##### Section 6 – Term and Termination.

1. This Public License applies for the term of the Copyright and Similar Rights
   licensed here. However, if You fail to comply with this Public License, then
   Your rights under this Public License terminate automatically.
2. Where Your right to use the Licensed Material has terminated under Section
   6(a), it reinstates:

    1. automatically as of the date the violation is cured, provided it is cured
       within 30 days of Your discovery of the violation; or
    2. upon express reinstatement by the Licensor. For the avoidance of doubt,
       this Section 6(b) does not affect any right the Licensor may have to seek
       remedies for Your violations of this Public License.
3. For the avoidance of doubt, the Licensor may also offer the Licensed Material
   under separate terms or conditions or stop distributing the Licensed Material
   at any time; however, doing so will not terminate this Public License.
4. Sections 1, 5, 6, 7, and 8 survive termination of this Public License.

##### Section 7 – Other Terms and Conditions.

1. The Licensor shall not be bound by any additional or different terms or
   conditions communicated by You unless expressly agreed.
2. Any arrangements, understandings, or agreements regarding the Licensed
   Material not stated herein are separate from and independent of the terms and
   conditions of this Public License.

##### Section 8 – Interpretation.

1. For the avoidance of doubt, this Public License does not, and shall not be
   interpreted to, reduce, limit, restrict, or impose conditions on any use of
   the Licensed Material that could lawfully be made without permission under
   this Public License.
2. To the extent possible, if any provision of this Public License is deemed
   unenforceable, it shall be automatically reformed to the minimum extent
   necessary to make it enforceable. If the provision cannot be reformed, it
   shall be severed from this Public License without affecting the
   enforceability of the remaining terms and conditions.
3. No term or condition of this Public License will be waived and no failure to
   comply consented to unless expressly agreed to by the Licensor.
4. Nothing in this Public License constitutes or may be interpreted as a
   limitation upon, or waiver of, any privileges and immunities that apply to
   the Licensor or You, including from the legal processes of any jurisdiction
   or authority.

Creative Commons is not a party to its public licenses. Notwithstanding,
Creative Commons may elect to apply one of its public licenses to material it
publishes and in those instances will be considered the “Licensor.” Except for
the limited purpose of indicating that material is shared under a Creative
Commons public license or as otherwise permitted by the Creative Commons
policies published at [creativecommons.org/policies][policies], Creative Commons
does not authorize the use of the trademark “Creative Commons” or any other
trademark or logo of Creative Commons without its prior written consent
including, without limitation, in connection with any unauthorized modifications
to any of its public licenses or any other arrangements, understandings, or
agreements concerning use of licensed material. For the avoidance of doubt, this
paragraph does not form part of the public licenses.

Creative Commons may be contacted at [creativecommons.org][cc].

[policies]: //creativecommons.org/policies
[cc]: //creativecommons.org


================================================
FILE: Makefile
================================================
# -- Define variables. -- #
BUILD_DIR = target/doc
SRC = src/*.rs
LANDING = landing/*.html landing/*.css
RESOURCES = resources/* resources/.nojekyll

# -- Define build rules -- #
.PHONY: all clean test docs publish

default: all

clean:
	rm -rf $(BUILD_DIR)

# Generate everything, but just leave it in the build directory.
all: test docs landing resources

test:
	cargo test

docs:
	env RUSTDOCFLAGS="--html-after-content src/includes/media-playback-speed.html" cargo doc --no-deps --document-private-items

# Fancy landing page components.
landing: $(LANDING) target_dir
	cp $(LANDING) target/doc

# GitHub pages settings, favicon, RSS feed, etc. Note: the RSS feed is updated
# manually, so running `make modules` won't update it.
resources: $(RESOURCES) target_dir
	cp $(RESOURCES) target/doc

target_dir:
	mkdir -p $(BUILD_DIR)


================================================
FILE: README.md
================================================
# New Rustacean

This is a *slightly ridiculous* approach to building a podcast hosting setup using
Rust's documentation tools, for the [New Rustacean] podcast. I'm making the
site source publicly available so that others can follow along and learn from
my successes, failures, and various misadventures along the way. Feel free to
submit pull requests if you find typos or the like!

[New Rustacean]: https://newrustacean.com

I hope to evolve the structure here based on what will hopefully *become* the
structure for sites generated with `cargo doc` in the future, with
supplementary/guide-like material living in the `src/doc` directory. For an
example of existing repositories which use this structure, see [rust-lang/rust]
and [rust-lang/cargo].

[rust-lang/rust]: https://github.com/rust-lang/rust
[rust-lang/cargo]: https://github.com/rust-lang/cargo


================================================
FILE: build.rs
================================================
use std::process::Command;

use cc::Build;

fn main() {
    // Build a C file to link into Rust code.
    Build::new().file("src/e029/ffi-demo.c").compile("ffi-demo");

    // Build a C file which links *against* Rust code.
    Command::new("clang")
        .args([
            "src/e031/e031.c",
            "-Ltarget/debug",
            "-lshow_notes",
            "-o",
            "link-against-rust",
        ])
        .spawn()
        .expect("executed the build for linking in Rust from C");
}


================================================
FILE: docs/bonus/10-script.md
================================================
# Becoming a Contributor

## Chris Krycho

### Rust Belt Rust, 2017

---

![family](http://cdn.chriskrycho.com/images/talks/rbr_2017/family.jpg)

Note: Hello, everyone! It's good to see all of you. We only have half an hour, and even if that's ten to fifteen minutes longer than a normal New Rustacean episode, that's still not much time, so let's jump right in! Our theme is "Becoming a Contributor." There are two prongs to this talk, two big ideas I hope you all walk away with.

---

### Introduction: The Big Ideas


Note: The first thing I hope all of you take away is that **there is no reason _you_ cannot contribute meaningfully** to the success of Rust – or indeed any open-source project you care about. Anyone can be a contributor. And not "even you" but perhaps "_especially_ you". The fact that you're an outsider, or new to programming, or new to systems programming: sometimes that makes you a _better_ contributor. Because you don't necessarily share the biases of – you're not wearing the same blinders that – someone who's been writing systems-level code for 20 years have. So the first idea: **you can contribute**.

The second idea I hope you take away is **just *how many* ways there are to contribute meaningfully**. It has almost become a cliche in the Rust community to say "code isn't the only thing that matters," but I want to show you today just how true that is. And I want to make that point again more forcefully, because for all that we often say that, the idea that _shipping code_ is what really matters is the kind of pernicious lie that can come back and bite any of us. It certainly gets to me at times! But it's a lie, and we're going to see that in detail. That's the second big idea: **there are an _astounding_ number of ways you can contribute**.

---

### Introduction: Why?


Honestly, some of both – but serving people most of all.

Note: There are a lot of things to be passionate about in the world of software development. But at the end of the day, I care about software because I care about _people_. To borrow a label from Scott Wlaschin – a developer I admire enormously, mostly working over in the F# community – I am a _humanist_, not a _technologist_. The technologies are interesting in themselves to a degree; but I mostly care about the ways that technologies can help us serve people more effectively. As software developers, that takes a lot of shapes. But today I want to zoom in on just these two ideas about open-source software:

---

### Introduction: The Big Ideas


Note: So: why these two ideas? For one thing, because I think they are among the most applicable to everyone here. We have an enormous open-source focus. But for another, because they can also serve as windows into the ways we can – and should – think about software more generally. So: let's talk about how you become a _contributor_.

---

### Introduction: Outline

1. Introduction
2. Why bother contributing?
3. Who is a contributor?
4. What is a contribution? How can you contribute?
   * ...so many things they won't fit on this slide.
5. When and where to contribute?
6. Conclusion

Note: We're going to take this on in the good old grammar-school fashion: _who_, _what_, _when_, _where_, _why_, and _how_. We're not going to take them in that order though, and we might smash a few of them together.

---

## Why bother contributing?

There is more work to be done than hands to do it.

Always.

Note: The first question we might be asking is: _why contribute at all_? Why should you be interested in becoming a contributor? And the best answer I can offer is: because there is more work than hands to do it. Always. Every open-source maintainer can tell you the truth of this.

---

## Who is a contributor?


Note: People define this differently, but I have a very simple definition: **A contributor is _anyone_ who improves a project.**

---

### Who is a contributor? Examples


For example:

* submit a patch to fix a typo
* add a small correction for a code sample in a project
* file an issue instead of just suffering through a problem in silence
* everything else we're going to talk about today

---

### Who is a contributor? Me!


How I got here:

![my first Rust commit](http://cdn.chriskrycho.com/images/talks/rbr_2017/first-commit.png)

Note: That might sound overblown, but it's really not. I am literally standing on this stage in front of you today because I submitted some small typo and code sample improvements to "Rust by Example" a few years ago, and realized: I can make a difference in this community. And that gave me the motivation I needed to _keep_ contributing.

---

### Who is a contributor?

_All of us!_

We're meant to help each other.

Note: I don't imagine the story is all that different for _most_ people who are open-source contributors in this room. Something got them over the hump, and it was probably something small, insignificant-seeming at the time. They might be particularly skilled in this thing or that thing, but in fact a lot of them are in those roles just because they saw a need and stepped up to fill it. And then kept at it for a long time. But it made them a contributor. And that feeling – of helping build something bigger than you can build on your own – is a good one. I'd go so far as to say it's part of what humans are _meant_ for. It's part of us in a deep, deep way.

---

## Who is a contributor?


That's it. Really!

No quibbling!

And no magic!

Note: If you're inclined to quibble with that definition, I challenge you to ask _why?_ I think, most often, it's because we feel defensive about wanting to project our own particular kinds of contribution as the most important, or the most valuable. But I'm more of the mindset that, as I read recently, "anyone who would be first… must be last of all, and servant of all." We should stop worrying about our own prestige and turf-marking, and start rejoicing in the many different ways people are able to make our projects better.

There's no magic that makes you qualified to be a contributor. There's just a willingness to serve where you see a need.

---

## What & how can you contribute?

(This is a very, _very_ long list.)

Note: And that takes us into the "what" of all of this, the _how_. (Yes, I'm combining those two). **_What_ is a contribution? _How_ can you contribute?** Turns out, this is a _long_ list.

---

### What & how: code

The obvious one. 😏

Fix bugs! Implement features! etc.


![good first issue](http://cdn.chriskrycho.com/images/talks/rbr_2017/good-first-issue.png) ![mentored](http://cdn.chriskrycho.com/images/talks/rbr_2017/mentored.png) ![easy](http://cdn.chriskrycho.com/images/talks/rbr_2017/easy.png)


These are all over the ecosystem.

Note: Let's get this right out of the way up front, because it's the most obvious: you can write code. You can fix bugs or help implement new features. You can do that even if you're not an expert – especially in the Rust community. Many Rust projects have gone out of their way to mark issues as good-first-issues, or easy-to-tackle, or mentorship-available. Maybe it's your first contribution to an open-source project: that's okay. You can take a stab at it, and the fact that it might not be good _is okay_. The whole point of these kinds of issues is that they give you a place where you can jump in safely.

That goes equally for everything from the Rust compiler itself to many of the other projects in the ecosystem. Look at the repository, for example! And it's not just this project. _Lots_ of projects in the Rust ecosystem are like this.

---

#### What & how: code – we're kind here

No one will ever swear at you or insult for making a mistake in Rust-land. _Everyone_ makes mistakes.

Remember: we want people to contribute!

![good first issue](http://cdn.chriskrycho.com/images/talks/rbr_2017/good-first-issue.png)
![mentored](http://cdn.chriskrycho.com/images/talks/rbr_2017/mentored.png)
![easy](http://cdn.chriskrycho.com/images/talks/rbr_2017/easy.png)

Note: And no one is going to swear at you or insult for making a mistake here. Not even if you're working on something important, and not even if you've been doing it for a while. That is not. how. we. roll. here.

Instead, we _want_ people to show up, knowing nothing: we're happy to help. So: try opening a PR and let people help you learn how to do it well! In fact, : if you haven't ever opened a PR on a Rust project, find one that looks interesting to you and has an issue tagged that way, and submit a PR before the weekend is out! You can do it!

---

#### What & how: code – a caveat

Code is not the only contribution.

It's not even the most important contribution.

It's just the most obvious contribution.

Note: But code is not the only thing that makes you a contributor. I put it up front because I think it's worth doing – but I also wanted to get it out of the way. In every software community, it's easy to _over_-value the code. That might sound crazy, given that it's open-source _software_, but the reality is that no one fails to value the code. We _do_ often fail to value all the other things that make an open-source software project actually useful. It's certainly true that there's no project without the code. But it's also the case that there's no _useful_ software without a lot of other things besides the code, and we often undervalue those.

---

### Filing bugs

![filing bugs](http://cdn.chriskrycho.com/images/talks/rbr_2017/new-issue.png)

Note: So let's take one step away from code, and talk about what is probably the single _easiest_ way anyone can contribute. _File issues._ If you're using a binary and it doesn't work, open a ticket. If you're integrating a library and it seems like the API doesn't do what it should, or if it seems like it's missing some functionality… well, you can suffer in silence, or you can open a bug ticket! Many times, the author of the software _doesn't know there's a problem_. The only way they can fix it is if they know about it!

---

### Docs

You're probably on board with this already.

Because undocumented and badly documented projects are really, _really_ frustrating!

Note: Perhaps the thing most of you will be most persuaded of the utility of is _documentation_. All of us have faced the difficulty of trying to figure out how to integrate some poorly-documented (or undocumented!) library into our own codebase. That experience, in word, _sucks_.

So working on documentation is one of the highest-value areas you can contribute to any project. It's also really hard, in a bunch of ways – harder, in some ways, than writing the code is!

---

#### Docs: who?

Explanation of how things work under the hood ≠ introductory documentation/API docs/learning materials/etc.

Note: One kind of documentation is **explanation of how things work under the hood**. The implementer is the most qualified there! That doesn't mean they don't still need help even with that, though! Some people are incredible implementors and terrible explainers; you can often do a great service by serving as an "interpreter" for them – taking their explanations and making the literary tweaks and cleanups and polish that they need.

Another kind of documentation, though, developers and maintainers are often really poorly equipped to write, and that's **introductory documentation**. This is the problem of expertise: when you know exactly how something is _meant_ to work, and especially when you're the one who implemented it, there are things that seem obvious to you which simply aren't obvious to someone approaching it for the first time. And as hard as you try, you _can't_ escape that entirely. You can imagine what it might be like not to know something, but there's no substitute for actually not knowing something.

---

#### Docs – how?

You, too, can document things in just 3 easy steps!

1. Write down the things you don't understand from the docs as you go.
2. When you figure them out, write that down, too.
3. Then: file an issue or write a PR to improve it!

Note: What that means is that one of the most valuable things you can do as you learn a new library is _write down the things you don't understand from the docs as you go_. And when you figure them out, _write that down, too_. If nothing else, writing up that experience – filing it as an issue on the bug tracker, or otherwise getting it in the hands of the maintainers – can help them make important changes to things like the order various concepts are introduced, or adding little notes to help people feel comfortable with not knowing something until it _can_ be introduced later, and other things like that. It can help them recognize and fill in gaps in their docs – things they simply assumed but which they didn't realize they were assuming – and fill those in. At the most extreme, you might even help them realize that some parts of the docs need full rewrites… and the work you've done in writing things down might just be the foundation or the actual content of those new docs.

---

#### Docs: varieties

So what kinds of things would we call _documentation_?

* API documentation
* READMEs
* Tutorials
* Books
* The Rust Reference

Note:

* Overview/talk through
* Zoom on _Books_: Okay, books are a _huge_ undertaking, but they can genuinely serve as documentation. Especially for large projects. In fact, several of the most important pieces of "documentation" the Rust project itself has are books: "The Rust Programming Language", "Rust by Example", and "The Rustonomicon". But there are also important but totally unofficial books like Daniel Keep's "A Practical Intro to Macros in Rust 1.0" and "The Little Book of Rust Macros", or Jorge Aparicio's book on microcontrollers with Rust.
* The Rust Reference: This is a special category, and one that's especially important to me. The Rust Reference is supposed to be an exhaustive guide to the language, and the value of that being complete and accurate is hard to overstate. It's also wildly out of date today. I wrote an RFC last year that said, basically, "We need to actually document everything! That includes updating the Reference!" The trick is: it's a huge undertaking, and while I and a few others made a good start on it earlier this year, that effort got bogged down by life, and it needs to be resuscitated. And it's not just Rust which could use investment in that area. Other languages and frameworks have the same issue. It's _really_ important that there be an answer other than "dive into the source and try to figure out what its intent is" – the more central the component is in the ecosystem, the more important that is.

---

#### Docs: Translation

![translation](http://cdn.chriskrycho.com/images/talks/rbr_2017/translation.png)

Note: Another huge place you can contribute to documentation is _translation_. For good or ill, English has become the sort of _primary_ language of programming, but that doesn't mean we should treat it as the _only_ language, or as _more important_ than other languages. Translating documentation is amazing and very needed work, and it's work that not everyone is really capable of! I'm fluent in English and… ancient Hebrew and ancient Greek. For some reason, there's not much demand for technical writing in Greek from the era when Plato was alive. So I'm not much use at translation.

But many of you out there _are_ multilingual, and could take docs written in English and convert them for, say, Czech-speaking developers. Perhaps just as importantly, you can go the _other_ direction, and help non-English-speaking maintainers reach a broader audience. Take an amazing project which only has documentation in Amharic (because its developers don't feel comfortable enough in English to translate it themselves) and translate it to English: _use_ the fact that English _is_ the common language to increase the reach of non-Western developers!

---

### Visual Design

The _language_ design is great.

The landing page/docs/etc...?
Well, we're *working* on it.

Note: One of the areas where you could move the ball down the field fastest in the Rust community is with **_visual_ design**. (To be clear, the _language_ design is great!) But our websites could sometimes use some work.

---

#### Visual design: it's not just us

This is just not what "systems programmers" are interested in.

So: bend the curve again.

Make Rust stand out in this area.

Note: Systems programming language types have historically _not_ spent a lot of time on the _presentation_ of their tools. In part this is just a matter of what these kinds of languages have been oriented towards: if you spend all day hacking on kernel code, you're _likelier_ to be a person for whom user interface and visual design is less interesting than, say, optimizing memory performance or minimizing the number of cache misses a given approach has. But presentation _does_ matter, and it matters especially as we want to enable more and more people to be able to write this kind of code.

Speaking frankly, though I've spent a large chunk of my career to date writing systems-level languages, I've found the way a lot of these tools are presented to be a huge turn-off, and at times a barrier even to getting them working for me locally. Perhaps the most egregious example of that was some of the "documentation" – I'm not sure I should even call it that! – for Fortran, when I was first getting started programming back in college. The presentation of the material was essentially hacker-ish in a _bad_ way: no CSS, no attention to organization of the material, no structure to help you find your way through it.

---

#### Visual design: how

* If you're an expert or just a talented amateur, please pitch in
* If you're just flat bad at design (it's okay!), choose good tools
  * Wing
  * Pure.css
  * Skeleton
* Think about information hierarchy, a.k.a. outlines

Note: You can help here even if you're not especially comfortable with visual design if you're willing to spend just a little time on it! For example, you can simply help a team adopt something like Bootstrap. Yes, it'll look like many other open-source projects out there. But it won't be horribly, catastrophically ugly and unreadable! Or you can do something even simpler – you can use a dozen lines of CSS and have something that's responsive on small screens, much easier to read than the unstyled defaults, and much nicer-looking to boot. So don't think that just because you aren't a design expert means you can't help here. But if you _are_ a design expert: **_please help here!_**

Just as important as the _visual_ design is thinking about and actively designing the **information hierarchy** of your content. What leads to what? Which pieces go together, and which pieces can be broken up into their own pages or sections within pages? Think about the content like an _outline_. Many sites don't have any such structure to them; they're kind of haphazardly cobbled together. If you can help the maintainers with the _structure_ and _organization_ of their content, that can make an enormous differences as well.

---

### Blogging

It's okay if it feels hard.

Writing words ≠ writing software.

But you can do it!

Note: One of the other big ways you can help a project may not even end up in the repository at all. You can _blog_.

I know blogging can seem intimidating, for many of the same reasons that writing documentation can. Technical writing is hard, and it's a completely different skill from programming. But it doesn't have to be amazing; it just has to get the information out there – and you'll get better as you practice.

---

#### Blogging: "Easy Mode"

> Just write down what you're learning. —Me, just now

Note: You can start on "easy mode", too. I mentioned this earlier when talking about documentation, but "just write down what you're learning" is an incredibly effective technique for generating content. If you look at a lot of the technical blogging I've done over the years, it has been nothing more complicated than "here is what I just learned." And if you want a _superb_ example of this which is _very_ different from mine, take a look at the work that Julia Evans does on her blog! She regularly writes down, in an inimitable way, highly technical ideas she's just learning. If you want someone to make arcane Linux command line tools seem amazing and approachable, her blog is your ticket.

---

#### Blogging: good examples

Two totally different writers doing great work:

* Vaidehi Joshi: "Basecs", intro to CS
* Julia Evans: _what I just learned_ + comic illustrations

Note: But even beyond "what I just learned," blogging is a superb way for teaching in general. Over the course of this year, for example, Vaidehi Joshi has been writing what is essentially a friendly introduction to computer science on her blog on Medium. This is a totally different style of _content_ (as well as of presentation!) from the kind of "what I just learned" content that Julia Evans writes, but it's also really effective, because she takes her knowledge and translates it into something others can pick up. That's obviously more work than just writing down things you just learned, but it can also pay really high dividends as others are able to substantially deepen their knowledge.

---

#### Blogging: all the options!

* one-offs, or series
* technology:
  * _introduce_ it
  * _deep dive_ into using it
  * explain _how it's built_
* _critique_ or _highlight_ problems
* demonstrate _integrating_ different parts of the ecosystem
* _invite feedback_ on your own projects

Note: In blogging, as in documentation, there is a whole spectrum of basic teaching content you can contribute! And communities need the whole spectrum for simple introductions to extremely thorough, advanced tutorials.

But blog posts can also be much more versatile than traditional documentation.

* **They can be one-offs, or series.** You can give a topic as much depth, or as little depth, as you _care about_ or _think it deserves_. I wrote an 18-part series comparing Rust and Swift, and it could have been 30 parts if I hadn't eventually gotten derailed. That's not _documentation_, but there's a lot people can learn from those kinds of things.
* **They can introduce a technology, or dig deep into how to use it, or how it's built.** You're not limited to just one particular tack when blogging. Is your interest in the specific implementation details of some corner of the compiler? Write about that! Is your interest in how a given Rust library solves a specific kind of problem you've run into with another library, or with a similar library in another language? Write about that! You get the idea.
* **They can critique or highlight problems with specific pieces of the ecosystem!** A careful, well-articulated, critical blog post can do wonders for showing the problems with a given approach and can even sometimes help suggest the right solutions to those problems. I've repeatedly watched, for example, as people have blogged about their struggles getting their heads around the Tokio tooling; the result has been a _lot_ of work by the Tokio team to respond to those problems. The more thoughtful and careful you are in that kind of criticism, the better! Good criticism is _incredibly_ valuable. Because we all have blind spots, and someone else's perspective can help jar us out of those.
* **They can show how to _integrate_ different parts of the ecosystem.** For example, as part of the "Increasing Rust's Reach" initiative, Ryan Blecher recently wrote up a detailed walk-through on how to use the Diesel ORM and the Rocket web framework together to build a small blogging engine. That's _huge_! It makes it that much easier for someone who's just starting out with Rust, coming in from something like Python or Ruby, to dive in and get that intensely rewarding feeling of _having built something_ in a relatively small amount of time. That's also helpful because (almost) no one is building something with _just_ Diesel, or just _any_ crate. A huge part of what every software developer does is about fitting together other pieces of software.
* **They can invite feedback on your own projects.** Talk about what you're doing, what your stumbling blocks are, what you don't understand. People will often show up and help you with comments and clarifications!

And that's just scratching the surface. Blogs are incredibly versatile, and you should lean on that.

---

### Audio and Video

Not just words! Noises and pictures, too!

---

#### Audio: podcasts

* Not everyone learns the same way.
* Lots of people have commutes.

---

#### Audio: but there are already podcasts

![New Rustacean](http://cdn.chriskrycho.com/images/talks/rbr_2017/newrustacean.png) ![Request for Explanation](http://cdn.chriskrycho.com/images/talks/rbr_2017/rfe.png) ![Rusty Spike](http://cdn.chriskrycho.com/images/talks/rbr_2017/rusty-spike.png)

Note: Everything I've talked about so far has been in written form. But audio and video media can also be really helpful. Not everyone learns best by reading. And not everyone has tons of time to sit down and read a book every day. One of the reasons I started the New Rustacean podcast is that it gives people a way to get up to speed on the language while on a daily commute. But there's still a _huge_ need for more audio and video content in this space! One podcast is not enough! _Two_ podcasts is not enough! Seriously, not even three podcasts is enough! So I'm laying down another challenge: there's plenty of room for more, and more kinds, of audio content in this ecosystem.

---

#### Video

People have different learning styles!

People loved RailsCasts. It was a bootstrapper. We could use the same!

If you have skillz with video, use them!

Note: There's also a huge opening for people to produce good video content. I've heard often from people that things like RailsCasts were essential in helping them learn the Ruby on Rails ecosystem. We _need_ video tutorials which might look kind of like that, or like the kinds of things I'm doing on the podcast. If you have any skill that way, and any interest in teaching, you should make Rust videos – there aren't many out there.

---

#### Video: what

There are lots of options:

* make screencasts
* live-stream working on open-source
* live-_pair_ working on something
* …lots more you can think of!

Note: Another, totally different tack you can take with video is _live-streaming_. Sean Griffin has done this at times, and I've actually done it just once, and it's a ton of fun – and it can be incredibly illuminating for other people to see how you work and how you solve problems.

---

### Talk to people

* IRC/Gitter/Slack/Discourse
* Meetups
* Conferences

Physicality matters. Presence matters.

(We know this! We're at a conference!)

Note: You can also host or help with a local meet-up! For a lot of people, one of the major challenges of learning _any_ new piece of technology is that – even with IRC and Gitter and Slack and so on – you can feel isolated and alone. And people can help you solve problems in person, and make you feel supported in person, in ways that even a great community can't really manage online. So _go_ to meet-ups, at a minimum. And help the organizers. And if there isn't a meet-up in your community... you can start one! The #rust-community team has a ton of resources

---

### Being inviting

What about all you old-timers? You still have things to contribute.

_Welcoming_•_Mentoring_

Note: Last but not least in this list of _how_ to be a contributor, I want to take a minute and talk about "being a contributor" to those of you who've been contributors for a long time. Some of you have been shipping open-source software for years – some of you even for decades. Much of what I've said so far is old hat for you. Maybe not the design bits quite so much! But you've been doing this for a long time, and you're not trying to get over the hump of making your first contribution. You have other things to contribute here:

* The most important thing you can do is practice **welcome people.** The Rust community does this well, in general, but it's something we need to keep in front of us as a goal as the community grows. It's easy to get frustrated with newcomers as your project grows, demands on your time increase, and your work as a maintainer seems less like fun and more like a second job. But continuing to actively welcome newcomers in is _incredibly_ powerful. You can make it possible for people to go from zero to really making a difference. And remember: so once were you. None of us started out as magical wizards of Rust and open-source.

* The second big thing you can do is **mentoring.** As I mentioned, I'm now the maintainer of one of the core pieces necessary to make Ember.js and TypeScript play nicely together. But while I've done _some_ writing-of-code with that, a much larger part of my current and future work there is about helping other people learn TypeScript well enough to start using it in their apps and add-ons. But the flip-side of that is: even a fair bit of the code I _have_ written, I was able to write because someone more comfortable with some of the infrastructure mentored _me_ through its quirks and oddities.

---

## When & where to contribute

Note: The last thing I want to touch on is _when and where_ to contribute. There are two things I'd suggest you should consider here:

---

### When & where: you

Where are _you_ in the process of becoming comfortable with contributing?

* Just getting started?
* Already comfortable?

Note: If you've never done any open-source work at all before, that's different than if you've gotten pretty comfortable with it in a different ecosystem and are just figuring out where to make yourself useful in _this_ ecosystem.

---

#### When & where: if you're just getting started

1. Look for these!


   ![help wanted](http://cdn.chriskrycho.com/images/talks/rbr_2017/help-wanted.png) ![help wanted](http://cdn.chriskrycho.com/images/talks/rbr_2017/easy.png)


2. Pick big projects!

Note: If you're just getting started, I'd pick a big project with lots of those "Help Wanted" and "Mentoring" and "Easy" tags on issues, and let the size of the project help you out. Those are projects that are _used to_ helping people make their first contributions. Crazy as it seems, something like Servo can actually be an _easier_ place to start out that a much smaller project. Sure, the technical lift is higher, but there are also a lot more people actively invested in your success there.

---

#### When & where: if you're experienced

1. Find smaller projects.
2. Pick something interesting which could use the help.

(Remember: more work than hands!)

Note: On the other hand, if you're already comfortable contributing and have some idea what you're best at, you might look around and find smaller projects with fewer contributors which look interesting and _could use the help_. Because again, there's always more work to do than hands to do it.

---

#### When & where: project lifecycles

Where is a given project at in its life-cycle?

* small project, basically done?
* need docs?
* big project, a billion needs?
* etc.

Note: The second consideration dovetails nicely with that: **where is a given project at in its life-cycle?** As enthusiastic as you might be about some project, if it's a small project and it's already in a "basically done" state, well... that's probably a lot less useful a place to invest your time _if_ you're focusing on code. On the other hand, it's often the case that projects are "done" in terms of code, but desperately need help with documentation, their web site, etc. Big projects, or projects just starting out, are often better places to dig in if you're really looking to flex your coding muscles (but both of them _also_ usually have huge needs in terms of all those non-code avenues we talked about).

Think about both of those, and then see if you can pick a project that's a good fit for your current skillset and comfort level and jump in!

---

## Conclusion


Note: And that's a good place to wrap things up! I hope you're feeling like _you can do this_. Because you can. Open-source a project of your own and see where it goes. Write a blog post. Add some docs. Open a PR. Record a podcast. Make some videos. Start a meet up. Become a contributor!

---

## More info

* <https://www.rust-lang.org/en-US/contribute.html>
* <https://blog.rust-lang.org/2017/09/18-impl-future-for-rust.html>
* <https://internals.rust-lang.org/>
* `#rust`, `#rust-community`, `#rust-internals`, etc. on irc.mozilla.org


================================================
FILE: docs/bonus/13-silly-mistakes.md
================================================
# Bonus: I Still Make Silly Mistakes

Hello, I’m Chris Krycho and this is New Rustacean: a show about the Rust programming language and the people who use it. This is a bonus episode: I Still Make Silly Mistakes.

## Sponsor: Parity

First up, Parity is back sponsoring the show again because they want *you* to come write Rust with them! Parity is advancing the state of the art in decentralized technology, and they’re using Rust to do it, leaning hard on its trifecta of performance, reliability, and productivity. They're building cutting-edge tech in areas like WebAssembly and peer-to-peer networking. Two of the larger projects they're working on are: Substrate, a framework for building blockchains, and Polkadot, a platform leveraging blockchain tech for scaling and interoperability in decentralized systems.

If that sounds interesting, check out their jobs at <parity.io/jobs>!

## That mistake…

So, the mistake I titled this episode after. Every time I draft an episode of New Rustacean, I start by writing out a script for it, long-form, in my preferred Markdown editor. (You can find those scripts in the show notes!) When I record the show, I’m reading that script—usually with some minor improvisation. One of the things I do as I’m writing is include links inline in the script. I do that for two reasons:

- first, so that anyone who is reading the script has an easy way to link to the things I’m talking about throughout the episode
- and second, so that when I pull that script over into the repository for the show, I can just pull those links out and put them in the show notes

The first part works fine. Pulling the links out for the show notes has increasingly annoyed me, though: I have to go through and manually pull out each link from the text, and while that’s not a *ton* of work, it’s repetitive and error-prone. And “repetitive and error-prone” is basically the working definition of what software is good at! So I figured: hey, here’s a chance to play with a couple data structures I’ve not spent much time with in Rust and get more familiar with the [pulldown-cmark](https://github.com/raphlinus/pulldown-cmark) crate, which has a nice API for dealing with Markdown!

(As I mentioned in Part I of the Rust 1.31 and 2018 Edition news episode, I basically default to Rust for these tasks at this point: it takes me about the same amount of time as doing in a scripting language would, and I enjoy it a lot more.)

So I did what I normally do in these kinds of situations and ran `cargo new extract-md-links`. I pulled in the `pulldown-cmark` in my `cargo.toml`, and debated whether I wanted to pull in [the `structopt` crate](https://github.com/TeXitoi/structopt) for command-line argument handling—and decided against it because I figured: all I need to be able to do is pass in a single argument and this is a private tool for my very specific niche problem. No problem; I’ve parsed arguments from the command line manually for over a decade!

Right?

Wrong!

I whipped up my main function and started trying to load a test document to start on the link extraction, figuring that would be the meat of this particular little problem. And then I started seeing an error that made *no* sense to me: `"stream did not contain valid UTF-8"`.

What.

Look: I *know* this file is valid UTF-8. It’s a blog post that currently runs through a Python-powered static site generator; it wouldn’t even have successfully published if it were *not* valid UTF-8. What's more: the file opens as valid UTF-8 in Visual Studio Code and Sublime Text. It validates properly as UTF-8 when I dump it into an online UTF-8 validator. It loads properly if I open a Python REPL and load the exact same path I was passing to my little Rust tool!

At this point, as you can probably imagine, I started to feel like I was losing my mind. I hopped into the Rust Discord channel and started asking *really* basic questions about the things I was seeing. As an aside, if you've never just hopped into one of the Rust chat communities online, you should do that the next time you get stuck. And the rest of this story is a great example of *why*, but the short version is that the Rust community is *incredibly* helpful. Even for silly problems where the question-asker really ought to know better! But we'll get to that.

So I started describing my problem, and a few other Rust users—especially @alercah—started asking helpful questions and offering helpful comments about the file I was trying to work with:

- **What’s the first byte?** So instead of running `std::fs::read_to_string`, I used `std::fs::read`, which gives you back a `Vec<u8>` if it succeeds. It succeeded, so dumped the first byte.
- **That doesn’t seem right; what’s the *second* byte?** At this point I just grabbed the first *eight* bytes the same way and shared those.
- **Those are definitely not valid unicode. What’s the file?** I linked directly to the file I was trying to load from my blog source on GitHub.
- **That file starts with different bytes than the bytes your Rust program is reporting.** And indeed, it started with the bytes I’d have expected: three hyphens (which are what start a block of YAML metadata for my blog posts).

That last point had me *truly* confused. How in the world could two different people read the same file and get different results? And this of course was the key to the whole thing. But I'm getting ahead of myself again.

My next step was to just dump the minimal set of code to reproduce this program straight into a code block in Discord, along with the actual Cargo command I was running and the actual error I was seeing. And then @alercah spotted my problem, and it turned out it had nothing at all to do with the file I thought, or with unicode at all. My problem was simply that I was *opening the wrong file*.

You see, the first argument to a program is always the name of the program itself. There’s good reason for this; I’ve linked [an interesting discussion][unix] in the show notes (using this tool, which now works!) about why you might want the same program to be able to be called with different names and do different things in those circumstances. That's all just fine and dandy. Except that I was thinking the first argument would be the thing I was passing to the program: the path to the file I wanted to process. Instead, it was, you know: not unicode. Because it was a binary: the Rust program I was running! Once I grabbed the *second* argument, not the *first*, everything just worked exactly the way I expected.

[unix]: https://unix.stackexchange.com/questions/315812/why-does-argv-include-the-program-name "Why does argv include the program name?"

So that's what happened *technically*, that's the bug. But, and this is the actually interesting part of this experience, I think: you may recall my comment a minute ago that I’ve been doing this—parsing command line arguments—for over a decade! And I mean that literally: I first parsed command line arguments manually in Fortran and Java programs in 2008. This is a quote-unquote “rookie mistake.” And I laughed *really* hard at myself when I realized what had happened because it's such a "rookie mistake"!

But of course, that phrase is really misleading. “Rookie mistake” suggests that these kinds of mistakes are specific to rookies, and the reality is that they *aren’t*. I'm not a rookie a decade in, at least not at this particular thing. But these kinds of things happen to all of us. And "these kinds of things" are just mistakes that come from *unfamiliarity*. Being new to programming entirely is one reason you might be unfamiliar with something. But just being rusty—no pun intended!—is another reason you might be unfamiliar with something! I haven’t had to hand-parse an argument in about five or six years, because I’ve been using something like [Python’s `argparse` library][argparse], or [Commander in Node][commander], or [clap] and [structopt] in Rust! And that meant it was easy to forget this kind of thing because I just hadn’t had to do it manually for such a long time. So that was the first reminder: *everyone* makes "rookie mistakes," because they're not really *rookie* mistakes; they're unfamiliarity mistakes.

[argparse]: https://docs.python.org/3.7/library/argparse.html#module-argparse
[commander]: https://github.com/tj/commander.js
[clap]: https://clap.rs
[structopt]: https://github.com/TeXitoi/structopt

The second good reminder for me in this was actually from the feeling of frustration itself. It reminded me of what it’s like to be just starting out—to be a rookie!—to be looking at a compiler message that seems like it’s trying really hard to be helpful, but which is clearly telling you something that isn’t *exactly* the problem: it's not the *root* of the problem. “Yes, it’s true," I was saying, "that this is not unicode. But I have no idea *why* it isn’t unicode!” And even when you’re a decade along in your career and have generally developed a reasonable set of debugging techniques and intuitions about why things go wrong, things like this can be totally mystifying—still! And this should remind us—it reminded me—to be sympathetic to people just getting started—because even things which are totally obvious to us can be genuinely confusing to newcomers, *or even to us ourselves* with just a little distance from the specific expertise we’ve developed!

## Outro

Anyway, that’s my fun story and my two takeaways about a silly mistake I made recently; I hope it’s helpful and encouraging when you make your own silly mistakes or when you see someone make what seems like a silly mistake!

Thanks as always to this month’s $10-or-more sponsors:

- Soren Bramer Schmidt
- Graham Wihlidal
- Benjamin Manns
- Matt Rudder
- Bryan Stitt
- Brian McCallister
- Evan Stoll
- Oluseyi Sonaiya
- Nathan Sculli
- Ryan Osial
- Martin Heuschober
- Andrew Dirksen
- Daniel Collin
- Daniel Mason
- Dan Abrams
- Nick Gideo
- Behnam Esfahbod
- Scott Moeller
- Adam Green
- Nicolas Pochet
- Alexander Payne
- Nick Stevens
- Peter Tillemans
- Michael Mc Donnell
- James Hagans II
- Joseph Schrag
- Raph Levien
- Chris Palmer
- Anthony Deschamps
- David Carroll
- Jerome Froelich
- John Rudnick
- Jason Bowen
- Ramon Buckland
- Embark Studios
- Johan Andersson
- Jonathan Knapp
- Rob Tsuk
- Jako Danar
- Paul Naranja
- Chip

You can sponsor the show at patreon.com/newrustacean or via other services listed on the show website, <newrustacean.com>. There, you’ll also find show notes, including links to things I talk about, scripts, code samples, and interview transcripts. The notes for *this* episode are at <newrustacean.com/show_notes/bonus/_13/>.

Please recommend the show to others if you like it, whether in person, via your podcast directory, or in various media online! You can contact me at @chriskrycho or @newrustacean on Twitter, or by sending men an email at hello@newrustacean.com.

Until next time, happy coding!

================================================
FILE: docs/bonus/14-my-workflow.md
================================================
# Bonus: How the Sausage Gets Made

Hello, I’m Chris Krycho and this is New Rustacean: a show about the Rust Programming Language and the people who use it. This is a bonus episode: How the Sausage Gets Made!

## Sponsor: [Parity](https://parity.io/jobs)

First of all, I’m really pleased and grateful that Parity continues to sponsor the show, and it’s because they want to hire *you* to come work in Rust with them!

Parity is advancing the state of the art in decentralized technology, and they’re using Rust to do it, leaning hard on its trifecta of performance, reliability, and productivity. They're building cutting-edge tech in areas like WebAssembly and peer-to-peer networking. Two of the larger projects they're working on are: Substrate, a framework for building blockchains, and Polkadot, a platform leveraging blockchain tech for scaling and interoperability in decentralized systems.

If that sounds interesting, check out their jobs at <parity.io/jobs>!

## Conferences

Second up, it’s time for me to mention some Rust conferences!

First, and most urgent is RustLab, to be held in Florence, Italy, this June 28–29. I call it the most urgent because the CFP closes tomorrow, March 24! (I meant to have this episode out a week ago! Whoops!)

Second is RustConf, being held August 22–23 in Portland, Oregon. Once again I’m on the program committee, and once again we’d love to have you submit. It was a great conference last year, and I hope to have an equally great program this year! And hey, I’m looking forward to being in Portland again, as I was this week for EmberConf—it’s such a fun city!

Third, near and dear to me (I seriously could not be more excited) is Colorado Gold Rust: a brand new regional Rust conference being held in Denver, Colorado, on September 20–21. I *will* be there, and I will almost certainly be there in a very official New Rustacean way! Stay tuned for details on that as we hammer them down.

Finally, Rust Belt Rust is being held this year in Dayton, Ohio, on October 18–19.

The calls for proposals for Colorado Gold Rust and Rust Belt Rust are not yet open, but I will certainly mention on the show when they are.

## How I Make the Show

Okay, so today’s episode is a little unusual for the show, but I get asked questions about how I make the show and about a number of small but important decisions I’ve made along the way often enough that I thought it would be worth setting this all down in one place, so that I can have an easy place to reference when those questions inevitably come up!

I want to note before I dive in, though, that what follows is *my approach and process*, as it has evolved over the course of the show and as a relatively financially successful show with a solid listener base. It is *not* my recommendation of how *you* should produce a show if you decided to start one! If you're interested in my thoughts in *that* direction, you should check out the two guest lectures I delivered on the subject at North Caroline State University back in the fall of 2016, both linked in the show notes ([A], [B]).

[A]: https://winningslowly.org/bonus.03/
[B]: https://winningslowly.org/bonus.04/

### Prep

I also have a confession: I drafted this episode back in January, because I *knew* that I’d be super busy right now in March because I was teaching a workshop on TypeScript again at EmberConf, and trying to get out *any* episodes in March last year just about did me in! But that leads me into the first bit of how the show gets made: these episodes are all scripted top to bottom.

That wasn’t always the case. The first few episodes of the show, I just wrote outlines and winged it. That was… not a good idea. I managed it okay, but if you go back and listen to those episodes, you can *tell* I’m winging it, and not in a good way. There were two big problems with doing it that way for me.

1.  The first problem was that I had to record basically as soon as I finished learning something, because there was no way that an outline was going to do the job even a few days or a week later. My goal from the start has been to make this a top-notch resource that would have years of value to people, and the deeper into the language I got, the less comfortable I was with just saying stuff off the top of my head, instead of writing down *exactly* the right thing to make sure I got it right.

    So, a few episodes in, I started scripting the episode top to bottom. And, again: you can tell! It's obvious that I'm reading a script, both in the sense that it's obviously not just off-the-cuff (and it's a little bit less natural), but also in the sense that I can be much clearer and more precise as a result, and hopefully that tradeoff is worth it. Of course, it doesn't protect me from making mistakes! You can check out even a few recent episodes and note that there are corrections in the show notes! It does mean those mistakes are much less likely to happen, and they're typically smaller!

2.  The second problem in doing it off the cuff was the editing job. So, here's the thing: when I edit a podcast, I *really* edit a podcast. I cut out umms and uhhs, and long pauses, and coughs, and so on. If I stumble over something, I nearly always back up and say it again. If, when I'm speaking from the script, something just *sounds* wrong, I back up and say it a different way. But those kinds of stumbles and things which made me need to edit happened a *lot* more when I was recording everything off the cuff, unscripted. That in turn meant that I had to spend more time editing the show, rather than doing, well, literally anything else! And as much as I enjoy editing podcasts—it's actually quite pleasant work for me!—it's not something I want to spend more time doing than actually *necessary*.

    Scripting lets me make a tradeoff: I spend a lot more time in up-front preparation, in exchange for a lot *less* time spent editing… and, as a bonus, I get scripts that I can make available with the episodes for people who prefer reading over listening, or for people who just want to go back and review the material in a different medium later.

### Recording

Given that kind of prep work, producing the show is pretty straightforward most of the time! I'm just recording off of a script! Even when I do have guests, they have all been pretty easy to coordinate with. We just set up a Skype call (or something like that) and I split apart the guests' audio from mine so I can do that same kind of careful editing on both sides of the recording. I'm on a Mac, which means there are a bunch of *really great* tools for these kinds of things—in particular, [Audio Hijack] and [Loopback] from [Rogue Amoeba] have been game-changers for me when dealing with recording. Audio Hijack also supports *streaming*, so I hook it up to an [Icecast] server and broadcast my live recording sessions to the internet sometimes (like right now!).

[Audio Hijack]: https://www.rogueamoeba.com/audiohijack/
[Loopback]: https://www.rogueamoeba.com/loopback/
[Rogue Amoeba]: https://www.rogueamoeba.com/
[Icecast]: https://icecast.org

When I'm recording, whether alone or with guests, I take note of any obvious moments where I need to make an edit—I just write down the time stamp of my recording from Audio Hijack in a notes app, as a Markdown-style to-do list item. If I'm recording with guests, I also write down anything they mention that seems interesting and worth linking, so that I can use it for the show notes later. For solo episodes, I actually build everything I need for the show notes during the scripting process: I add links to the script wherever I mention a particular topic, and I built [a small tool (in Rust, of course!)][extract] to extract those links from the script to drop into the show notes when I'm done. For teaching episodes, I also spend the time building out the example code—both as a teaching resource and also just to make sure I understand things correctly!

[extract]: https://github.com/chriskrycho/extract-md-links

### Editing

Now, once I have all the audio in hand, I do the editing work I described a minute ago. I start by preprocessing the audio with a *suuuper* fancy tool called iZotope RX, which is worth its weight in gold for dealing with things like noise removal and cleaning up weird artifacts… but also you will pay your own weight in gold for it.

Once I have preprocessed the audio, I switch into editing mode. Because I've usually written down most of the major edits, it doesn't normally take me very long. I'm using Logic Pro, and it gets the job done *just fine*, though it's pretty obvious that it's not really designed for podcast production. (When traveling I sometimes also use Ferrite, an iOS app, which is *incredible* value for money: full purchase is something like $20 and it's an absolutely fantastic podcast editing studio.)

My workflow is basically: cut out and rearrange as necessary for any of the flubs I made along the way and took notes on, then use Logic's handy strip silence tool to remove any particularly long gaps. I then listen through to the whole episode, pulling together all the places where there was silence, and adding in the musical cues for the intro, an initial sponsor read if there is one, and the outro. This is also the phase where I sometimes turn mistakes into bloopers—only if they're actually good or funny, though. I also add chapters marks into the audio, usually just corresponding to the section headings in the script, which get exported with the WAV file when I'm done. I use a free tool called Forecast to convert that into an mp3 file with chapters in it, and upload that to my hosting!

## Publishing and Hosting

So, speaking of hosting: how do I *publish* the show? Well, you can see that the website just rustdoc, of course, and I talked about *why* I did that all the way back in [the very first proper episode of the show][e001]. But if you know how podcasts work, you know that I need an RSS feed, and one set up to include downloads. And rustdoc… doesn't even know what RSS is, much less how to generate one for a podcast! I *could* write the RSS feed by hand, but happily there's an app for that. I use a tool called Feeder which generates RSS feeds with just about every option you could imagine, including podcasting—I basically just copy the show notes material into a standalone Markdown file and pipe that into the "notes" section for each episode in Feeder, and then my build process for the show pulls the generated feed output into the right location.

[e001]: https://newrustacean.com/show_notes/e001/

The show HTML (including that RSS feed) is all just hosted via GitHub pages. I currently use Backblaze's B2 service—which is effectively an Amazon S3 replacement—to host the audio files, because they're quite reliable and extremely low cost. That setup is one of my favorite things things about podcasting—simple file hosting and an RSS feed is all you need. It's all just built on open web tech!

### Google, Spotify, and Stitcher

And that leads me into the last part of this discussion—an answer to the question I get fairly often: <i>Hey, can you add the show to Google Play Podcasts or Spotify or Stitcher?</i> And the answer is: <i>I could, but I won't.</i> I'm not particularly ideological about many things in software—I save that for the theological side of my life!—but one thing I'm deeply committed to is the open web. The open web is an amazing thing: for all its messiness and all the nasty things that exist on it, the fact that I can put up a blog or a podcast using free, open technologies available to everyone is *amazing*. The fact that people from all over the world can listen to this because of that still astounds me, and I still think it's wonderful. And podcasting, like blogging, is an incredibly simple technology built on nothing but file hosting and RSS.

Unfortunately, Stitcher, Google Play Podcasts, and Spotify's podcast service all aim to make something *different* out of podcasting in their own ways. They're not the only ones, but they're the ones with the most influence. From a technical perspective, all of those services re-host—and, just as importantly, re-compress—my audio. That annoys me first and foremost because I've made extremely careful and considered decisions about my audio; I don't want anyone else changing that. It frustrates me second because they do it primarily because it gives them more insight into their users' behaviors, and it turns out there's money to be made there. Although there are technical benefits to them—controlling that means they have command over streaming, the source won’t go down, etc.—the deeper reasons are those economic reasons.

And that leads me to the final reason I consistently refuse to put *any* of my podcasts on those services or any others like them which may appear in the future: they're interested in monetizing my content and your listening habits for themselves—not for you and not for me. In particular, they want to do that by analyzing everyone's listening habits and trying to deliver more targeted ads. I'm simply not on board with that model. Finally, in each of those cases they clearly want to be *the* source—the sole or primary gatekeepers and middlemen—for podcasting. And I have no interest whatsoever in contributing to the centralization of yet another open web standard. We don’t need a Facebook for podcasting.

Now, to be clear, I don't think it's wrong for anyone to use those services, and I don't think there's anything wrong with other podcasters making different choices about these particular tradeoffs! Depending on what your podcasting needs look like, it may be worth dealing with those downsides as part of a larger play to be financially viable, or because you’re part of a podcast network that is on those platforms, or simply because those tradeoffs don’t bother you as they do me. That’s legitimately fine: this is a complicated space when it comes to the moral reasoning! But this is a place *I* draw the line. If Google, Spotify, and Stitcher decide to work the same way everyone else does—*with* the open web—they're welcome to my shows. Because, after all: it's just RSS! But so long as they're trying to do an end-run around the open web for better ad monetization, I'm not interested.

## Outro

Anyway, that's it for this bonus episode. I hope it was interesting, and if it piqued your curiosity or encouraged a budding interest in podcasting, I do encourage you to check out the podcasting guest lectures I mentioned a few minutes ago—you can check them out in the list of bonus episodes at <winningslowly.org/season-bonus.html>, and I've linked them both in the show notes! Likewise, if the ethics concerns of this particular episode are interesting to you, Winning Slowly is likely to be of interest in general. This season, my cohost and I are basically arguing it out every episode in the interest of finding a third way that is neither techno-utopianism nor radical techno-skepticism.

### Patreon Sponsors

Thanks as always to everyone who sponsors the show! This month’s $10-or-more sponsors included:

- Oladapo Fadeyi
- Nick Stevens
- Rob Tsuk
- Embark Studios
- Alexander Payne
- Ryan Osial
- Matt Rudder
- Bryan Stitt
- Graham Wihlidal
- Daniel Collin
- Oluseyi Sonaiya
- Daniel Mason
- Jako Danar
- Raph Levien
- Peter Tillemans
- Soren Bramer Schmidt
- Evan Stoll
- Adam Green
- Anthony Deschamps
- Brian McCallister
- Joseph Schrag
- Jonathan Knapp
- John Rudnick
- Benjamin Manns
- David Carroll
- Behnam Esfahbod
- Jason Bowen
- Paul Naranja
- Dan Abrams
- Chip
- Nick Gideo
- Martin Heuschober
- Scott Moeller
- Jerome Froelich
- James Hagans II
- Nathan Sculli
- Ramon Buckland
- Arun Kulshreshtha
- Michael Mc Donnell
- Andrew Dirksen
- Johan Andersson
- Nicolas Pochet

You can sponsor the show at <patreon.com/newrustacean> or via other services listed on the show website, <newrustacean.com>. There, you’ll also find show notes, including links to things I talk about, scripts, code samples, and interview transcripts. The notes for *this* episode are at <newrustacean.com/show_notes/bonus/_14/>.

Please recommend the show to others if you like it, whether in person, via your podcast directory, or in various media online! You can contact me at @chriskrycho or @newrustacean on Twitter, or by sending men an email at hello@newrustacean.com.

Until next time, happy coding!

================================================
FILE: docs/bonus/burnout-script.md
================================================
# Bonus: Burnout

Hello, I’m Chris Krycho and this is New Rustacean: a show about the Rust Programming Language and the people who use it. This is a bonus episode, on *burnout*.

For today’s episode, I’m going to do something slightly different than usual. All the sponsors and show notes stuff will be up front in the next two minutes. After that, I’m going to talk about burnout and my experience of it—but there’s no script today. My *hope* is that hearing me talk about it, and talk about it “off script,” will help someone out there.

So: let’s talk sponsors.

## Sponsor: Parity Technologies

First, Parity Technologies is sponsoring this week’s episode because they want to hire you! Parity is advancing the state of the art in decentralized technology. Their flagship software is the Parity Ethereum client, but they're also building cutting-edge tech in areas like WebAssembly and peer-to-peer networking. Their next big project is Polkadot, a platform leveraging blockchain tech for scaling and interop in decentralized systems. Parity uses Rust for its trifecta of safety, speed, and correctness! If that sounds interesting, check out their jobs at paritytech.io/jobs.

Thanks again to Parity!

## Patreon Sponsors

Second, thanks to everyone who sponsors the show on Patreon! As of recording, there are 100 of you sponsoring right now, and I find that particularly amazing and encouraging in the midst of the burnout I’ve been experiencing. This month’s $10-or-more sponsors included:

- Ryan Osial
- Anthony Deschamps
- Peter Tillemans
- Nicolas Pochet
- Marshall Clyburn
- Martin Heuschober
- Matt Rudder
- Paul Naranja
- Oluseyi Sonaiya
- Hans Fjällemark
- Dan Abrams
- Michael Mc Donell
- Nathan Sculli
- Rob Tsuk
- John Rudnick
- Daniel Collin
- Daniel Mason
- Ramon Buckland
- Joar Wandborg
- Chip
- Graham Wihlidal
- Alexander Payne
- Behnam Esfahbod
- Raph Levien
- Nick Stevens
- Aaron Turon
- Zachary Snyder
- Chris Palmer

If you’d like to sponsor the show, you set up ongoing support at patreon.com/newrustacean, send a one-off at any of a number of other services listed at newrustacean.com, or get in touch directly. The website also has scripts and code samples for most of the teaching episodes as well as transcripts for many of the interviews, along with full show notes for every episode. You can find the notes for \_this\_ episode at \<newrustacean.com/show\_notes/bonus/burnout\>.

If you're enjoying New Rustacean, please help others find it – by telling them about it in person, by sharing it on social media, or by rating and reviewing the show in your favorite podcast directory.

The show is on Twitter @newrustacean, or you can follow me there @chriskrycho. Tweet me with news, topic ideas, etc! You can also respond in the threads on the Rust user forums, Reddit, or Hacker News, or—and this will always be my favorite—just send me an email at hello@newrustacean.com.

---- 

Okay, so let’s talk about burnout.

- what it isn’t
- what it is
	- Mayo clinic guidelines:
		- Have you become cynical or critical at work?
		- Do you drag yourself to work and have trouble getting started once you arrive?
		- Have you become irritable or impatient with co-workers, customers or clients?
		- Do you lack the energy to be consistently productive?
		- Do you lack satisfaction from your achievements?
		- Do you feel disillusioned about your job?
		- Are you using food, drugs or alcohol to feel better or to simply not feel?
		- Have your sleep habits or appetite changed?
		- Are you troubled by unexplained headaches, backaches or other physical complaints?

		Mayo calls it:  

		> a special type of job stress

		But the triggers aren’t just *job*-related

		Job-related causes Mayo suggests:

		- Lack of control.
		- Unclear job expectations.
		- Dysfunctional workplace dynamics.
		- Mismatch in values.
		- Poor job fit.
		- Extremes of activity.
		- Lack of social support.
		- Work-life imbalance.

		I add:

		- long-term stresses in family life, e.g. your dad gets a brain tumor or you’re a caregiver for someone
		- specific triggers can take “I’m stressed” -\> “burnout”

- it gets worse if you don’t deal with it
- how do you deal with it?
	- sleep
	- don’t overwork
	- friends
	- exercise
	- counselors! meds!

================================================
FILE: docs/bonus/translating-between-languages-script.md
================================================
# Bonus: Translating Between Languages

Hello, I’m Chris Krycho and this is New Rustacean: a show about the Rust Programming Language and the people who use it. This is a bonus episode on translating between programming languages.

## Sponsor: [Manning Books/Rust in Motion](http://bit.ly/2OXnlEb)

First up, a new sponsorship! I’m *really* excited to be partnering with Manning Books to bring you a discount on some *video content* they’ve put together. Even better because that video content is by Carol Nichols (whom I interviewed a couple years ago) and her husband Jake Goulding! I’ve been saying for years that we need more video content: it’s a huge way people learn. Manning’s Rust in Motion is one of the first major video courses for Rust I know of. You can get it for 40% off at [deals.manning.com/new-rustacean](http://bit.ly/2OXnlEb) – there’s a link in the show notes. That link actually gives you 40% off of *anything* at Manning, including their book *Rust in Action*, which is in early access preview. Thanks so much to Manning for sponsoring the show and building some great video content with Carol and Jake!

## Translating from TypeScript

I’ve mentioned a number of times on the show that my day job is building a web front-end in JavaScript and TypeScript—these days, pretty much entirely TypeScript. I recently had an opportunity come up to work on a side project where I am converting some library code from TypeScript to Rust, to accelerate this project via WebAssembly in the browser. I hope to have more to say about that project in the future; for now, what’s most interesting to me for this little bonus episode is what that *experience* has been like. There’s an interesting nugget here for reflecting on programming languages and what makes them valuable.

I’ve said to a number of people over the last year that writing TypeScript and writing Rust can feel very similar. Their surface syntax has a lot in common, and depending on how you write your TypeScript, the semantics can end up feeling relatively similar as well. “Depending on how you write your TypeScript,” is an important qualification. There are a *lot* of ways to write TypeScript, because there are a lot of ways to write JavaScript, and TypeScript is just type annotations on top of JavaScript. If you’re writing TypeScript like it’s C# or Java, it won’t feel much like Rust at all. But if, like me, you prefer a more functional idiom and you use TypeScript kind of like a weird, extremely verbose version OCaml, with carefully controlled mutation, well, it ends up feeling a lot like Rust. After all: Rust is kind of like OCaml, but with explicit control over ownership and mutation! So in my experience, writing TypeScript and Rust felt pretty similar, in very good ways, a lot of the time.

But. Let me tell you. When you start trying to translate things from TypeScript to Rust, stuff gets really weird, really fast.

One of the things that initially feels very similar between the two, for example, is the type system. And so far as it goes, that feeling is not totally wrong. Both languages give you generic types; both give you interface-like ways of expressing constraints and let you bound generics with those interface-like structures—literally `interface` in TypeScript and of course `trait` in Rust.

There are important differences in both the surface syntax and the underlying semantics, especially in the languages’ type systems, though, of course. The most obvious difference at the *surface* is that TypeScript has a structural type system, where it only cares about the *shape* of the objects you pass, where Rust has a nominal type system: two structs with the same fields are still different structs, because they have different *names*. What’s more, TypeScript has anonymous, bare union types but doesn’t have built-in tagged unions like Rust’s enum types. So in TypeScript you can say something is a string or a number, without any wrapping name; but you have to write a ton of boilerplate to get the equivalent of Rust’s `enum` types. And vice versa: in Rust you get *tagged* unions for free, but you can never have a *bare* union type: you always have to do the boilerplate of wrapping those kinds of things in an enum. So there are real differences at this level!

But while I thought those would be the thing that would end up leading to the biggest mismatch, it turns out that accommodating for *those* isn’t that hard. You have to write some enum types out more explicitly, and you can throw away some of the workarounds and boilerplate that come from not having Rust’s `enum` tagged union types in TypeScript, but it’s not that bad, because the semantics are relatively similar, even with those differences in surface syntax.

No, what gets really weird is the combination of TypeScript’s `interfaces` *not* being isometric with Rust’s `traits`, and *ownership*. In retrospect, the latter should have been obvious, but the `interface`/`trait` distinction was a lot *less* obvious.

Let’s start with the obvious one, and then we’ll use it as a way of circling back around to the `interface`/`trait` thing. TypeScript’s approach to interfaces and classes is (mostly) like interfaces and classes in most object oriented languages you’d be familiar with: both interfaces and classes can include both data and functions. Rust… doesn’t do that. At all. As we’ve talked about in recent teaching episodes, Rust makes a clean separation between *data* and *behavior*. `struct` and `enum` types have data. `trait` types have behavior. And never the twain shall meet.

Layered on top of that is the ownership system: TypeScript is perfectly happy to let you have lots of shared mutable references to the same data, recursive types are be fairly idiomatic, and cycles between data structures are no big deal (though they *can* cause memory leaks if you’re not careful). All of this is perfectly normal for a garbage-collected language! Meanwhile, Rust has as its most basic distinctive the *every piece of data has a single owner* rule. Recursive types are *not* all that idiomatic, and have to be explicitly wrapped in some kind of pointer type; and shared mutable references to the same data are right out. Cyclical data relationships in Rust are just a quick way to pain: you can make them work, sometimes, but it’s hard and never natural.

So if you go to try to translate a TypeScript `interface` straight into a Rust `trait`, or a TypeScript `class` straight into a Rust `struct`, *things get weird.* This is because of the real differences between the two languages is in their base semantics—the deep structure and most important constraints of the languages. These aren’t things that are apparent from surface syntax, since the surface syntax of the two is pretty similar!

Now, as an aside, this doesn’t mean syntax doesn’t matter. People often step from “syntax doesn’t map perfectly to semantics” to “syntax is irrelevant,” but the second doesn’t follow from the first. Syntax can map more or less cleanly to the underlying semantics, and it can lead—or mislead—by the way it’s shaped. So what we ought to say is that while syntax matters, it’s far from the *only* thing that matters.

What I have ended up finding as I’ve worked on this translation project is that sometimes an `interface` in TypeScript translates to a `trait` in Rust… but sometimes it should be a `struct` or an `enum`! It depends on how it’s used and what the mechanics in play are. Likewise, things like an abstract base class in TypeScript don’t have *any* corresponding notion in Rust, so you have to dig a bit on what the intent is and then spend a while thinking about how you might express that intent in Rust.

More, sometimes it may not be possible to express exactly the same thing in Rust in any idiomatic way, or sometimes even at all. For example, as I noted a moment ago, TypeScript supports cyclical types: it’s just modeling the way JavaScript behaves at runtime, and JavaScript types can and do have cycles. If you want an object with a reference to its parent which references the item as its own child, well… Rust doesn’t have a fun time with bidirectionally linked tree structures. You can *make* it work with `Rc` (or `Arc`) and `Weak`, but if you then need to handle, say, partial equality with the `PartialEq` trait, you need to define local newtypes to avoid the orphan rule, and so on.

The net of all of this is just an interesting little observation on the realities of how different languages lead us to solve problems in different ways. Things that make very good sense in TypeScript are so difficult or un-idiomatic in Rust that you would just *never* do it that way. And the inverse is true as well, of course! There are plenty of things that Rust’s type system makes easy that are much harder to do in TypeScript, since Rust can (and does) assume that its types are useful inputs for defining runtime behavior and TypeScript has to just erase all of its types entirely, with JavaScript’s runtime behavior only *hopefully* matching the types!

And that is a good reminder of why I think being a polyglot programmer is *really good*. Different languages, even the ones which are superficially similar, help us *think* in different ways.

## Closing

I’m sure I’ll keep learning as I keep pushing forward on this, but I thought it would make for an interesting little aside here—thanks for listening, and I hope you enjoyed it!

Thanks to everyone who sponsors the show! This month’s $10-or-more sponsors included:

- Behnam Esfahbod
- Ryan Osial
- John Rudnick
- James Hagans II
- Peter Tillemans
- Alexander Payne
- Michael Mc Donnell
- Chip
- Dan Abrams
- Joseph Marhee
- Bryan Stitt
- Rob Tsuk
- Daniel Mason
- Oluseyi Sonaiya
- Adam Green
- Nathan Sculli
- Graham Wihlidal
- Scott Moeller
- Joar Wandborg
- Nick Stevens
- Raph Levien
- Daniel Collin
- Chris Palmer
- Anthony Deschamps
- Nicolas Pochet
- Bryce Johnston
- Paul Naranja
- Ramon Buckland
- Matt Rudder
- Martin Heuschober
- Jonathan Knapp
- Aaron Turon

If you’d like to sponsor the show, you set up ongoing support at patreon.com/newrustacean, send a one-off at any of a number of other services listed at newrustacean.com, or get in touch directly. The website also has scripts and code samples for most of the teaching episodes as well as transcripts for many of the interviews, along with full show notes for every episode. You can find the notes for \_this\_ episode at \<newrustacean.com/show\_notes/bonus/functional\_programming\>.

If you're enjoying New Rustacean, please help others find it – by telling them about it in person, by sharing it on social media, or by rating and reviewing the show in your favorite podcast directory.

The show is on Twitter @newrustacean, or you can follow me there @chriskrycho. Tweet me with news, topic ideas, etc! You can also respond in the threads on the Rust user forums, Reddit, or Hacker News, or—and this will always be my favorite—just send me an email at hello@newrustacean.com.

Until next time, happy coding!


================================================
FILE: docs/bonus-2-script.md
================================================
Legacy Code
===========

Intro (15s)
-----
Hello, I'm Chris Krycho, and this is the New Rustacean podcast---a 15--20 minute
show about learning the Rust programming language. This is **Bonus Episode 2:
Legacy Code**


Talk (6-8m)
----

  - Talking with a colleague about changes we're making to a codebase right now.
  - History: all but one major job or contract == maintenance.
  - The problem: a lot of times, legacy code is a mess.
  - The temptation: FIX ALL THE THINGS!!!
  - The other problem: stuff (usually, for the most part) actually works now
  - The solution: clean up your mess as you go. Be a good Boy Scout.


Closing (1m)
-------
### Sponsors
Thanks to Chris Palmer for sponsoring the show this month! See the list of other
sponsors in the show notes.

If you'd like to sponsor the show yourself, you can set up recurring donations
at Patreon.com/newrustacean, or one-off donations at Venmo, Dwolla, or cash.me.

### Follow/support
You can find show notes with detailed code samples illustrating these ideas, as
well as links to things mentioned on the show, at NewRustacean.com. You can also
follow the show on Twitter or App.net @newrustacean, or follow me there
@chriskrycho. If you like the show, please rate and review it on iTunes to help
others find it. Last but not least, I'd love to hear from you on social media,
in the thread for the show on the Rust user forum at users.rust-lang.org, or via
email at hello@newrustacean.com.

Until next time, happy coding!


================================================
FILE: docs/bonus-3-script.md
================================================
Building as a Community
=======================

Intro (30s -> 0:30)
-----
Hello, I'm Chris Krycho, and this is the New Rustacean podcast---a show about
learning the Rust programming language. This is **Bonus Episode 3: Building as a
Community**.

Normal episodes are 15--20 minutes long, but bonus episodes like this one are a
bit shorter---usually under 10 minutes. I took a one-week long 8--5-every-day
class three weeks ago, and then started a new job two weeks ago, which included
getting trapped in New York City by a once-a-century blizzard, so I have not had
time to put together quite as technical a talk as usual. But today's topic,
community, is just as important for whether Rust succeeds in the long term---
maybe even more important---than some of the technical details we talk about
week in and week out.


Talk (6-8m)
----

  - **A story (2m):** learning Fortran
  - **Another story (2m):** learning Rust
  - **Takeaways (4m):**

     1. Community matters even for building something big and complicated, and
        you don't have to be a jerk to get really amazing results. Quite the
        opposite, in fact. (elaborate: Rust, Elixir, etc.``)

     2. Building *as* a community matters as well. It's great that we're kind to
        each other---really great. But we should also actively help each other.
        This is true of any project you want to succeed. You'd be surprised how
        much open-source projects need help, and how often you're actually one
        of the best people *to* help. If you see a problem, you are often in the
        best position to fix it simply because you know the pain point.

        And if you have a good community, like we do in Rust, people will help
        you help them. Ask around, look at lists of issues, etc.---and even if
        an issue marked "easy" looks too daunting, give it a go. Find a project
        that looks interesting, or useful, and offer to help. People will help
        you learn what you need to know to solve that problem. You'll grow, the
        project will be in better shape, and it'll be a win all around.


Closing (1m 30s -> TODO)
-------
Next time, we're going to go for a high-level but extremely important discussion
about type systems, both in general and specifically in Rust. Since Rust's type
system is such a big part of its interest, and one of a few things that
distinguishes it from languages like C or Java, I think it'll be fun and
interesting to talk about that in a bit more detail.

### Sponsors
Thanks to Hamza Sheikh and Chris Palmer for sponsoring the show this month!
Check out the list of other sponsors in the show notes. If *you'd* like to
sponsor the show, you can set up recurring donations at Patreon.com/newrustacean,
or one-off donations at Venmo, Dwolla, or cash.me.

### Follow/support
You can find show notes with detailed code samples illustrating these ideas, as
well as links to things mentioned on the show, at NewRustacean.com. You can also
follow the show on Twitter @newrustacean, or follow me there @chriskrycho. If
you like the show, you'd make my week by rating it on iTunes, recommending it in
another podcast directory, tweeting about it, or just telling a friend!

Thanks to everyone who's added corrections and fixed typos in the show notes;
pull requests are great. I also love hearing from you! Definitely say hi on
social media, add your thoughts in the thread for the episode on the Rust user
forum at users.rust-lang.org, or shoot me an email at hello@newrustacean.com.

Until next time, happy coding!


================================================
FILE: docs/bonus-4-script.md
================================================
# We *can* have nice things.

## Intro {>> 15s <<}

Hello, I'm Chris Krycho, and this is the New Rustacean podcast---a show about learning the Rust programming language. This is *Bonus Episode 4: We **can** have nice things.*

## News and Follow-up {>> 4m <<}

First up, some news---and there's a bunch of it this week!

Rust 1.8 was release this week! It's been just under a year since 1.0 came out, and in that time we've seen fairly dramatic movement forward in the language, but without any substantive breaking changes. Just about any package that built on 1.0 still builds, despite the language having gained a lot of new capabilities. I *love* that.

There are a few nice changes in Rust 1.8:

1. The plus-equals and minus-equals and similar operators are now overloadable via the op-assign family of traits, like `AddAssign`. That's a small but very nice improvement; getting to a point where all those kinds of things are extensible via traits makes for a more consistent, and more robust, programming model for Rust.
2. The first steps toward building Rust itself with Cargo, instead of with Make, are now on stable. This is bootstrapping taken to another level entirely: we're headed toward a point when Rust itself will be used for all the pieces around building Rust. If you're worried about not-invented-here syndrome, that's a good caution, but having experienced quite a few different package managers and tools lately... I think this is a good move. Make is a great tool, but Cargo is a much better one for these purposes, and the combination of Cargo and crates.io is *really* good---far better than pretty much anything else out there.
3. In just a few release cycles, Rust will no longer require a special nightly build of Rust to build itself: it will always be built using the previous version of the compiler, so 1.10 will be built with 1.9, and 1.11 with 1.10, and so on.
4. There's a new tool for managing Rust installations currently in beta. It's called "rustup", just like the current standard install script, but it's actually a pure-Rust implementation of the multirust tool. If you're familiar with tools like rbenv, pyenv, nvm, etc., this is that kind of tool: it allows you to manage multiple installations of your language, and set local directory rules for which version to use, and so on. Try it out!

Second, a quick note on scheduling: the last few weeks have been really, *really* busy for me between work, my Master's degree, and some family stuff. But I've had Rust on my mind a *lot*, between watching the 1.8 release come out, watching Sean Griffin live-code on Diesel a bit, and especially by way of comparison with all the JavaScript I'm writing for my day job. So here's a bonus episode, with the Strings episode to be recorded this coming weekend!

## Body {>> 7m <<}

I've been writing a ton of EmberJS for my day job, and I keep looking around for something *like Rust* in the JavaScript world. There are plenty of compiled-to-JavaScript languages out there, from CoffeeScript (which kind of kicked off that whole trend); to things like TypeScript, which shows the influence of the .NET team and C# pretty heavily; to Elm and PureScript, which are heavily inspired by Haskell. But none of them have the really wonderful mix of pragmatism and elegance that seems to characterize Rust to me. Rust is a fairly unique mix, with its extremely capable type system, performance, and what we often call *ergonomics*---how it feels to use. It's no one thing: it's syntax and semantics; it's a strong, *expressive* type system; it's the lack of nulls; it's powerful enumerations; it's trait-oriented instead of inheritance-oriented polymorphism; it's the whole package together. Basically, every day I write JavaScript and look at the alternatives, or even fairly solid other languages like C#, the more impressed I am by Rust.

People often wonder what the best way to learn a programming language is. The common answer is "just use it," of course: but how? How do you *start*, especially if it's not something you can use day-to-day for work, and if you don't have a specific project in mind for it? One of the best answers is: use it to build all the little tools you need for *other* projects. A colleague noted that the way he learned F# in a way that *stuck* was using it with the Fake tool to write (and now maintain) a bunch of our in-house tooling. You can do the same thing with Rust. Just write *something* in it. Because as much as Rust gets pegged as a "systems programming language" because it has the ability to do low-level work, the truth is that it's also just really good in its own right for *general* programming tasks.

Over the weekend, I saw some posts on Hacker News about the Rust 1.8 release which hit on this same theme. Several users noted that they'd been using Rust more and more for the kinds of small projects where they once would have defaulted to something like Python. Between how solid a package management and build tool Cargo is, and the fact that once you get a Rust binary to *compile*, many times it already does what you want it to, it's extremely powerful. And it's also the kind of thing you can just install and run on *any platform*. Anybody who's spent time trying to distribute, say, Python or Ruby programs knows how valuable that is. Not having to install a runtime to install a program is a *big deal*.

I was talking about this on Twitter in light of that thread, and someone responded exactly how I've felt for a while now: it "Feels like Python, runs like C." In fact, this is actually what attracted me to Rust in the first place. When I started reading through the book, I remember very distinctly thinking, "Huh. This is the first language I think might replace Python as my go-to tool in general." And that's been born out by the last eight months of using it for little things here and there. And of course that goes for other languages, too; you could do the same with Elixir, or Haskell, or whatever else.

It might sound crazy to use Rust instead of Python for doing some relatively high-level work. Again: there's all that press out there about writing operating systems in it---and it's good at that. But that's not the only thing it's good at. The type system and good compiler mean that it's versatile and capable in all sorts of domains. Next time you need a utility... write it in Rust. You may be surprised at how straightforward it is, and you'll learn things about using Rust, and you'll come away with a better appreciation for just how well-designed the language is. I certainly intend to!

## Outro

### Sponsors

Thanks to Hamza Sheikh, Chris Palmer, and Vesa Khailavirta for sponsoring the show this month! You can see a full list of sponsors in the show notes.

If you're interested in sponsoring the show, you can set up recurring contributions at Patreon.com/newrustacean, or one-off contributions at Venmo, Dwolla, or cash.me, or get in touch with me directly.


### Follow/support

You can find links to those as well as to the discussion threads I mentioned at NewRustacean.com. You can also follow the show on Twitter @newrustacean, or follow me there @chriskrycho. You can help *others* find the show by rating and reviewing it on iTunes, recommending it in another podcast directory, tweeting about it, or just telling a friend!

So do respond on social media, in the thread for the episode on the Rust user forum at users.rust-lang.org, or via email at hello@newrustacean.com.

Until next time, happy coding!


================================================
FILE: docs/bonus-5-script.md
================================================
# Better than open source contributions

## Intro

Hello, I'm Chris Krycho, and this is the New Rustacean podcast---a show about learning the Rust programming language. This is *Bonus Episode 5: Better Than Open Source Contributions*.

## News and Follow-up

First, a quick explanation on the delay of this episode: we had a family health emergency come up---the kind that landed a family member in the hospital for several days---so recording this obviously took a lower priority. Podcasts are good and Rust is great, but family is far, *far more important*. As you'll see in a minute, that's actually especially fitting given the content of this particular bonus episode.

One of the big highlights for me in the last couple weeks is the announcement of the open-source Xi editor project, which aims to be a performant, extensible editor with a Rust text engine backing it and native interfaces in Cocoa and eventually .NET, GTK, etc. This is incredibly interesting to me for a variety of reasons, some them algorithmic (like the fascinating *ropes* algorithm he's using to implement the text engine; and others architectural, like the planned structure for linking the front and back ends; and of course some simply Rustic: this is *exactly* the kind of thing I've long had in mind to use Rust for, and the reason I started learning it in the first place. I'll link the project in the show notes, and you should definitely keep an eye on it.

One other thing to check out: for Rust's 1.0's one-year birthday, the Rust team launched a community survey. I've linked it in the show notes, so go fill it out!


## Open source

Now, for today's topic. Over the last few years, I've often seen the suggestion that you need to be actively involved with open source software for the sake of your career. Last week, I saw someone say flat-out that he won't hire someone who doesn't do a bunch of open-source work in their spare time.

This is, in a word, *nonsense*.

To start with, I don't really buy the argument that it's somehow a mark of a good developer. I've had several jobs where it wouldn't have been remotely relevant---and for the job I have now, which is an absolute dream in many ways, I don't have any reason to believe the meager open source contributions I *had* made impacted the hiring decision whatsoever. And that's as it should be, because I think it would actually be a disaster if most companies started treating open-source contributions as a major component of a hiring decision. Or, for that matter, *any* component, for the vast majority of jobs. (The only exception is a job where you're being hired to work *on* open-source. But those are pretty rare.)

Why does this even come up? Well, employers tend to care about open-source contributions on your resume for a couple reasons.

1. **They see it as a way to evaluate your code quality.** This is a reasonable desire, but there are lots of ways to do this which don't involve requiring open source work. One of my favorites, an idea o picked up from The Frontside, is for a company to hire you at their standard consulting rate for a day and just work with you directly. This gives you a good feel for the company, gives the people at the company a good feel for where your skills really are and how you work with a team, and---incredibly importantly---doesn't ask you to do something for free to prove your value as an employee.
2. **They see it as a sign that you're the kind of employee they want to hire, because they want people who do a lot of programming outside of work.** From companies like this, just run away. Basically, this means two things about the company in question:
	1. They do not value anything about you except your programming interest. As I'll come back to in a minute, this is a profoundly misguided view of what makes for a healthy employee---because it's a profoundly misguided view of what makes a healthy *human*.
	2. It drives the company toward a monoculture, and means it will miss out on a lot of other wake vey qualified and talented people, whose input and perspectives will be enormously enriching. While diversity can become a sort of totem, something people chase for its own sake, I think a wide variety of perspectives really is quite good for the work we all do. More than that, though: do you really want to work at (or be) the kind of company that turns down a programmer just because she's a mom who thinks spending time helping her kids with their homework in the evening is more valuable than doing open source software? Or because he's a son whose parents are ill and he takes care of them? Or because she's spending nights and evenings investing in community theater? Or any number of other legitimate, healthy, human reasons people have to do something besides *code* in their spare time?

Don't get me wrong. I like doing software work for fun. I make a podcast about a programming language, for goodness' sake. But demanding that everyone fit that mold is incredibly shortsighted; it will make you build a pretty terrible company culture filled with people who are just clones of you. And it inherently devalues everything else. At the end of the day, you don't want to work for a company that's incapable of seeing things besides software as valuable. If "you must do open source" is one of their prerequisites, keep applying for other software jobs. There are more than enough to go around.

But let's take this one step further: even the "we want you to have other hobbies" line you sometimes hear can be a problem. Some companies want you to have outside activities and not sell yourself to the job for reasons that are still, at the end of the day, purely mercenary. It's increasingly well-known that people are more productive on the job when they have healthy personal lives, so it's understandable that well-informed companies are starting to value that. But I think that, while that shift is good in one way, in too many cases it still comes down to a commoditization of people. In a way, it's worse than the more directly exploitative practices it replaces: it says that families and non-work hobbies are valuable not because they're good, essential parts of human existence as it is supposed to be, but merely as more means to the end of profit. And human beings and human relationships are not means, but ends in and of themselves. When we turn people's entire lives and all their loves into nothing more than another way to maximize productivity and profit, we have gotten things completely backwards.

Now of course it *does* help, but that's because people are meant for more than work! We are not meant for less: work is good. Programming is good. Creating things and putting them into the world is good. But those things aren't everything, and we should never, *ever* make everything about them.

Don't get me wrong. I'm grateful that my employer is quite serious about people taking care of their families and leaving work at work. And if you're running a business or managing a product team, you will probably find that people do give you better work when you encourage them to do things besides programming. But don't make the mistake of reducing people to levers for profit. And if you're an employee, don't make the mistake of letting someone demand that you make your life about the job---not directly and not indirectly. Be okay interrogating the way companies think as well as what they do, because *it matters*. It *really* matters. The best kinds of companies want you to spend time with your family and have things you're passionate about outside of work not just because it's good business, but because it's simply *good*.


## Closing

In some ways, as much as I love talking about Rust---and as happy as I'll be to hop back into that next time---I think it's worth stopping to say things like this. Thanks for listening, and if you found this episode helpful, do please share it with friends or colleagues.

### Sponsors

Thanks to Chris Palmer, Hamza Sheikh, Daniel Collin, and Vesa Khailavirta for sponsoring the show this month! You can see a full list of sponsors in the show notes.

If you're interested in sponsoring the show, you can set up recurring contributions at Patreon.com/newrustacean, or one-off contributions at Venmo, Dwolla, cash.me, or Flatttr---or get in touch with me directly.


### Follow/support

You can find links to everything I mentioned at NewRustacean.com. You can also follow the show on Twitter @newrustacean, or follow me there @chriskrycho. You can help *others* find the show by rating and reviewing it on iTunes, recommending it in another podcast directory, tweeting about it, or just telling a friend!

So do respond on social media, in the thread for the episode on the Rust user forum at users.rust-lang.org, or via email at hello@newrustacean.com.

Until next time, happy coding!


================================================
FILE: docs/bonus-6-script.md
================================================
# It doesn't need to be sexy

## Intro

Hello, I'm Chris Krycho, and this is the New Rustacean podcast---a show about learning the Rust programming language. This is *Bonus episode 6: It doesn't need to be sexy.*

## News and follow-up

-   Aaron Turon and Alex Crichton published their new `futures-rs` crate, which provides some low-level primitives for a concept variously called *futures*, *promises*, or *delayed* or *deferred* values. I'll link the crate in the show notes; it has some great documentation as well as being what looks to be a pretty solid implementation. I'll come back around and devote an episode to futures in the future. This is a huge thing for the ecosystem, and part of what makes it great is that it's not part of the language, but built on top of it---the language's core primitves expose everything required to do it and do it *well*. This will open a *lot* of doors for higher-level interfaces in lots of other libraries.

-   Closely related, Carl Lerche, the author of the Mio low-level I/O Rust library, recently published Tokio, a network application framework, which takes advantage of `futures` directly.

-   I just bumped into a project called Shadercat, by Claudia Doppioslash, who's already decently well-known for her work helping teach people about functional programming---but in this case, she's looking at doing graphics program with Unity and Rust. If those are interests of yours, you should definitely subscribe to the blog, which I'll link in the show notes.

-   _The Rust Programming Language_ is now a co-authored work by Steve Klabnik and Carol Nichols, who co-founded Integer32, the first Rust consultancy (which I mentioned a few episodes back).

-   Speaking of *writing* projects, keep your eyes open; I have a Rust-related writing project coming your way later this fall, which I'll discuss in more detail once it's out!

Now, for today's discussion.

## What to build

Over the past few months, as I've watched and participated in the Rust community, I've noticed a pattern (and I include myself in it): we glorify the compiler team and work. A lot of the focus in the community is on the language core itself. And this is a problem.

Now, I get this: like I said, I've been guilty of that myself, right down to the kinds of things I've focused on in my "News" sections. The language is *cool*, and the team working on designing it and tweaking it is very talented. More than that, having a language moving forward at such an active pace is something fairly novel. To the best of my knowledge, there is nothing else quite like the pace of post-1.0 Rust development, where a language is simultaneously stable *and* improving its capabilities rapidly, making it better at solving many problems and capable of solving new ones. It's *exciting*.

It's especially tempting because we can jump in and participate in helping improve the language itself---not an experience most of us have had in other language communities, even really great ones. There are a lot of upsides to just how open the Rust development process is, and this is one of them.

But.

*If* we want Rust to really flourish and succeed, we need to look more broadly and choose things besides the compiler to focus our attention on, and to lavish our praise on. And that's a two-fold change:

1.  We need to keep our eyes open for other significant open-source projects in the community, and chip in on those.

2.  We need to look around and note all the *other* things there are to work on, including the small ones, and buckle down and do those.

Let's take those in turn.

### Filling major gaps

First, on filling big gaps: There are a bunch of projects in a fairly nascent state which could make a *big* difference in how useful Rust is and how easy it is for companies to adopt it. And it's worth understanding that one of the biggest things that helps languages be more than an exciting flash in the pan is getting them used in "industry" settings. You're starting to see some of this with Rust already---companies from Dropbox to Academia.edu and many others.
    
But for Rust to go from *niche* to *everywhere*, there are a lot of pieces of "infrastructure" that need to be built outside the language itself. *Big* infrastructure pieces. We need both the low-level infrastructure pieces like mio and the new futures library I mentioned at the top of the show, and some higher-level abstractions sitting on top of those to make it easier for people to build e.g. web services easily. {>> TODO: other gaps <<}
    
### Filling smaller gaps

What about all the little pieces? The community actually has a good start on this. Lots of us have built little exploratory projects---another Rust binding to some C library, a part of an XML parser, etc.---and those are *great* for little learning projects, but we also need to take a lot of those and turn them into production-level tools that are at a level that can be used in larger projects.
    
Now, don't be discouraged: if you've written that kind of small project, and you're thinking, "No way is this ready for some big company to depend on; I'm still just learning!" that's okay. No one should be sad about learning and learning in public, and no one should feel ashamed of their projects. *All* I mean is that as we move from the "just trying this out" phase to the phase where we feel reasonably competent with the language, we can start looking around and thinking about how we can turn "my first XML parser" into a *great* XML parser---perhaps by collaborating with several others who've done the same, and looking at some of the state-of-the-art options out there.
    
Those kinds of small projects aren't that *sexy*, but they're incredibly important. In many ways, given a sufficiently decent lanaguage *foundation*, they're actually *more* important than anything else that the language might do. If you don't believe me, look at JavaScript: the language has a lot of issues in its design, and there are well-known problems with the Node.js ecosystem and tooling. I *like* JavaScript, but the amount of time I've spent chasing down something which broke five layers deep in an npm dependency is infuriating.

But none of that matters that much, because there is also a vibrant community trying to solve every problem imaginable---sometimes several times over in different ways, which causes its own set of problems! And the result is that, whatever the language's warts and whatever the weaknesses of the tools, the Node.js ecosystem is flourishing. And a huge part of that is simply people's willingness to build small things which *aren't* glorious, which aren't at the very center of the community.
    
A willingness to embrace that idea---that it doesn't have to be sexy for it to matter and be a valuable contribution---is huge. We need that in spades for Rust to become all it can. So: go write an incredible XML parser (or, better, help make one of the two that already exists more robust and capable). And then maintain it: fix bugs when they're found, keep on top of pull requests as they come in, and generally try to make it useful to people.

There isn't a lot of glory in that. But it's *extremely* valuable.

And you know what? A lot of Rustaceans are out there doing just that. I saw news come by this week about everything from cryptography to building Alexa skills for the Amazon Echo to a library for getting input from gamepads and controllers. This is fantastic. So, number one: keep it up. And number two: let's work to celebrate those kinds of things just as loudly as the core language itself. They're not in competition. It's the combination of the language and the things we build with it that makes this all worth doing.

## Outro -- Sponsors and Following

Thanks as always to the sponsors who help make the show possible! This month, the sponsors included Chris Palmer, Daniel Collin, Eric Fulmer, Jared Smith, Raph Levien, Stephen Murawski, and Vesa Khailavirta for sponsoring the show this month! You can see a full list of sponsors in the show notes, and the top tier of sponsors on a dedicated page on the website as well.

If you're interested in sponsoring the show, you can set up recurring contributions at Patreon.com/newrustacean, or one-off contributions at a variety of other services listed at the show website: newrustacean.com.

There you will also find links to the news items from the top of the show, and code samples illustrating referencing and dereferencing data.

You can also follow the show on Twitter \@newrustacean, or follow me there \@chriskrycho. If you enjoyed the show, please help *others* find the show by rating and reviewing it on iTunes, recommending it in another podcast directory, sharing it online, or just telling a friend!

Also, please do respond on social media, in the threads for the episode on the Rust user forum or on Reddit, or via email at hello@newrustacean.com. I love hearing from you!

Until next time, happy coding!

================================================
FILE: docs/bonus-7-script.md
================================================
# Katas---learning by doing

## Intro

Hello, I'm Chris Krycho, and this is the New Rustacean podcast---a show about learning the Rust programming language. This is *Bonus episode 7: Katas---learning by doing.*

## News and follow-up

First, an apology a bit of explanation for the delay between episodes! In the last 10 days, I've traveled something like 4,800 miles for a conference and a wedding. There's are a couple of reasons I'm not at this year's RustConf or Rust Belt Rust conferences, and one of the big ones is this is too much travel! Gladly, the rest of the year is *much* slower, and things should normalize pace-wise from here.

Now, a couple quick bits of news and updates: First, literally *as I record*, the first RustConf is going on! Video from the conference will be made available after the fact, and you can bet I'll be watching it. One particularly fun bit related to *this* show---as you may recall: Raph Levien is presenting on his work on the Xi editor. I'm particularly excited about that talk.

Second, a couple neat things from around the community more generally:

- I mentioned Claudia Doppioslash's work on gaming and Rust in a previous episode; now she and a few others have launched arewegameyet.com, which highlights the state of tools for building games in Rust.
- That reminds me: if you haven't yet, take a look at areweideyet.com and arewewebyet.org to see the state of IDE support and web development respectively in Rust.

Third, some updates from core:

- There's a great discussion around direction and vision for the Rust language in 2017 on the Rust internals forum, which I'll link. Lots of good discussion about where and how to focus efforts to improve the language's adoption---you should read it and chime in!
- Early, early, alpha-level support for incremental compilation has landed in the nightly builds of the compiler, and support for that with Cargo is being built out now---some of the long-expected fruits of MIR landing. That should help compile times a *lot*.

## Katas

- I've been interested in Elm for a while (and why: ML-like, use JS at work, guarantees around it, etc.)
- I've gone back to same problem in JS repeatedly
- Idea isn't new to me: "katas" are a thing out there
- The actual problem isn't hard, and that's a big part of what makes katas useful. The point isn't so much the problem---which you can figure out how to solve---as figuring out how to solve it *well* in *this* language.
- Going back to it as you become more familiar with the language, or as you pick up new ideas lets you apply newfound knowledge while not worrying about trying to understand the *problem*.
- So I did this "pizza test" with Elm. It took me a couple hours, because I was learning the language and its tooling and how the compiler works and so on
- Then I started in on it it on an even broader scale with Rust. Broader how?
    - Elm and JS are already in-browser setups. Rust is not.
    - Pull in a bunch of crates:
		- Hyper for HTTP requests
		- Serde for deserializing JSON
		- Pencil for serving the actual rendered page
		- handlebars-rust for simple HTML templates
	- Why? To get a feel for those crates as well as for what solving *these* problems in a Rustic way feels like, just as I was sorting through it in Elm.

The best ways to learn things in programming, in my experience are to *do* them, and to *teach* them. As I said in the very first episode of the show---almost a year ago, now!---that latter bit is one big reasons I'm making the podcast. It's helping *me* keep learning Rust while very busy with other things.

## Outro -- sponsors and following

Thanks as always to the sponsors who help make the show possible! This month, the sponsors included Chris Palmer, Daniel Collin, Raph Levien, Stephen Murawski, and Vesa Khailavirta for sponsoring the show this month! You can see a full list of sponsors in the show notes, and the top tier of sponsors on a dedicated page on the website as well.

If you're interested in sponsoring the show, you can set up recurring contributions at Patreon.com/newrustacean, or one-off contributions at a variety of other services listed at the show website: newrustacean.com, along with links to the bits I discussed on the episode.

You can also follow the show on Twitter \@newrustacean, or follow me there \@chriskrycho. If you enjoyed the show, please help *others* find the show by rating and reviewing it on iTunes, recommending it in another podcast directory, sharing it online, or just telling a friend!

Also, please do respond on social media, in the threads for the episode on the Rust user forum or on Reddit, or via email at hello@newrustacean.com. I love hearing from you!

Until next time, happy coding!


================================================
FILE: docs/bonus-8-script.md
================================================
# Giving Back (by Teaching)

## Intro

Hello, I'm Chris Krycho, and this is the New Rustacean podcast---a show about learning the Rust programming language. This is *Bonus episode 8: Katas---Giving Back (by Teaching).*

## News

Good news, everyone! I finished the course work for my Master's degree this past Monday, so things are settling down and it's going to be much easier to put out episodes every other week. (That last class was a weeklong intensive and was the reason this episode is reaching you a week later than usual.) Huzzah!

## Giving Back (by Teaching)

Now, a few thoughts on giving back by teaching.

Over the last few years, I've been working on finding ways to use the skills and abilities I have, and the advantages I've been given, to help others. There are lots of ways to do that. But one of them---and one of the ones I seem best equipped for---is *teaching*. This podcast is part of that. I haven't been in a spot where writing huge amounts of code outside of work was something I could do: I just didn't have that much spare mental energy between work and school. But writing a podcast, or a technical blog post, exercises a *completely* different part of my mind. So I've done that, and I intend to do a lot more: continuing to produce this podcast, giving well-prepared talks in my area, writing detailed technical blog posts, etc.

But I've also been thinking about other, more significant ways to contribute to the world around me. In the last month, I've bumped into two other men at my church who are on the very early parts of the curve in learning programming. So I've decided to set up "office hours" for a few hours in a local coffee shop every month, and I'm going to see what I can do to help these guys get their feet under them as software developers. There are two big "rules" I'm going to have for these office hours: anyone, of whatever skill level and interested in whatever language, is welcome. That means that even though I don't *love* Java or C#, I'm going to do my very best to help these guys get up to speed on them, because that's what they want to learn---and I'm not going to say a disparaging word about either language. There's time enough to talk through the tradeoffs which come with different languages when someone has their feet under them (and, better, when they have a *job* in the field, if they want it). I've also been looking around tentatively---and, after my wife and daughters and I move to be nearer our extended family sometime in the next year, will be looking around *intently*---at ways I can actively use my background and abilities to help others "bootstrap" their way into our profession. That might be serving in a correctional facility. It might be showing up at a learn-to-use-computers class. It might be any number of things. But I have been given much, and I take seriously the idea that much is therefore expected of me. I think we *all* ought to take that idea more seriously.

Accordingly I want to challenge you listeners: what are the ways *you* can help others? I have a few ideas, but I'd also love to hear more: tweet them at me @newrustacean, email me at hello@newrustacean.com, add them to the threads for the episode on Hacker News, Reddit, <users.rust-lang.org>, and I'll mention them on the show. (If I get *enough* feedback along those lines, I'll just write another bonus episode and talk through those options!) But in the meantime, let's look at just a few of the ways you might help, regardless of where you might be in your own technical journey. And remember: you might be at different points on this curve in different skills and frameworks and language. That's how it always goes.

### Total Newbie

So maybe you're just on the early side of the learning curve yourself. That's not just okay, it's *great*. You have some specific things you can offer to others both just behind you and far ahead of you---things that an experienced developer literally *cannot* offer, no matter how thoughtful. One is your *questions*. Ask them! File issues on projects you're using. If there is documentation and you can't make head or tails of it, open an issue. Be polite about it, of course, but be detailed and thorough: note what you don't understand with specific reference to the docs you're reading. Sometimes, people will just point you to materials which lay the foundation for what you're reading, and that's a win---but even there, it may suggest to them the kinds of things they might link from their own docs in a "you-need-to-know-these-things-first" way. One example of that which I really love: enough questions combined with a really thoughtful documentation team has led to the Ember.js documentation having two really helpful resources: a list of exactly those kinds of assumed foundational items, and a readily-accessible glossary of terms you might not know if you're a new developer, with links to further explanation of all of them. Those are the kinds of things it's *very* difficult for an experienced developer to identify in the specific. I might know *that* a fresh developer needs that knowledge, but I now suffer from the "curse of knowledge" and I don't remember the specifics of which pieces are confusing and how their combinations may also be confusing. So again: ask questions and open issues about confusing things!

The other thing total newbies can do, which helps enormously in tackling the same "curse of knowledge" problem, is explain things to others who are just a bit behind you. If you started learning Rust a week ago and have finished your first pass through the book, you know more than someone who just discovered the language---and your new eyes can make it easier to understand exactly what they're struggling with. You can help actively with that in several ways: by writing blog posts or giving introductory talks, or just by hanging out and answering questions in places like users.rust-lang.org and Reddit, or on the IRC, Discord, Slack, Matrix, etc. Those kinds of "I just learned this thing!" blog posts can be illuminating for others just trying to dip their toes in the water---and when you get something wrong (as I did in the last episode! More on that in the future), it's a chance for *you* to learn and also a chance for the folks further down the road to improve the ways the material is taught.

### Intermediate

Now, as an intermediate developer---and this is roughly where I find myself in many ways---it's sometimes murky what the best things to do are. You know enough that most day-to-day work is straightforward enough, but often not enough to tackle something like rewriting a significant library. But this is actually a great time to start investing actively in others. You *do* know enough to be productive, and that means that even if you're not an expert in a given subject, you know enough to help others get up and running. You're well-equipped to know what the common pain points in your tech stack are, and how you work around them: you have an immediate answer when someone says, "Wait, why is _foo_ not working?" because you've grown those calluses and know to simply insert a _bar_ there and move on.

It's also a great spot for doing more talks and blogging to stretch your *own* knowledge. I wrote a post about a couple new features in TypeScript a few months ago, because I knew enough TypeScript and enough JavaScript that I knew I *could* figure it out. That post in turn has been illuminating to others, not least since it was one of the earlier and more thorough posts on the subject. There was nothing especially profound about what I did there; I just wrote down what I was figuring out and put it online for others to find. Now it's useful not just to me but to others.

Finally, it's also a great time to be helping *write* documentation. If you spend time in the communities where people ask questions---again, the forums or chat channels---you'll see questions that come up over and over again. Find a good spot to add those to docs, or to wikis, or write a blog post explaining it both so you have an easy thing to link people to and also to help people find it by searching: not least because there are a lot of people who use any given tool but never actually make it into a forum or a chat room to ask for help.

### Expert

What about the grand gurus, who know a piece of tech inside and out---the Rust core team, or people like BurntSushi, who has developed the fantastic ripgrep tool, or any number of others I could name? Well, one is writing as careful and thorough documentation as you can manage. This isn't glamorous work, and it can feel like it's taking away from your productivity. But the reality is that true *experts* in a domain can offer something besides merely their ability to accomplish the technical tasks in the domain. They can also, if they're willing to work hard at it, *develop expertise in others*.

In fact, I'd go so far as to argue that the 10x-developer, usually considered mythical, *does* exist. Just not the way most people think when they talk about it. A developer who is brilliant and speedy, but who fails to pass on the knowledge he or she has gathered can accomplish an enormous amount. A developer who takes and shares her or his knowledge with others---who mentors others through their own process of developing expertise, who writes documentation so good that people new to a project can come up to speed quickly and then can accomplish something on their own---that developer can be a 10x developer *easily*. Empowering others can extend your own reach in surprising ways. It's also incredibly rewarding to watch other people go from "How does this work?" to mentoring others themselves.

I've never been formally mentored in the software world, but even the informal mentoring I've had from friends and acquaintances has increased my own capabilities dramatically.

That takes me to my last point for experts: step out of the way as people "level up." That's a huge part of *any* mentoring process, and it's tough for everyone, I think. But if you want people you're helping to truly succeed, you have to give them more and more responsibility with less and less support, and eventually also less and less feedback---trusting them to grow into that responsibility. Doing that can empower people *enormously*.

## Closing

So there are a few thoughts on ways you can give back. There are *lots* more, of course; I've focused mostly on "teaching"---not least because that's where I'm strongest! But I'd love---*love*---to hear your ideas on other things we can do to use our abilities and time and position to help others.

## Sponsors

Thanks to 

- Chris Palmer
- Christopher Giffard
- Dan Abrams
- Daniel Collin
- Matt Rudder
- Ben Whitley
- Peter Tillemans
- Philipp Keller
- Steven Murawski
- Raph Levien
- and Vesa Khailavirta

for sponsoring the show this month! You can see a full list of sponsors in the show notes.

If you're interested in sponsoring the show, you can set up recurring contributions at Patreon.com/newrustacean, or give a one-off contribution at any of a number of other services listed on the show website, or if you're a company interested in advertising to developers, please email me!

### Info

You can find show notes with links, code samples, and more at NewRustacean.com. You can follow the show on Twitter @newrustacean, or follow me there @chriskrycho. If you enjoy the show, please tell somebody about it! You can also help others discover the show by rating and reviewing it on iTunes, recommending it in other podcast directories, or sharing it around on whatever social media you use.

And again: I'd love to hear your feedback on this topic *especially*.

Until next time, happy coding... and giving back!


================================================
FILE: docs/bonus-9-script.md
================================================
# Outro


Thanks to this month's $10-or-more sponsors:

- Anthony Deschamps
- Chris Palmer
- Christopher Giffard
- Behnam Esfahbod
- Dan Abrams
- Daniel Collin
- David W. Allen
- Matt Rudder
- Olaf Leidinger
- Peter Tillemans
- Philipp Keller
- Raph Levien
- and Vesa Khailavirta

As always, thanks as well to everyone who helps other people find the show---whether by just telling a friend, or by rating or reviewing it in iTunes or recommending it in another podcast directory, or by sharing it on social media!

You can find show notes for this episode, including code samples for everything I discussed, at newrustacean.com/show_notes/e02. The show is on Twitter @newrustacean, and I am @chriskrycho. Tweet me with news, topic ideas, etc! You can also respond in the threads on the Rust user forums, Reddit, or Hacker News, or – and this is my favorite – just send me an email at hello@newrustacean.com.

Until next time, happy coding.


================================================
FILE: docs/cysk/bindgen-cbindgen-script.md
================================================
# CYSK: `bindgen` and `cbindgen`

## Intro

Hello, I’m Chris Krycho and this is New Rustacean: a show about the Rust programming language and the people who use it. This is Crates You Should Know: bindgen and cbindgen.

## [Sponsor: Parity](https://parity.io/jobs)

Before we dive in, Parity is back sponsoring the show—because they want to hire you to come work in Rust with them!

Parity is advancing the state of the art in decentralized technology, and they’re using Rust to do it, leaning hard on its trifecta of performance, reliability, and productivity. They're building cutting-edge tech in areas like WebAssembly and peer-to-peer networking. Two of the larger projects they're working on are: Substrate, a framework for building blockchains, and Polkadot, a platform leveraging blockchain tech for scaling and interoperability in decentralized systems.

If that sounds interesting, check out their jobs at <parity.io/jobs>!

## Motivation

Over the last few episodes we talked a great deal about <i>foreign function interfaces</i>, and I walked through how you can explicitly define and build those out yourself. However, as you can imagine, doing that for every single function and type you deal with in a large project with lots of FFI is… painful and error-prone. Happily, the work of mapping C interfaces to Rust interfaces can, by and large, be automated—with [the `bindgen` crate][bindgen source]. And, similarly, we can automate the work mapping Rust interfaces to C interfaces with [the `cbindgen` crate][cbindgen source]. Today, we’re going to dive into how each of them works!

[bindgen source]: https://rust-lang.github.io/rust-bindgen/
[cbindgen source]: https://github.com/eqrion/cbindgen/

## [`bindgen`][bindgen source]

`bindgen` is an *official* Rust tool, but it is not part of the standard library. That’s because it’s not needed for *most* projects in Rust, and it’s really a library for your *build* process rather than for your crate proper. It’s a tool for *generating bindings* from Rust to C and *some* C++ libraries. If the thought of writing out bindings by hand and hoping you get them exactly right every time seemed a bit intimidating… well, you’re not alone in that; I feel much the same!

bindgen only generates Rust bindings for C code. It’s designed to cover the half of the story that’s usually most important for integrating Rust into an existing codebase, where you want to be able to add Rust alongside C or C++. For example: this is exactly what Mozilla needed when they started pulling Rust into the Firefox codebase, which is pretty much *entirely* C++.

`bindgen` supports two ways of using it: as a command line tool, and as a part of a `build.rs` script. The latter is the recommended path, and it gives you a great deal of control over exactly how you use it. In particular, it lets you account for architecture-specific bits dynamically—which is often important for cross-platform Rust code which is interacting with cross-platform C or C++ code! If you follow that recommendation, you don’t need separate binding files for every target you build against. However, your consumers *will* need a copy of the clang compiler to build your code in that case. Happily, it’s fairly easy to get an up-to-date version of clang on every major platform, including for multiple different Linux distros.

As with build-file dependencies in general, you’ll put `bindgen` in your `[build-dependencies]` section of your `Cargo.toml` file. Then you need to create an *entry point* for the library to do its work: a single `.h` header file which uses the `#include` syntax to pull in every item declaration you need bindings for, by including *other* `.h` header files from the project you’re working with. This file has one other purpose, but we’ll come back to it in a minute. Once you have included all your requisite dependencies, you’ll go into your `build.rs` file and add a `use bindgen;` statement. Then the simplest thing you can do with its exported `Bindgen` type is create a builder and call its `header` method with the path to that `.h` file you created as its argument, and then call its `.generate` method. This will do the work of attempting to parse that header file and all the files *it* includes, and to generate a data structure which can be written as Rust type definitions of the sort we talked through in detail in episodes 029 and 031. You can write that out using the `.write_to_file` method on the generated bindings item, also just passing it a standard file path.

### Customizing bindgen

There are a number of ways we can customize the behavior beyond the defaults, though, which is helpful for situations where the defaults aren’t quite what you need.

#### Customizing bindgen: enums

You can map C/C++ enums into Rust in a variety of different ways:

-   The first is as a set of constants—optionally namespaced into a module—with each Rust constant having the integer value corresponding to the enum literal value on the C side

-   The second is as Rust enums, with guarantees that the discriminants match across the languages. This sounds like what you always want, right? But it’s only what you always want if you’re in control of the C side, because otherwise you can cause undefined behavior with it! The docs link to an explanation of *why*; the point is that, as always with FFI, things are more complicated than they might seem at first.

-   The third is as bitfields, a densely packed layout designed to save space and deal with byte alignment issues—the kinds of concerns that come up when you’re dealing with registers on embedded systems, or sometimes when dealing with message protocols

#### Customizing bindgen: regular types

You can also extensively customize how bindgen handles different types.

For one thing, you can set up a whitelist or a blacklist to determine which types get exposed in the first place. It may well be that you only want to pull in a small subset of the items defined across a bunch of different header files you’re including, but the C side doesn’t really give you that kind of control. When you `#include` a file, it’s literally just dumping the contents of that file in as a string. (I have… stories… about this behavior; if you ever happen to see me at a conference or a meetup ask me and I will happily regale you with the horrors I have seen.) You can use the `bindgen::Builder` whitelist family of methods—`whitelist_type`, `whitelist_function`, and `whitelist_var`—to tell bindgen to allow *only* a subset of items into the generated Rust definitions.

You can similarly blacklist *types* from appearing with the `blacklist_type` function. However, this is only for when you need to provide your own handwritten definition of the type, because it’ll still show up in *other* functions and types, and so you have to provide a definition for the type or your crate won’t compile! In these cases, your best bet is telling bindgen to generate a type that is opaque to Rust—the inverse of the opaque type scenario I talked it great detail in e031. Here, you use the `bindgen::Builder`’s `opaque_type` helper to make it generate a type for which Rust only knows the size and alignment.

You can also replace one C or C++ type with a different C or C++ type entirely entirely—one that bindgen can do the right thing with, when the original is too complicated for bindgen to get right. Servo has to do this at times with C++ types, but I’m hard-pressed to imagine it ever coming up in plain-old C code. (Of course, I could be failing to think of a weird edge case: C has a few of those!)

Finally, for our purposes, you can customize what traits do and don’t get derived in *great* detail. That means you can opt out of `Copy` and `Clone`—which bindgen *tries* to do by default—or into other traits like `Debug` or `Default` or `Hash` or `Eq`, all using other methods off of `bindgen::Builder`.

Now, I’ve covered this at a high level, but there are *many* more settings you can tweak and customize along the way. There are two further resources you’ll find very helpful in digging further into `bindgen`: [the official guide][bindgen guide], and the [API docs][bindgen API docs]. Give them a read (and check out the very simple example in the show notes!).

[bindgen guide]: https://rust-lang.github.io/rust-bindgen/
[bindgen API docs]: https://docs.rs/bindgen

## [`cbindgen`][cbindgen source]

So that does it for `bindgen`, but what about going the other direction—generating C types from Rust, say, to be consumed by Swift? For that, we’ll use `cbindgen`.

`cbindgen` is *not* an official Rust tool, but that doesn’t mean you shouldn’t use it. Its design mirrors that of `bindgen`, so at a high level the *workflow* is the same as with `bindgen`, except that we’re going the other direction. `cbindgen` intentionally mirrors the API of `bindgen`. You can use it either from the command line or from a `build.rs` build script, and its API mirrors `bindgen`’s quite closely. You pull in the library, you create a `Builder`, you pass it a path to a crate directory, you call `generate` on it, and you write the fill out—but this time, instead of writing a Rust file, you’re writing out a `.h` header file.

It’s worth noting, however, that `cbindgen` has some important limitations and gotachs. Specifically (and here I’m cribbing from [a blog post by one of the main authors of the crate][future-directions]:

[future-directions]: https://blog.eqrion.net/future-directions-for-cbindgen/

- It has a hard time dealing with path resolution, so if you have multiple item which would resolve to the same external name, it’ll fall over

- It doesn’t understand privacy modifiers, and between that and its not understanding paths, it doesn’t actually know whether something should be exported from your crate or not. That’s a big deal! It *guesses*: if an item is `pub`, it thinks it’s exported. As we talked about in detail in e030, though, that’s not correct.

- Because of where it interacts with Rust code—i.e. at the level of the uncompiled syntax—it doesn’t understand macros, which are a form of code generation. There’s an option to work around this using a Rust compiler flat… but it’s not guaranteed to work properly with macro hygiene, so it’s not stable.

- It similarly doesn’t always know what to do with `#[cfg]` attributes. It tries! …but it can’t always do the right thing, where by “the right thing” I mean “the thing you want” or “the thing you find unsurprising.”

The net of all of those is that basically the maintainers are confronted with the problem of trying to reimplement non-trivial subsets of `rustc`! So cbindgen *does* work today, and you can use it in exactly the ways I talked through above, but you should be aware of those caveats… and you should keep your eyes on a *follow-on* project, [`rust-ffi`], which aims to address those with a more robust architecture that splits apart some of the concerns and runs as a Rust compiler plugin for the bits that need to understand Rust itself correctly. (I’m not sure how alive that project is: it was a proof of concept, but it seems promising; hopefully it gets some forward motion soon!)

[`rust-ffi`]: https://github.com/eqrion/rust-ffi

## Binding libraries for other languages

The other thing worth calling out here is that there are dedicated libraries for providing Rust bindings for most of the major scripting languages. I’ll name them here, and link them in the show notes—in many cases, those are *the* place you should start if you’re wanting to augment code written one of those languages with a native extension in Rust.

- Python has [PyO3](https://github.com/PyO3/PyO3)
- Elixir and Erlang have [Rustler](https://github.com/rusterlium/rustler)
- JavaScript has [Neon](https://neon-bindings.com)
- Ruby has [Helix](https://github.com/tildeio/helix)

Those are in various degrees of maturity and stability, but all are at least *usable* and indeed all of them are actually being used in production. There was [a great write-up from the folks at Discord][discord-elixir-rust] just today (as I write and record) about how they’re using Rustler to speed up a critical part of their Elixir back end (linked in the show notes, of course!).

[discord-elixir-rust]: https://blog.discordapp.com/using-rust-to-scale-elixir-for-11-million-concurrent-users-c6f19fc029d3

## Testing

The last thing to say is that *you should test your bindings*. It’s one thing to look at code and be pretty sure you wrote the right things. It’s something else entirely to have tests in place that make *sure* you do. Use Rust’s built-in testing infrastructure to check on a couple things:

1.  Do a simple “is this just basically right?” test. Does invoking each function you’re importing via FFI give you the right results in the happy path? Testing *more* than the happy path is probably good, but at a *minimum* you want to check this part.

2.  Do you end up with any panics because you have invalid data flowing across the FFI boundary? To manage this you may need to write some unsafe code; but it’s a good way to make sure that your invariant-checking pieces are correct. Assert that things *should* panic when given bad data, for example, using the `#[should_panic]` attribute on a test function. Or get more fine-grained using the `std::panic::catch_unwind` function to get a `Result` with the error and dig into its details.

I expect this is a place where some kind of fuzz- or property-based-testing could also be useful… but I’ll freely admit that that’s just speculation, because I haven’t ever actually been able to give those a whirl myself. I’d love to hear if you’ve put those kinds of tools to use in FFI contexts in particular!

## Conclusion

Thanks as always to this month’s $10-or-more sponsors:

- Raph Levien
- Martin Heuschober
- Graham Wihlidal
- Jason Bowen
- Soren Bramer Schmidt
- Daniel Collin
- Peter Tillemans
- Oluseyi Sonaiya
- Behnam Esfahbod
- Nicolas Pochet
- Jonathan Knapp
- Dominic Cooney
- Cristian Paul
- Dan Abrams
- Nathan Sculli
- James Hagans II
- Chip
- Anthony Deschamps
- Andrew Dirksen
- Embark Studios
- Paul Naranja
- Ryan Osial
- Benjamin Manns
- Michael Mc Donnell
- Daniel Mason
- Bryan Stitt
- Alexander Payne
- Nick Gideo
- David Carroll
- Daniel Bornkessel (April only)
- John Rudnick
- Rob Tsuk
- Nick Stevens
- Arun Kulshreshtha
- Adam Green
- Jako Danar
- Jeff May
- Zach Peters
- Scott Moeller
- Evan Stoll
- Joseph Schrag
- Matt Rudder
- Ramon Buckland
- Johan Andersson
- Brian McCallister
- Jerome Froelich
- Ola Fadeyi

You can find show notes for this episode and every other at <newrustacean.com>—with scripts, code samples, and a number of interview transcripts.

Please recommend the show to others if you like it, whether in person, via your podcast directory, or in various media online! You can contact me at @chriskrycho or @newrustacean on Twitter, or by sending men an email at hello@newrustacean.com.

Until next time, happy coding!

================================================
FILE: docs/cysk/serde.md
================================================
# Crates You Should Know: Serde

Hello, I’m Chris Krycho, and this is New Rustacean: a show about the Rust programming language and the people who use it. This is **Crates You Should Know: Serde.**

## Intro

It’s actually kind of amazing to me that we’re two and a half years into the show before I finally get around to talking about Serde. It’s been mentioned on the show repeatedly, and it’s one of the absolute core building blocks of the Rust ecosystem, and it’s frankly just a really impressive piece of software in its own right – inside the Rust ecosystem *or* outside. So now we’re going to do a solid dive into the library’s purpose, approach, and (at a high level) APIs!

## Serde

Serde is a library for *serialization* and *deserialization* of data – data of all sorts. The name is just a mashup of the first syllable of *serialization* and *deserialization* - ‘s’ ‘e’ ‘r’ from serialization and ‘d’ ‘e’ from deserialization.

One thing that distinguishes Serde from e.g. the JSON-to-data-structure implementation in your other favorite language is that *most* of the time, the serialization and deserialization that happens, and really the data layer transformations of any sort (including for ORMs) are done at *runtime*, by mapping over the supplied data structure. Serde and Rust obviously still have to do some work at runtime, but that work is a lot narrower in scope, because they use Rust’s types and Serde’s traits to avoid any runtime attribute tagging or reflection. As is often the case with this kind of trait-driven programming, the compiler can often optimize it down to the same kind of performance you’d get by hand-writing a serializer... but as we’ll cover in a moment, you pretty much never have to hand-write serializers!

The current list of supported formats for serialization and deserialization is pretty long! Among others, you can serialize and/or deserialize to JSON, YAML, MessagePack, TOML, Pickle (from Python), URL, and XML. (And there are more!)

### Using Serde as a consumer

Serde, as you might expect, leans heavily on a few core traits: `Serialize` and `Deserialize`. And, happily, these are traits you’ll only *very* rarely need to implement yourself. Courtesy of Rust’s support for *custom derives*—which Sean Griffin and I talked about a bit in [our discussion of Diesel 1.0](https://www.newrustacean.com/show_notes/interview/diesel_1_0/part_1/index.html "Diesel 1.0, Part 1"). For Serde, you can take *essentially* any data type you can define in Rust and simply use the `derive` attribute by writing `#[derive(Serialize, Deserializer)]` in front of any type you define. In a few rare occasions, you’ll need to write the implementations yourself (and the really excellent docs have you covered in that case), but usually you’ll just derive these traits automatically.

To make that work, you’ll need to make a couple tweaks to your project besides adding Serde itself to the dependency list.

1. Add `serde_derive` to your Cargo.toml. It’s an *optional* dependency of Serde—and it’s probably safe to say it’s *usually* installed alongside it! But if you happen to be in a scenario where you’re not going to be using the derives, you don’t have to install it.

2. Add the dependencies for the target format you want to use—again, Serde breaks out its support for each format into its own crate. This keeps your build size down: there’s no reason to include, say, `serde_yaml` if you’re only targeting JSON.

3. In your `main.rs` or `lib.rs` file—depending on whether you’re building an application or a library—add the top-level attribute to include the custom derive macro: `#[macro_use] extern crate serde_derive`.

And that’s it! You can now derive `Serialize`, `Deserialize`, or both on any `struct` or `enum` you need to serializer or deserialize.

Once you’ve set up a data type with the relevant attributes, you can serialize and deserialize them by using the main functions a Serde target library supplies. The most common ones are:

- `ser::to_string`: the function for serializing a given Rust item into a string of a given format
- `de::from_string`: the function for deserializing a string of a given format into a Rust item

For other target formats, you’d see different names—if the Serde library you were using targeted binary buffers, for example, it would be `ser::to_bytes` and `de::from_bytes`.

Once you have the basic configuration all set up, you can start *using* those functions with your types.

You can also further customize the way a data type is serialized and deserialized by using other *attributes*. Serde has attributes for customizing the container (the struct or enum itself); customizing enum variants; and customizing struct fields. For example, you can rename a struct field or enum variant. These kinds of things might come in handy when you’re translating between the expectations from different data layers in other languages, for example. In JavaScript, it’s normal for payloads to be formatted in `camelCase`—lowercase first letter, capitalized first letter of all words following in a name—but since it’s normal for Rust fields to be `snake_case`—all lowercase, separating words in a name with underscores—you can use Serde’s `rename_all` container attribute. You can also skip fields and variants entirely, or define custom functions to serialize and deserialize them.

In short, Serde has *really* good defaults but also the flexibility to do most of what you need via attributes if the defaults don’t match your specific scenario... and the ability to just write your own specific `Serialize` and `Deserialize` implementation yourself if even *those* don’t get you far enough.

### Using Serde as a producer

The other use case for Serde is creating support for a new source for deserialization and target for serialization. As I noted earlier, Serde already supports a wide array of target formats. However, there are cases where you might need to write your own format for a given data representation type, or for a given protocol for transmission. In that case, you can implement your own serializer and deserializer plugin library, just like the existing libraries like `serde_json`.

Serde—as its docs emphasize!—is not a *parsing* library. Its functionality is *specifically* for converting data to or from a given, *already-parsed* format and Rust data structures. So, for example, `serde_json` [parses the JSON itself](https://github.com/serde-rs/json/blob/master/src/de.rs#L110), iterating through a buffer of bytes, and likewise actually [generates the JSON itself](https://github.com/serde-rs/json/blob/master/src/ser.rs#L72) (including supplying a variety of options for how you print the JSON).

The API you have to implement is not *large*, and it is *well-documented*. For any given data type, you have to implement the `Serialize` and/or `Deserialize` traits (depending on what you’re doing), and conventionally you should also supply `to_` and/or `from_` functions, like `to_str` and `from_str` for serializing and deserializing `&str` string buffers, or `to_bytes` and `from_bytes` for serializing and deserializing directly to `&[u8]` bytes buffers.

I’m not going to try to talk through everything involved in writing your own implementation; that would quickly involve far too much trying to describe code aloud, and I do enough of that in this podcast! Instead, if you’re interested in seeing a really quite straightforward and relatively easy to understand example, I recommend blocking out a couple hours and reading through the `serde_json` implementation. You’ll probably learn a lot!

## Outro

So that’s Serde! If you need to serialize or deserialize stuff in Rust… this is where it’s at!

### Sponsors

Thanks, as always, to all of this month's sponsors. Contributors who gave at least $10 included:

- Aaron Turon
- Alexander Payne
- Anthony Deschamps
- Chris Palmer
- Behnam Esfahbod
- Dan Abrams
- Daniel Collin
- David W. Allen
- Hans Fjällemark
- John Rudnick
- Matt Rudder
- Nathan Sculli
- Nick Stevens
- Peter Tillemans
- Olaf Leidinger
- Oluseyi Sonaiya
- Raph Levien
- and Vesa Khailavirta

If you’d like to sponsor the show, you set up ongoing support at patreon.com/newrustacean, or send a one-off at any of a number of other services listed at newrustacean.com. The website also has scripts and code samples for most of the teaching episodes as well as transcripts for many of the interviews, along with full show notes for every episode. You can find the notes for *this* episode at <https://newrustacean.com/show_notes/cysk/serde/>.

If you're enjoying New Rustacean, please help others find it – by telling them about it in person, by sharing it on social media, or by rating and reviewing the show in your favorite podcast directory.

The show is on Twitter @newrustacean, or you can follow me there @chriskrycho. Tweet me with news, topic ideas, etc! You can also respond in the threads on the Rust user forums, Reddit, or Hacker News, or—and this will always be my favorite—just send me an email at hello@newrustacean.com.

Until next time, happy coding!

================================================
FILE: docs/cysk/wasm.md
================================================
# Crates You Should Know: the `wasm-` tools

Hello, I’m Chris Krycho and this is New Rustacean: a show about the Rust programming language and the people who use it. This is Crates You Should Know: the `wasm-` tools.

## `wasm`

### Background

First, a little background on WebAssembly, or “wasm”. I’ve mentioned it in a number of contexts on the show before, but I’ve not dug into the details at all.

WebAssembly is the direct descendant of a research effort called asm.js, which was an attempt to specify a subset of JavaScript that would work as a compile target for C or C++, specifically to allow games to run in web browsers. The aims of and possible uses for WebAssembly are much broader than just games though: it can be used for all sorts of performance-intensive applications, running as a complement to (rather than a replacement for) JavaScript in the browser.

### How it works

So how does that work in a technical sense?

WebAssembly is a binary instruction format for a stack-based virtual machine. Because it’s a low-level binary format, it can in principle run at native speeds – “in principle” because it does depend on the context it’s running in, of course. This low-level format serves a compile target for higher-level languages, where by higher-level I mostly mean “like C++ or Rust” rather than “like Ruby or Elm.”

WebAssembly can be run in all modern web browsers, and it can actually be implemented in existing JavaScript VMs. However, it is not *limited* to running in browsers or JavaScript VMs, and you definitely won’t see native performance if it’s implemented in an existing VM rather than having its own dedicated runtime. And it’s worth reiterating: the browser is just the first and currently-most-popular deployment target. I’ve already seen research on running it as kernel code – and to be clear, I mean as *normal*, Ring 0 kernel code, with neither a browser nor a JavaScript VM anywhere to be seen. There are possibly real long-term benefits to doing exactly that, too, though I’m not going to dig into them today.

But let’s step back and unpack that description a little bit.

- wasm is a *binary instruction format*. This is basically the same as other kinds of assembly languages, which are *instruction formats* as well. It’s a binary format for speed reasons: no parse-the-string-into-the-actual-instructions step required. However, there *is* a human-readable format, which is handy for understanding the output of your compiled code. 

- wasm is designed for a *stack-based virtual machine*. There are a variety of kinds of virtual machines in the world, and most of them you’re like to be familiar with (Java, C♯, Python, Ruby, JavaScript, etc.) have both a stack and a heap, along with garbage collection. The wasm virtual machine model does *not* have a heap, and it does *not* have garbage collection. This has a lot of implications for the programming model, which, again, I’m not going to dig into today. It’s enough for now to know that the constraints exist so you can have them in mind if or when you start actually implementing things in wasm!

It is important that I note that WebAssembly does have an explicit goal of being a viable compile target for languages which *do* have VMs in the future, but also chose initially to target languages with low-level memory models: C, C++, and Rust are the major source languages which target WebAssembly today. There are early experiments happening in other languages, too, but large-scale real-world application of those is probably a year or more away. And we’re here for the Rust side anyway, so let’s talk about how you’d actually go about targeting and using wasm with Rust today. Because you can, and it’s actually not all that hard!

## Using wasm

The first thing you should do is add the target, so you can compile to WebAssembly *at all*: run `rustup target add wasm32-unknown-unknown --toolchain nightly`. The name of the target triple tells you that you don’t know the architecture or the OS it’s running against; you know only the instruction set to use (in this case, `wasm` instead of say `i686` or `x86_64` or some such).

You can then manually run the compiler with the `wasm32-unknown-unknown` target specified, and you’ll see output in `target/wasm32-unknown-unknown`—with a `.wasm` extension instead of the usual binary. Then you’d need to pull that into your existing JavaScript environment with the right host bindings. In other words, you’ll need to basically write some JavaScript by hand to get everything doing exactly what we want and need to *use* this WebAssembly code.

So, it’s nice that we can actually build wasm! But clearly this isn’t especially useful output. We need some help from the crates ecosystem to be *productive* with it. And that takes us into the actual *crates you should know* for dealing with wasm.

### `wasm-bindgen`

The first crate you should know about is `wasm-bindgen`. If you’ve heard of the `bindgen` tool, this is like that, but for `wasm`. If you *haven’t* heard of the `bindgen` tool, it’s pretty much the C and C++ equivalent of what I’m about to describe for JavaScript.

WebAssembly itself only supports a very limited set of types: basically, short and long integers, and short and long floating points. The other “types” in the language are just functions or particular layouts of these kinds of types. But of course, in both Rust and JavaScript, we are essentially *always* dealing with types much more complicated than just integers or floats. `wasm-bindgen` does the work of generating mappings between WebAssembly and JavaScript that let you do things like pass a Rust string to JavaScript or deal with JavaScript exceptions in Rust. Without that, you’d need to write a ton of manual glue code—specifically, manual glue code in JavaScript that uses integers for pointer arithmetic and for indexes into reference types. That is not a lot of fun.

Instead of writing all of that code by hand—an error-prone process if ever there was one—you use `wasm-bindgen`:

1. Add it to your crate as a dependency.
2. Install the `wasm-bindgen-cli` tool.
3. Annotate both any `extern` JS items you want to use and also any Rust items you want to export with the `#[wasm_bindgen]` attribute. (You’ll also need to enable the `proc_macro`, `wasm_custom_section`, and `wasm_import_module` features at the top of your crate for this to work. That means a nightly version of the compiler: all of this stuff will eventually stabilize but right now we’re just figuring it all out!)
4. Compile your crate with the `wasm32-unknown-unknown` target, again using the nightly compiler. This will generate `target/wasm32-unknown-unknown/the_name_of_your_crate.wasm`.
5. Run `wasm-bindgen` on that output; you can specify the directory where you want the output. Now you’ll have a `the_name_of_your_crate.js` wherever you specified.



### `wasm-pack`

So it’s great that we can compile down to WebAssembly, but we’re still left with a pretty important question. How do we get that to the environment we’re consuming it from – *especially* in a way that means other consumers don’t have to worry about the fact that it’s Rust? After all, one of the things we want to be able to do is ship WebAssembly so that *anyone* can use it. If we’ve written some super speedy Rust/WebAssembly implementation that we want JavaScript consumers to be able to use easily, we want to make sure they *don’t* need to install Rust and understand *its* ecosystem. Wasm should just be wasm from their point of view.

Enter the `wasm-pack` tool! It’s a command line tool that actually abstracts right over `wasm-bindgen` and all the invocations we just talked through and builds a package that’s ready to ship to npm *for you*.

I talked through `wasm-bindgen` first because I think it’s important to understand what’s going on under the hood, and because you still need to do everything but the last step of running `wasm-bindgen` directly on your code. You replace that step by running `cargo install wasm-pack` and then running `wasm-pack` in the root of your crate, or somewhere else with the path to your crate as an argument. Then it runs `wasm-bindgen` for you on your compiled artifacts.

The result will be a compiled directory called `pkg`, with a `.wasm` file and a `.js` file which consumes it, alongside a `package.json` all set up and ready to ship to the npm registry. You can publish that to npm as long as you have Node and either the `npm` or `yarn` command line client installed! Then any consumer which understands WebAssembly—Node 8 or later, as well as an increasing number of bundlers like Webpack and all evergreen browsers—can run your WebAssembly!

## Closing

So that’s where things stand *today*. As I noted at the outset, this area of the ecosystem is moving incredibly quickly right now, so you should keep your eye on the updates from the wasm working group and watch these repositories. As neat as things already are here, they’re going to be a lot better by the end of the year!

Thanks to everyone who sponsors the show. This month’s $10-or-more sponsors included:

- Aaron Turon
- Alexander Payne
- Anthony Deschamps
- Chris Palmer
- Behnam Esfahbod
- Dan Abrams
- Daniel Collin
- David W. Allen
- Derek Buckley
- Hans Fjällemark
- John Rudnick
- Matt Rudder
- Marshall Clyburn
- Nathan Sculli
- Nick Stevens
- Peter Tillemans
- Paul Naranja
- Olaf Leidinger
- Oluseyi Sonaiya
- Ramon Buckland
- Raph Levien
- Vesa Khailavirta
- and Zachary Snyder

If you’d like to sponsor the show, you set up ongoing support at patreon.com/newrustacean, or send a one-off at any of a number of other services listed at newrustacean.com. The website also has scripts and code samples for most of the teaching episodes as well as transcripts for many of the interviews, along with full show notes for every episode. You can find the notes for _this_ episode at <newrustacean.com/show_notes/news/rust_1_26>.

If you're enjoying New Rustacean, please help others find it – by telling them about it in person, by sharing it on social media, or by rating and reviewing the show in your favorite podcast directory.

The show is on Twitter @newrustacean, or you can follow me there @chriskrycho. Tweet me with news, topic ideas, etc! You can also respond in the threads on the Rust user forums, Reddit, or Hacker News, or—and this will always be my favorite—just send me an email at hello@newrustacean.com.

Until next time, happy coding!

================================================
FILE: docs/cysk-1.md
================================================
# `quick-xml`

## Intro

Hello, I'm Chris Krycho, and this is the New Rustacean podcast---a 15--20 minute show about learning the Rust programming language. This is *Crates You Should Know: `quick-xml`*.

## The crate

As part of my work on my Lightning static site generator, I realized I needed to be able to quickly parse XML for syntax highlighting: I want to be able to do that at build time, rather than running JavaScript on the page when a user sees it. (I'll talk about the crate I'm using to do *that* in a future crates-you-should-know episode!)

The challenge I faced was taking a bunch of well-formed HTML and reliably identifying every language-tagged code block, extracting it, syntax-highlighting it, and then replacing it in the original content. As you know if you've ever tried to do this kind of thing in HTML or XML, you *might* be able to get away with handling this with a regular expression *most* of the time, but eventually that approach will blow up in your face. This is a job for an XML parser and writer! (HTML is roughly a subset of XML. It's not strictly a subset, but usually you'll find that XML parsers can also handle HTML.)

So I went looking for an XML crate! There are a number of XML-processing crates in the Rust ecosystem presently, and I read through the docs for each of them and played with a couple of them. I landed on `quick-xml`: it's fast, it has a fairly ergonomic API, and it supports XML namespaces. (If you're wondering, I don't need namespaces for *this* project, but lightning is not just about static site generation for me; it's also a proving ground for a bunch of *other* ideas I'm working on.)

So let's talk about that API a little! The crate is pretty straightforward. At the top level, it exposes four structs and one enum: `Element`, `XmlDecl`, `XmlReader`, and `XmlWriter`. There are also some types for handling attributes, errors, and namespace management, off in their own dedicated modules. The `Element` type is the workhorse of the struct types, and the reader and writer types and methods use it heavily in conjunction with the `Event` enum. The `Event`s are things like start tags, end tags, comments, text, and so on---each variant contains an `Element`. `XmlDecl` is just a wrapper around an `Element` with some extra functions for handling the specific attributes you care about from XML declarations specifically. The `XmlReader` and `XmlWriter` types do exactly what they say: give you an interface for reading and writing XML.

Now, `quick-xml` is implemented as a "pull parser," meaning that instead of preemptively handing you a fully parsed tree or something along those lines, it works as an iterator, which in turn allows you to step through it as you will. There are upsides and downsides to this approach. The biggest downside is that if you want a tree structure, you have to build it yourself. The biggest upside is that if you *don't* need a tree structure, you don't pay the cost of having it anyway. That's particular interesting for memory usage reasons. I'm not *overly* worried about that in the case of Lightning---it should be a memory hog---but I also take the view that if you *can* do things in a more lightweight fashion, it's often good to do so. That's a big part of what attracts me to Rust, in fact: the ability to do things that are fast and lightweight on a user's machine. In any case, the net result of making `quick-xml` be a pull parser is that parsing and writing some XML with the crate was pretty easy.

Here's how it works: The `XmlReader` takes a buffer of content and produces a stream of `Event`s, and the `XmlWriter` takes `Event`s and writes them to anything which implements the `std::io:Write` trait. In practice, that means that you can just treat the reader type like a standard iterable---because it *is* a standard iterable. When I talked about traits back in episode 9, I hinted at this kind of thing, with `std::iter::Iterator` specifically. Here's where all that power comes to bear: you can use the exact same set of iteration methods on an `XmlReader` as you can the built-in `Vec` type. Then, to do whatever transformations you need to do, you can just match on the `Event` type.

In Lightning, that translated to pulling the events out of the `XmlReader` instance, inspecting them to see if they were important for syntax highlighting (and doing the syntax highlighting if so), and then pushing them into an `XmlWriter` instance. To do this, I built a little state machine which determined what to do from each event coming out of the reader. If the event wasn't of interest for syntax highlighting, I'd just push it directly into an `XmlWriter`. If the events matched the magical pair of tags---`pre` and `code` with a language class attached---I could grab the *text* element, parse it, and hand it back, building a new `Element` out of the highlighted code. Then I could push *that* into the `XmlWriter`. And when I'd finished processing the whole thing, I could just convert it back into a string for further processing or write it to a file.

I've used very powerful XML parsing toolchains before; in particular I made heavy use out of the Python lxml tool a couple years ago when generating the HTML for HolyBible.com. Certainly if you wanted to do the kinds of things that gives you, you'd need to build on top of `quick-xml`. But, and this is important, you *can*. It's a great little library, with a very well-thought-out API. If you're working with XML or HTML, this is well worth becoming acquainted with. And if you haven't used a pull parser before, this is a great place to learn it. *I* hadn't ever done so, and I learned a ton from the experience. In fact, sometime in the next year or so, I end up implementing a parser in Rust, it will almost certainly be a pull parser. More on that when it happens.

## Closing

In short, if you're doing things with XML, `quick-xml` is a great bet---and it's also open to contributions, so if you find something it doesn't do well, you should file an issue or open a PR!

### Sponsors

Thanks to 

- Chris Palmer
- Matt Rudder
- Ben Whitley
- Peter Tillemans
- Philipp Keller
- Steven Murawski
- Raph Levien
- and Vesa Khailavirta

for sponsoring the show this month! You can see a full list of sponsors in the show notes.

If you're interested in sponsoring the show, you can set up recurring contributions at Patreon.com/newrustacean, or give a one-off contribution at any of a number of other services listed on the show website.

### Follow

You can also find links to the docs, repository, and crate page for `quick-xml` at NewRustacean.com. You can follow the show on Twitter @newrustacean, or follow me there @chriskrycho. If you enjoy the show, please tell somebody about it! You can also help others discover the show by rating and reviewing it on iTunes, recommending it in other podcast directories, or sharing it around on whatever social media you use.

I hope you've enjoyed this first crates-you-should-know episode, and I hope to put out at least one of these a month. I have a handful on my list, but I'd love to hear suggestions for more. You can shoot those my way, or respond more generally, in the threads for the episode on the Rust user forum or Hacker News, or by emailing me at hello@newrustacean.com.

Until next time, happy coding!


================================================
FILE: docs/cysk-2.md
================================================
# `clap`

Hello, I'm Chris Krycho, and this is the New Rustacean podcast---a 15--20 show about learning the Rust programming language. This is *Crates You Should Know: `clap`*.

## The crate

### Background

When I started building Lightning, I knew that part of what I would need would be a really great command line interface, and that it would need to be robust enough to handle not just generating a site but also rapidly creating posts, pages, etc. In my previous setup, I'd actually created a custom tool to do all of those things, and other site generators (like Jekyll) include this functionality.

In Rust, you have three major options for handling this kind of thing.

1. You can just directly access the arguments handed to the process, using the `std::env::args` function, which hands you back an iterable struct of the arguments.
2. You can use `docopt`, a Rust implementation of the docopt command line interface language (from Python), by the same guy who built the Rust regex library and the `ripgrep` Rust grep tool. It's a great tool, and I might come back to it at some point in the future.
3. You can use `clap`: a *command-line-argument-parser* (where the name is an acronym from the description: c-l-a-p). This is our focus for today, and it's *very* different from `docopt` in a lot of ways.

I don't recommend using the args directly unless perhaps for a very small toy bit of code. Using `docopt` or `clap` is a much better choice: both give you help messages essentially for "free" once you've done the work of setting up the structure. Both can also give you basic shell completion for bash, and clap can generate completions for zsh, fish, and PowerShell as well. You also get a lot of mileage out of community-tested and -embraced tools.

One other qualification before I dive into talking about `clap`: I picked it not because I think it's *better* than `docopt`, but because it was the one that meshed best with how I like to approach this problem, and so was the one I started using with Lightning.

### The API

The usage pattern for `clap` is straightforward: you define a configuration it should use, and at runtime it parses the args wherever in your program flow you take that configured struct and run the handy `get_matches()` method. Usually, that's right at startup, of course. `get_matches()` takes the arguments passed to the program and converts them into a data structure you can readily convert into whatever *internal* data structures you need for running your program. There are three major ways to configure `clap`.

First, you can use a normal (and quite elegant) Rust API to build it directly inline. This is the tack I took initially with Lightning, because it was the most familiar to me after having used Python's `argparse` library in the past. And in fact, in many ways `clap` feels like a spiritual successor to that library, so if you've used it and like it, you'll appreciate `clap` a lot---not least for the ways it *improves* on that earlier model. In this mode, you get to use the *builder* pattern, a concept I may have mentioned before but which I now realize deserves its own full episode.

From a user's perspective, though, you just create an instance of the type by writing `clap::App::new()` and then supplying further calls on that instance. The methods are set up so that you can just chain the calls one after another---you don't have to set up any intermediate variables. Other methods include things like `arg`, `subcommand`, `version`, `author`, `about`, and so on. There are also the `Arg` and `Subcommand` structs, along with several other helper structs. `Subcommand` instances are just more `App` instances, but attached to a parent `App`, so they have all the same customizability and capabilities as the main `App`. `Arg` instances let you specify the name (and a short variant) of the argument, whether it's optional or required, whether it's positional, help text for the argument, even things like whether the argument is required *unless some other condition* holds. They're basically as configurable as you could want. You can also group `Arg`s with `ArgGroup`s.

Second, you can write a YAML file specifying the various options and their relationships. These give you a *subset* of the capabilities you have in the full library API. Mind: it's an extremely full-featured subset. Though I started off with the Rust API for Lightning, I ended up switching over to the YAML version because it does everything *I* need. (Note that the YAML version is behind a feature option in Cargo---another thing I'm pretty sure I haven't covered, but which should probably get its own short episode.) I'll link both my Lightning code and, more importantly, the example in the `clap` codebase, which covers *all* the features the YAML variant supports.

Third, you can use a macro, `clap_app!`, which gives you a handy short-hand syntax which sits somewhere between the YAML and the library API in terms of ergonomics. It's definitely briefer than the full API to use, and looks closer to the kinds of things you'd write in the YAML form. It will, by dint of being a macro, be much more difficult to see where you got things wrong if you mess up, compared to the full library API.

I should also add here that there are a bunch of other convenience macros you can use to get information about the crate at compile-time even in the standard API approach---tools like `crate_authors!`, `crate_description!`, and `crate_name!`, which give you, well, the crate authors, description, and name respectively. Those let you keep the name, description, and author fields of your help output in sync with what's in your crate automatically. Don't-repeat-yourself and all that jazz!

One other thing I want to say about `clap`: its documentation is simply superb. The index of the automatically generated docs includes a lengthy example of how to use the library in each of the three ways mentioned above. There are also multiple examples of using the app in the `examples` directory in the repository, which I believe combine to cover every feature the library has. I had a question at one point about something I didn't perfectly understand from the documentation, so I went and looked and exactly that case was covered by one of the examples; it solved my question entirely. That was a *fabulous* experience, and I wish more libraries did it. It's a big inspiration for me, in fact: I won't be calling Lightning "1.0" until I have that same degree of coverage in docs.

There's even a work-in-progress online *book* on creating command-line applications, using clap. Note: when I say "work-in-progress" I mean it: the site itself describes the material as "pre-alpha" and many of the chapters don't yet exist. Still: there's a lot of great material here.

## Closing

In short, `clap` is a *fantastic* utility library for building command line tools, and it's well worth your time! It's also actively developed, in the open on GitHub, so you can and should contribute if you find a gap or a bug!

### Sponsors

Thanks to 

- Chris Palmer
- Christopher Giffard
- Matt Rudder
- Ben Whitley
- Peter Tillemans
- Philipp Keller
- Steven Murawski
- Raph Levien
- and Vesa Khailavirta

for sponsoring the show this month! You can see a full list of sponsors in the show notes.

If you're interested in sponsoring the show, you can set up recurring contributions at Patreon.com/newrustacean, or give a one-off contribution at any of a number of other services listed on the show website, or if you're a company interested in advertising to developers, please email me!

### Info

You can also find links to the docs, repository, and crate page for `clap` at NewRustacean.com. You can follow the show on Twitter @newrustacean, or follow me there @chriskrycho. If you enjoy the show, please tell somebody about it! You can also help others discover the show by rating and reviewing it on iTunes, recommending it in other podcast directories, or sharing it around on whatever social media you use.

I'd love to hear your feedback, as well as suggestions for topics, interviewees, and so on, in the threads for the episode on the Rust user forum or Hacker News. I also love getting email---you can send me a note at hello@newrustacean.com.

Until next time, happy coding!


================================================
FILE: docs/cysk-3.md
================================================
# RLS

Hello, I'm Chris Krycho, and this is the New Rustacean podcast---a 15--20 show about learning the Rust programming language. This is *Crates You Should Know: R.L.S.*

## The crate

In terms of *exciting* things happening in the Rust ecosystem right now, there are a lot we could mention – not least crates like Diesel and Rocket which are especially appealing to me as a web developer. And we'll get around to a bunch of those eventually. But today, the crate I want to talk about is one you're not very likely *ever* to use by adding it to your `crates.toml` file, but which by the end of 2018 you will probably be using in every single Rust project nonetheless: the Rust Language Service (or RLS for short).

The RLS is Rust's answer to the question: _How do we make it easy for everyone to have a great integrated development environment for Rust?_ For the most part, IDEs for other languages have always had to implement their own smarts about the language. So, for example, the JetBrains family of IDEs – tools like IntelliJ IDEA, WebStorm, PyCharm, RubyMine, CLion, etc. – all use some common underlying infrastructure for things like code analysis, completion, refactorings, and so on. That infrastructure is shared among JetBrains products, but they have to implement everything specific to Java, Scala, JavaScript, Python, PHP, C++, etc. for themselves. And if you open up Eclipse, it has its own infrastructure for code completion, refactoring, etc. Lighter-weight GUI text editors like Atom, Visual Studio Code, and Sublime Text have *their* own code completion And if you're running vim or emacs, they have their own tools, too. Every editor has to reimplement the same things.

But not so with Rust. The Rust Language Service means every editor which supports the open-source *Language Service Protocol*, can have completion, type inference, type checking, and (soon-ish) automated refactoring and code formatting tools for Rust… basically for free.

### Background: LSP

A few years ago, as part of its work on Visual Studio Code and the plugins it developed for supporting cross-platform .NET work in C#, Microsoft developed the *Language Service Protocol*. The protocol defines a standard way for a *client* (normally, though not *necessarily*) an editor of some sort to talk to a *server* (e.g. a compiler or other language analysis tool). The protocol defines the kinds of messages, the format they go in, etc. in a straightforward JSON format. And because it's such a straightforward format, you can talk to a LSP server via simple command-line call if you want – which makes it fairly easy to test at a basic level, and even (in principle) lets you do interesting things like build Read-Evaluate-Print-Loops (REPLs) with it. (There's nothing like that on the radar for Rust, at least to the best of my knowledge, but it's certainly interesting!)

I use the TypeScript Language Service every day at work, and it means that editors like VS Code, Sublime, and Atom all have pretty similar feature sets and behavior for doing TypeScript development, despite being very different editors in many other ways. It brings the experience of writing TypeScript in those languages – with community-supported plugins, in the cases of Atom and Sublime – very nearly to parity to the professionally developed and supported features of JetBrains IDEs, and even the official Microsoft support VS Code plugin... is just a TypeScript language server client.

### Status

If you listened to the second news episode, you'll recall that I mentioned this was coming down the line and was in a very early and very rough "alpha" stage back in late 2016. As of this week (in mid-April, 2017), it has graduated from the "early alpha" stage it was in then to "beta": you
Download .txt
gitextract_cw5hn_qg/

├── .editorconfig
├── .gitignore
├── .travis.yml
├── Cargo.toml
├── LICENSE.md
├── Makefile
├── README.md
├── build.rs
├── docs/
│   ├── bonus/
│   │   ├── 10-script.md
│   │   ├── 13-silly-mistakes.md
│   │   ├── 14-my-workflow.md
│   │   ├── burnout-script.md
│   │   └── translating-between-languages-script.md
│   ├── bonus-2-script.md
│   ├── bonus-3-script.md
│   ├── bonus-4-script.md
│   ├── bonus-5-script.md
│   ├── bonus-6-script.md
│   ├── bonus-7-script.md
│   ├── bonus-8-script.md
│   ├── bonus-9-script.md
│   ├── cysk/
│   │   ├── bindgen-cbindgen-script.md
│   │   ├── serde.md
│   │   └── wasm.md
│   ├── cysk-1.md
│   ├── cysk-2.md
│   ├── cysk-3.md
│   ├── cysk-rayon.md
│   ├── cysk-rocket.md
│   ├── e000-script.md
│   ├── e001-script.md
│   ├── e002-script.md
│   ├── e003-script.md
│   ├── e004-script.md
│   ├── e005-script.md
│   ├── e006-script.md
│   ├── e007-script.md
│   ├── e008-script.md
│   ├── e009-script.md
│   ├── e010-script.md
│   ├── e011-script.md
│   ├── e011-transcript.md
│   ├── e012-script.md
│   ├── e014-script.md
│   ├── e015-script.md
│   ├── e016-script.md
│   ├── e017-script.md
│   ├── e018-script.md
│   ├── e019-script.md
│   ├── e020-script.md
│   ├── e021-script.md
│   ├── e022-script.md
│   ├── e023-script.md
│   ├── e024-script.md
│   ├── e025-script.md
│   ├── e026-script.md
│   ├── e027-script.md
│   ├── e028-script.md
│   ├── e029-script.md
│   ├── e030-script.md
│   ├── e031-script.md
│   ├── interview/
│   │   └── diesel-1.0/
│   │       ├── master.md
│   │       ├── part-1.md
│   │       └── part-2.md
│   ├── interview-1-part-1-script.md
│   ├── interview-1-part-2-script.md
│   ├── interview-3-script.md
│   ├── interview-4-part-1.md
│   ├── interview-4-part-2.md
│   ├── interview-4-part-3.md
│   ├── interview-4-sponsors.md
│   ├── irr_2017/
│   │   ├── anna-liao.md
│   │   ├── lee-baillie.md
│   │   └── matt-gathu.md
│   ├── meta-2.md
│   ├── meta-3.md
│   ├── news/
│   │   ├── 1-script.md
│   │   ├── 2-script.md
│   │   ├── increasing-rusts-reach.md
│   │   ├── rust-1-20.md
│   │   ├── rust-1-21-1-22.md
│   │   ├── rust-1-23.md
│   │   ├── rust-1-24.md
│   │   ├── rust-1-25.md
│   │   ├── rust-1-26.md
│   │   ├── rust-1-27.md
│   │   ├── rust-1-28.md
│   │   ├── rust-1-31/
│   │   │   ├── part-1.md
│   │   │   └── part-2.md
│   │   ├── rust-1-32.md
│   │   ├── rust-1.33-and-1.34.md
│   │   ├── rust-1.35.md
│   │   └── rust_1_29_1_30.md
│   └── rbr_2017/
│       ├── andrew-hobden.md
│       ├── anthony-deschamps.md
│       ├── arun-kulshreshtha.md
│       ├── ben-striegel.md
│       ├── colin-dean.md
│       ├── holden-marcsisin.md
│       ├── jess-saxeter.md
│       ├── master-script.md
│       └── pete-lyons.md
├── landing/
│   ├── index.html
│   ├── landing.css
│   └── sponsors.html
├── resources/
│   ├── .nojekyll
│   ├── CNAME
│   ├── favicon.pxm
│   ├── feed.xml
│   ├── media-playback.css
│   └── media-playback.js
├── rust-toolchain.toml
└── src/
    ├── bonus/
    │   ├── _1.rs
    │   ├── _10.rs
    │   ├── _13.rs
    │   ├── _14.rs
    │   ├── _2.rs
    │   ├── _3.rs
    │   ├── _4.rs
    │   ├── _5.rs
    │   ├── _6.rs
    │   ├── _7.rs
    │   ├── _8.rs
    │   ├── _9.rs
    │   ├── burnout.rs
    │   ├── mod.rs
    │   └── translating_between_languages.rs
    ├── cysk/
    │   ├── _1.rs
    │   ├── _2.rs
    │   ├── _3.rs
    │   ├── bindgen_cbindgen.rs
    │   ├── mod.rs
    │   ├── rayon.rs
    │   ├── rocket.rs
    │   ├── serde.rs
    │   └── wasm.rs
    ├── e000.rs
    ├── e001.rs
    ├── e002.rs
    ├── e003.rs
    ├── e004.rs
    ├── e005.rs
    ├── e006.rs
    ├── e007.rs
    ├── e008.rs
    ├── e009.rs
    ├── e010.rs
    ├── e011.rs
    ├── e012.rs
    ├── e013.rs
    ├── e014.rs
    ├── e015.rs
    ├── e016.rs
    ├── e017.rs
    ├── e018.rs
    ├── e019.rs
    ├── e020.rs
    ├── e021.rs
    ├── e022.rs
    ├── e023.rs
    ├── e024.rs
    ├── e025.rs
    ├── e026.rs
    ├── e027.rs
    ├── e028.rs
    ├── e029/
    │   ├── ffi-demo.c
    │   ├── ffi-demo.h
    │   └── mod.rs
    ├── e030.rs
    ├── e031/
    │   ├── e031.c
    │   ├── e031.h
    │   └── mod.rs
    ├── includes/
    │   └── media-playback-speed.html
    ├── interview/
    │   ├── _1/
    │   │   ├── mod.rs
    │   │   ├── part_1.rs
    │   │   └── part_2.rs
    │   ├── _2/
    │   │   ├── mod.rs
    │   │   ├── part_1.rs
    │   │   └── part_2.rs
    │   ├── _3.rs
    │   ├── _4/
    │   │   ├── mod.rs
    │   │   ├── part_1.rs
    │   │   ├── part_2.rs
    │   │   └── part_3.rs
    │   ├── diesel_1_0/
    │   │   ├── mod.rs
    │   │   ├── part_1.rs
    │   │   └── part_2.rs
    │   ├── integer32.rs
    │   ├── irr_2017/
    │   │   ├── anna_liao.rs
    │   │   ├── lee_baillie.rs
    │   │   ├── matt_gathu.rs
    │   │   └── mod.rs
    │   ├── mod.rs
    │   └── rbr_2017/
    │       ├── andrew_hobden.rs
    │       ├── anthony_deschamps.rs
    │       ├── arun_kulshreshthra.rs
    │       ├── ben_beckwith.rs
    │       ├── ben_striegel.rs
    │       ├── colin_dean.rs
    │       ├── esty_thomas.rs
    │       ├── holden_marcsisin.rs
    │       ├── jess_saxeter.rs
    │       ├── katie_nolan.rs
    │       ├── matthias_endler.rs
    │       ├── mod.rs
    │       ├── parry_wilcox.rs
    │       ├── pete_lyons.rs
    │       ├── thomas_gideon.rs
    │       └── tom_kriezkowski.rs
    ├── lib.rs
    ├── meta/
    │   ├── _1.rs
    │   ├── _2.rs
    │   ├── _3.rs
    │   └── mod.rs
    └── news/
        ├── _1.rs
        ├── _2.rs
        ├── _3.rs
        ├── mod.rs
        ├── rust_1_20.rs
        ├── rust_1_21_1_22.rs
        ├── rust_1_23.rs
        ├── rust_1_24.rs
        ├── rust_1_25.rs
        ├── rust_1_26.rs
        ├── rust_1_27.rs
        ├── rust_1_28.rs
        ├── rust_1_29_1_30.rs
        ├── rust_1_31/
        │   ├── mod.rs
        │   ├── part_1.rs
        │   └── part_2.rs
        ├── rust_1_32.rs
        ├── rust_1_33_1_34.rs
        └── rust_1_35.rs
Download .txt
SYMBOL INDEX (297 symbols across 73 files)

FILE: build.rs
  function main (line 5) | fn main() {

FILE: resources/media-playback.js
  function setPlaybackSpeed (line 1) | function setPlaybackSpeed(speed) {

FILE: src/bonus/_10.rs
  type Script (line 160) | pub struct Script;

FILE: src/bonus/_13.rs
  type Script (line 255) | pub struct Script;

FILE: src/bonus/_14.rs
  type Script (line 270) | pub struct Script;

FILE: src/bonus/burnout.rs
  type Script (line 191) | pub struct Script;

FILE: src/bonus/translating_between_languages.rs
  type Script (line 197) | pub struct Script;

FILE: src/cysk/bindgen_cbindgen.rs
  type Script (line 282) | pub struct Script;

FILE: src/cysk/serde.rs
  type Script (line 158) | pub struct Script;

FILE: src/cysk/wasm.rs
  type Script (line 163) | pub struct Script;

FILE: src/e000.rs
  function hello_world (line 44) | pub fn hello_world() {

FILE: src/e001.rs
  type TVShow (line 89) | pub struct TVShow {
    method new (line 109) | pub fn new(theme: &str, year: i32, director: &str) -> TVShow {
  function use_members (line 123) | pub fn use_members() {

FILE: src/e002.rs
  type Circle (line 58) | pub struct Circle {
    method origin (line 144) | fn origin(r: f64) -> Circle {
    method new (line 149) | pub fn new(x: f64, y: f64, r: f64) -> Circle {
    method x_by_ref (line 163) | pub fn x_by_ref(&self) -> f64 {
    method x_by_mut_ref (line 172) | pub fn x_by_mut_ref(&mut self) -> f64 {
    method by_take (line 185) | pub fn by_take(self) -> f64 {
    method by_take_mut (line 191) | pub fn by_take_mut(mut self) -> f64 {
  function demonstrate_ownership (line 68) | pub fn demonstrate_ownership() {
  function borrow (line 99) | pub fn borrow(ref_to_circle: &Circle) {
  function borrow_mut (line 115) | pub fn borrow_mut(mutable_ref_to_circle: &mut Circle) {
  function move_circle (line 127) | pub fn move_circle(moved_circle: Circle) {
  function demonstrate_method_ownership (line 199) | pub fn demonstrate_method_ownership() {

FILE: src/e003.rs
  type PreexistingStruct (line 74) | pub struct PreexistingStruct {
  type RelatedishThings (line 100) | pub enum RelatedishThings {
  function get_unit (line 116) | fn get_unit() -> RelatedishThings {
  function get_name (line 121) | fn get_name() -> RelatedishThings {
  function get_value (line 126) | fn get_value() -> RelatedishThings {
  function get_complex_data (line 131) | fn get_complex_data() -> RelatedishThings {
  function get_reused_structure (line 139) | fn get_reused_structure() -> RelatedishThings {
  function demonstrate_basic_enumeration (line 156) | pub fn demonstrate_basic_enumeration() {
  function demonstrate_match (line 177) | pub fn demonstrate_match() {
  function get_an_option (line 218) | pub fn get_an_option(get_it: bool) -> Option<f64> {
  function demonstrate_option (line 230) | pub fn demonstrate_option() {
  function get_a_result (line 251) | pub fn get_a_result(succeeds: bool) -> Result<f64, String> {
  function demonstrate_result (line 264) | pub fn demonstrate_result() {

FILE: src/e004.rs
  type MethodDemonstrator (line 62) | pub struct MethodDemonstrator {
    method new (line 89) | pub fn new() -> MethodDemonstrator {
    method method (line 108) | pub fn method(&self) {
    method get_hidden_data (line 129) | pub fn get_hidden_data(&self) -> (f64, String) {
  function demonstrate_methods (line 141) | pub fn demonstrate_methods() {
  function apply_function_to_i64 (line 162) | pub fn apply_function_to_i64<F>(a_number_function: F, the_number: i64) -...
  function demonstrate_function_arguments (line 176) | pub fn demonstrate_function_arguments() {
  function demonstrate_closure_environment (line 207) | pub fn demonstrate_closure_environment() {
  function demonstrate (line 242) | fn demonstrate() {

FILE: src/e005.rs
  function doubler_factory (line 91) | pub fn doubler_factory() -> Box<dyn Fn(i32) -> i32> {
  function doubler_closure_factory (line 108) | pub fn doubler_closure_factory() -> Box<dyn Fn(i32) -> i32> {
  function demonstrate_function_returns (line 154) | pub fn demonstrate_function_returns() {

FILE: src/e006.rs
  function a_public_module_fn (line 85) | pub fn a_public_module_fn() {
  function a_private_module_fn (line 96) | fn a_private_module_fn() {
  function a_public_module_fn (line 111) | pub fn a_public_module_fn() {
  function some_private_fn (line 117) | fn some_private_fn() {
  function use_modules_internal (line 127) | pub fn use_modules_internal() {
  function demonstrate_globbed_calls (line 166) | pub fn demonstrate_globbed_calls() {
  function demonstrate_aliased_calls (line 174) | pub fn demonstrate_aliased_calls() {
  function demonstrate_use_inside_function (line 182) | pub fn demonstrate_use_inside_function() {

FILE: src/e007.rs
  function add (line 96) | pub fn add(a: f64, b: f64) -> f64 {
  function test_add (line 107) | fn test_add() {
  function test_add_badly (line 138) | fn test_add_badly() {
  function test_will_panic (line 152) | fn test_will_panic() {
  function demonstrate_benchmarking (line 161) | fn demonstrate_benchmarking(bencher: &mut Bencher) {
  function support_function (line 172) | fn support_function(ns: u32) -> Duration {
  function demonstrate_benchmarking_with_sleep (line 182) | fn demonstrate_benchmarking_with_sleep(bencher: &mut Bencher) {

FILE: src/e008.rs
  function a_generic (line 100) | pub fn a_generic<T>(_t: T) {
  function a_generic_printable (line 107) | pub fn a_generic_printable<T: fmt::Debug>(t: T) {
  type Maybe (line 113) | pub enum Maybe<T> {
  type SimpleType (line 119) | pub struct SimpleType {
    method fmt (line 129) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  type GenericContainer (line 139) | pub struct GenericContainer<T, U> {
  type TestPoint (line 151) | struct TestPoint {
  type TestEnum (line 158) | enum TestEnum {
  function test_generic_fn (line 172) | fn test_generic_fn() {
  function test_generic_fn_with_debug_print (line 185) | fn test_generic_fn_with_debug_print() {
  function test_generic_enum (line 197) | fn test_generic_enum() {
  function test_generic_struct (line 220) | fn test_generic_struct() {
  function test_impl_display (line 235) | fn test_impl_display() {

FILE: src/e009.rs
  type DoubleAndOne (line 116) | pub struct DoubleAndOne {
    method the_usual (line 123) | pub fn the_usual() -> DoubleAndOne {
    method fmt (line 151) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    type Output (line 167) | type Output = DoubleAndOne;
    method add (line 169) | fn add(self, rhs: DoubleAndOne) -> DoubleAndOne {
  type ASimpleTrait (line 132) | pub trait ASimpleTrait {
    method get_some_integer (line 134) | fn get_some_integer(&self) -> i64;
    method a_default_print (line 137) | fn a_default_print(&self) -> &str {
    method get_some_integer (line 145) | fn get_some_integer(&self) -> i64 {
  type Item (line 158) | type Item = DoubleAndOne;
  method next (line 160) | fn next(&mut self) -> Option<DoubleAndOne> {
  function demonstrate_for (line 177) | pub fn demonstrate_for() {
  function test_a_simple_trait (line 195) | fn test_a_simple_trait() {
  function test_iterator (line 204) | fn test_iterator() {
  function test_add (line 215) | fn test_add() {
  function test_together (line 222) | fn test_together() {

FILE: src/e010.rs
  type TryResult (line 186) | pub type TryResult = Result<i32, &'static str>;
  function demonstrate_try (line 191) | pub fn demonstrate_try(tr: TryResult) -> TryResult {
  function test_demonstrate_try (line 206) | fn test_demonstrate_try() {
  function test_print_ident_name (line 212) | fn test_print_ident_name() {

FILE: src/e011.rs
  type Expressive (line 94) | pub enum Expressive {
    method fmt (line 104) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  type Strong (line 119) | pub enum Strong {
    method fmt (line 127) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  type StaticallyKnown (line 140) | pub enum StaticallyKnown {
    method fmt (line 146) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  type TypeSystem (line 157) | pub struct TypeSystem {
    method builder (line 165) | pub fn builder(
  function describe_type_systems (line 187) | pub fn describe_type_systems() {

FILE: src/e012.rs
  function functions_are_expressions (line 102) | pub fn functions_are_expressions() -> i32 {
  function if_blocks_are_expressions (line 119) | pub fn if_blocks_are_expressions() -> f64 {
  type ThreeTypes (line 147) | enum ThreeTypes {
  function match_blocks_are_expressions (line 157) | pub fn match_blocks_are_expressions() -> String {
  function ordinary_blocks_are_expressions (line 176) | pub fn ordinary_blocks_are_expressions() -> i32 {

FILE: src/e013.rs
  type Individual (line 118) | pub struct Individual<'a> {
  type NumericReference (line 139) | pub enum NumericReference<'a> {
  function refs_all_around (line 159) | pub fn refs_all_around<'a>(input: &'a [i32]) -> Option<&'a [i32]> {
  function test_refs_all_around (line 172) | fn test_refs_all_around() {

FILE: src/e014.rs
  function get_a_slice (line 105) | pub fn get_a_slice() -> &'static str {
  function get_a_string (line 110) | pub fn get_a_string() -> String {
  function show_from_behavior (line 117) | pub fn show_from_behavior() -> String {
  function demonstrate_unicode (line 122) | pub fn demonstrate_unicode() {
  function get_back_some_unicode (line 126) | pub fn get_back_some_unicode(desc: &str) -> String {
  function get_a_string_with_capacity (line 139) | pub fn get_a_string_with_capacity(capacity: usize) -> String {
  type Origin (line 159) | pub struct Origin;
  type DerefTarget (line 162) | pub struct DerefTarget;
  type Target (line 165) | type Target = DerefTarget;
  method deref (line 169) | fn deref(&self) -> &DerefTarget {
  function show_string_capacity (line 180) | fn show_string_capacity() {

FILE: src/e015.rs
  type FileData (line 158) | pub struct FileData {
    method new (line 163) | pub fn new(contents: &str) -> FileData {
  type ASendableType (line 170) | pub struct ASendableType {}
  function print_rc_count (line 173) | pub fn print_rc_count<T>(t: &Rc<T>) {
  function print_rc_body (line 178) | fn print_rc_body(fd: &Rc<FileData>) {
  function demonstrate_rc (line 183) | pub fn demonstrate_rc() {
  function get_empty_weak (line 219) | pub fn get_empty_weak(fd: Rc<FileData>) -> Weak<FileData> {
  function get_wrapped_file_data (line 223) | pub fn get_wrapped_file_data() -> Rc<FileData> {

FILE: src/e016.rs
  type SimpleContainer (line 150) | pub struct SimpleContainer {
  function demonstrate_need_for_cell (line 155) | pub fn demonstrate_need_for_cell() -> Vec<Cell<SimpleContainer>> {
  function double_cell (line 174) | pub fn double_cell(containers: &[Cell<SimpleContainer>]) {
  type SimpleNonCopyable (line 183) | pub struct SimpleNonCopyable {
  function add_to_each_string (line 188) | pub fn add_to_each_string(list_contained_strings: &[RefCell<SimpleNonCop...
  function need_for_cell (line 200) | fn need_for_cell() {
  function double_cell_works (line 214) | fn double_cell_works() {
  function add_to_each_string_works (line 228) | fn add_to_each_string_works() {

FILE: src/e017.rs
  type DataStore (line 123) | pub struct DataStore<'a> {
  function new (line 128) | pub fn new(contents: &'a i32) -> DataStore {
  function demonstrate_ref (line 134) | pub fn demonstrate_ref() {
  function demonstrate_deref (line 145) | pub fn demonstrate_deref() {
  function demonstrate_match (line 158) | pub fn demonstrate_match() {

FILE: src/e018.rs
  type NoImplsAtAll (line 124) | pub struct NoImplsAtAll {
    method new (line 129) | pub fn new(contents: &[u8; 8]) -> NoImplsAtAll {
  type HasAllTheImpls (line 142) | pub struct HasAllTheImpls {
    method new (line 147) | pub fn new(contents: &[u8; 8]) -> HasAllTheImpls {
    method borrow (line 155) | fn borrow(&self) -> &[u8] {
    method as_ref (line 161) | fn as_ref(&self) -> &[u8] {
  type Target (line 167) | type Target = [u8];
  method deref (line 169) | fn deref(&self) -> &[u8] {
  function takes_a_borrowable (line 175) | pub fn takes_a_borrowable<B: Borrow<[u8]>>(b: B) {
  function takes_a_reference (line 182) | pub fn takes_a_reference<A: AsRef<[u8]>>(a: A) {
  function coerces_via_deref (line 189) | pub fn coerces_via_deref(coerced: &[u8]) {
  function e018_demonstrate_borrow (line 200) | fn e018_demonstrate_borrow() {
  function e018_demonstrate_as_ref (line 218) | fn e018_demonstrate_as_ref() {}
  function e018_demonstrate_deref (line 221) | fn e018_demonstrate_deref() {

FILE: src/e019.rs
  type ANoCopyOrClonePoint (line 216) | pub struct ANoCopyOrClonePoint {
    method origin (line 224) | pub fn origin() -> ANoCopyOrClonePoint {
  type BJustClonePoint (line 272) | pub struct BJustClonePoint {
    method origin (line 279) | pub fn origin() -> BJustClonePoint {
  type CCopyPoint (line 309) | pub struct CCopyPoint {
    method origin (line 317) | pub fn origin() -> CCopyPoint {
  function demonstrate_cow (line 346) | pub fn demonstrate_cow(_point: &BJustClonePoint) {}
  function demonstrate_mut_cow (line 363) | pub fn demonstrate_mut_cow(_point: &mut BJustClonePoint) {}

FILE: src/e021.rs
  type Email (line 129) | pub type Email = String;
  type EmailStruct (line 170) | pub struct EmailStruct(pub String);
    method map (line 173) | pub fn map<F: FnOnce(String) -> String>(self, f: F) -> EmailStruct {
  type Item (line 180) | type Item = EmailStruct;
  method next (line 182) | fn next(&mut self) -> Option<EmailStruct> {
  type Target (line 189) | type Target = String;
  method deref (line 191) | fn deref(&self) -> &String {
  type EmailEnum (line 214) | pub enum EmailEnum {
  type Target (line 219) | type Target = String;
  method deref (line 221) | fn deref(&self) -> &String {
  type ThingToDestructure (line 240) | pub struct ThingToDestructure {
  function send (line 253) | pub fn send(_to_address: Email) {}
  function takes_a_str (line 275) | pub fn takes_a_str(_some_str: &str) {}

FILE: src/e022.rs
  type Script (line 147) | pub struct Script;
  function demo_send_and_sync (line 213) | pub fn demo_send_and_sync() {

FILE: src/e023.rs
  type Script (line 182) | pub struct Script;
  type Eatable (line 185) | pub trait Eatable {
    method prepare (line 187) | fn prepare(&self) -> String;
    method eat (line 190) | fn eat(&self) -> String {
    method prepare (line 212) | fn prepare(&self) -> String {
    method prepare (line 233) | fn prepare(&self) -> String {
    method eat (line 242) | fn eat(&self) -> String {
    method prepare (line 257) | fn prepare(&self) -> String {
    method eat (line 261) | fn eat(&self) -> String {
  type Nomable (line 197) | pub trait Nomable {
    method eat (line 198) | fn eat(&self) -> String {
  type Breakfast (line 205) | pub enum Breakfast {
  type MoarBreakfast (line 222) | pub enum MoarBreakfast {
  function demo_eatable (line 267) | pub fn demo_eatable() {

FILE: src/e024.rs
  type Script (line 177) | pub struct Script;
  type Point (line 201) | pub struct Point {
  type Output (line 208) | type Output = Point;
  method add (line 210) | fn add(self, other: Point) -> Point {
  type Eatable (line 220) | pub trait Eatable<T> {
    method eat (line 221) | fn eat(&self) -> T;
  function eat (line 225) | fn eat(&self) -> String {
  function to_string_inline (line 231) | pub fn to_string_inline<T: Display>(t: T) -> String {
  function to_string_with_where (line 237) | pub fn to_string_with_where<T>(t: T) -> String

FILE: src/e025.rs
  type Point (line 221) | pub struct Point {
  type Output (line 227) | type Output = Point;
  method sub (line 229) | fn sub(self, other: &Point) -> Point {
  function distance_from_boxed (line 237) | pub fn distance_from_boxed<'a, 'b: 'a>(offset: &'b Point) -> Box<dyn FnM...
  type DistanceFrom (line 244) | pub type DistanceFrom<'a> = Box<dyn FnMut(&'a Point) -> f32 + 'a>;
  function distance_from_alias (line 246) | pub fn distance_from_alias<'a, 'b: 'a>(offset: &'b Point) -> DistanceFro...
  function distance_from_impl (line 253) | pub fn distance_from_impl<'a, 'b: 'a>(offset: &'b Point) -> impl FnMut(&...
  type Script (line 261) | pub struct Script;

FILE: src/e026.rs
  type Script (line 194) | pub struct Script;

FILE: src/e027.rs
  type Script (line 280) | pub struct Script;

FILE: src/e028.rs
  type Script (line 264) | pub struct Script;

FILE: src/e029/ffi-demo.c
  function add (line 3) | int add(int a, int b) {
  function translate (line 7) | void translate(Point * point, float byX, float byY) {

FILE: src/e029/ffi-demo.h
  type Point (line 3) | typedef struct Point {

FILE: src/e029/mod.rs
  type Script (line 280) | pub struct Script;
  type Point (line 298) | pub struct Point {
  function add (line 327) | pub(super) fn add(a: c_int, b: c_int) -> c_int;
  function translate (line 342) | pub(super) fn translate(point: *mut Point, by_x: c_float, by_y: c_float);
  function add (line 367) | pub fn add(a: i32, b: i32) -> Option<i32> {
  function translate (line 394) | pub fn translate(point: &mut Point, by_x: f32, by_y: f32) {

FILE: src/e030.rs
  type Script (line 279) | pub struct Script;
  function local (line 284) | fn local() {}
  function demo (line 291) | pub fn demo() {
  function sibling (line 322) | fn sibling() {}
  function only_in_child (line 328) | fn only_in_child() {}
  function also_only_in_child (line 332) | pub fn also_only_in_child() {}
  function demo (line 341) | pub fn demo() {}
  function demo (line 347) | pub fn demo() {}
  function demo (line 357) | pub fn demo() {}
  function demo (line 364) | pub fn demo() {}
  function demo (line 369) | pub fn demo() {}

FILE: src/e031/e031.c
  function section (line 6) | void section() { printf("\n---\n\n"); }
  function main (line 8) | int main() {

FILE: src/e031/e031.h
  type point_t (line 11) | typedef struct point {
  type opaque_point_t (line 20) | typedef struct opaque_point opaque_point_t;

FILE: src/e031/mod.rs
  type Script (line 295) | pub struct Script;
  function add_in_rust (line 299) | pub extern "C" fn add_in_rust(a: c_int, b: c_int) -> c_int {
  function concat_strings (line 314) | pub unsafe extern "C" fn concat_strings(
  function free_rust_string (line 346) | pub unsafe extern "C" fn free_rust_string(to_free: *mut c_char) {
  type Point (line 362) | pub struct Point {
    method translate (line 370) | fn translate(&mut self, by_x: f32, by_y: f32) {
  function point_translate (line 382) | pub unsafe extern "C" fn point_translate(point: *mut Point, by_x: c_floa...
  type OpaquePoint (line 397) | pub struct OpaquePoint {
    method translate (line 403) | fn translate(&mut self, by_x: f32, by_y: f32) {
  method fmt (line 410) | fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
  function opaque_point_translate (line 425) | pub unsafe extern "C" fn opaque_point_translate(
  function opaque_point_new (line 441) | pub extern "C" fn opaque_point_new(x: c_float, y: c_float) -> *mut Opaqu...
  function opaque_point_describe (line 449) | pub unsafe extern "C" fn opaque_point_describe(point: *mut OpaquePoint) ...
  function opaque_point_free (line 466) | pub unsafe extern "C" fn opaque_point_free(point: *mut OpaquePoint) {
  function demo_union (line 483) | pub fn demo_union() {
  type Tag (line 520) | pub enum Tag {
  type Wrapped (line 527) | pub struct Wrapped<T: Copy + Clone>(T);
  type Either (line 539) | pub struct Either<L: Copy, R: Copy> {

FILE: src/interview/diesel_1_0/part_1.rs
  type Script (line 185) | pub struct Script;

FILE: src/interview/diesel_1_0/part_2.rs
  type Script (line 177) | pub struct Script;

FILE: src/interview/irr_2017/anna_liao.rs
  type Transcript (line 169) | pub struct Transcript;

FILE: src/interview/irr_2017/lee_baillie.rs
  type Transcript (line 163) | pub struct Transcript;

FILE: src/interview/irr_2017/matt_gathu.rs
  type Transcript (line 160) | pub struct Transcript;

FILE: src/interview/rbr_2017/andrew_hobden.rs
  type Transcript (line 11) | pub struct Transcript;

FILE: src/interview/rbr_2017/anthony_deschamps.rs
  type Transcript (line 11) | pub struct Transcript;

FILE: src/interview/rbr_2017/arun_kulshreshthra.rs
  type Transcript (line 11) | pub struct Transcript;

FILE: src/interview/rbr_2017/ben_striegel.rs
  type Transcript (line 11) | pub struct Transcript;

FILE: src/interview/rbr_2017/colin_dean.rs
  type Transcript (line 11) | pub struct Transcript;

FILE: src/interview/rbr_2017/holden_marcsisin.rs
  type Transcript (line 11) | pub struct Transcript;

FILE: src/interview/rbr_2017/jess_saxeter.rs
  type Transcript (line 11) | pub struct Transcript;

FILE: src/interview/rbr_2017/pete_lyons.rs
  type Transcript (line 11) | pub struct Transcript;

FILE: src/meta/_3.rs
  type Script (line 255) | pub struct Script;

FILE: src/news/rust_1_20.rs
  type Foo (line 144) | trait Foo {
    constant FOO (line 145) | const FOO: u32 = 0;
  type _Bar (line 148) | struct _Bar {}
    constant _BAR (line 151) | const _BAR: u32 = 50;
  type _Baz (line 156) | enum _Baz {}
    constant _BAZ (line 159) | const _BAZ: u32 = 100;
  function it_works (line 169) | fn it_works() {

FILE: src/news/rust_1_21_1_22.rs
  type Script (line 171) | pub struct Script;

FILE: src/news/rust_1_23.rs
  type Script (line 187) | pub struct Script;

FILE: src/news/rust_1_24.rs
  type Script (line 156) | pub struct Script;

FILE: src/news/rust_1_25.rs
  function demo_match (line 180) | pub fn demo_match(s: &str) {
  type Script (line 194) | pub struct Script;

FILE: src/news/rust_1_26.rs
  type Script (line 186) | pub struct Script;

FILE: src/news/rust_1_27.rs
  type Script (line 189) | pub struct Script;

FILE: src/news/rust_1_28.rs
  type Script (line 198) | pub struct Script;

FILE: src/news/rust_1_29_1_30.rs
  type Script (line 218) | pub struct Script;

FILE: src/news/rust_1_31/part_1.rs
  type Script (line 233) | pub struct Script;

FILE: src/news/rust_1_31/part_2.rs
  type Script (line 237) | pub struct Script;

FILE: src/news/rust_1_32.rs
  type Script (line 244) | pub struct Script;

FILE: src/news/rust_1_33_1_34.rs
  type Script (line 265) | pub struct Script;

FILE: src/news/rust_1_35.rs
  type Script (line 287) | pub struct Script;
Condensed preview — 233 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (2,196K chars).
[
  {
    "path": ".editorconfig",
    "chars": 59,
    "preview": "root = true\nindent_size = 4\n\n[*.{js,html}]\nindent_size = 2\n"
  },
  {
    "path": ".gitignore",
    "chars": 269,
    "preview": "# Rust/Cargo bits\ntarget\nCargo.lock\nrls\n\n# Website bits\n*.mp3\n*.m4a\n*.logicx\nrecordings\n\n# Miscellaneous tooling bits\n.p"
  },
  {
    "path": ".travis.yml",
    "chars": 92,
    "preview": "language: rust\ncache: cargo\nrust:\n- nightly\nbranches:\n  only:\n  - master\nscript:\n- make all\n"
  },
  {
    "path": "Cargo.toml",
    "chars": 297,
    "preview": "[package]\nedition = \"2018\"\nname = \"show-notes\"\n# Version will match released show number! Episode 12 will be `0.1.2`.\nve"
  },
  {
    "path": "LICENSE.md",
    "chars": 16299,
    "preview": "License\n=======\n\nTechnical materials\n-------------------\n\nThe MIT License (MIT)\n\nCopyright (c) 2015 Chris Krycho\n\nPermis"
  },
  {
    "path": "Makefile",
    "chars": 833,
    "preview": "# -- Define variables. -- #\nBUILD_DIR = target/doc\nSRC = src/*.rs\nLANDING = landing/*.html landing/*.css\nRESOURCES = res"
  },
  {
    "path": "README.md",
    "chars": 859,
    "preview": "# New Rustacean\n\nThis is a *slightly ridiculous* approach to building a podcast hosting setup using\nRust's documentation"
  },
  {
    "path": "build.rs",
    "chars": 502,
    "preview": "use std::process::Command;\n\nuse cc::Build;\n\nfn main() {\n    // Build a C file to link into Rust code.\n    Build::new().f"
  },
  {
    "path": "docs/bonus/10-script.md",
    "chars": 32720,
    "preview": "# Becoming a Contributor\n\n## Chris Krycho\n\n### Rust Belt Rust, 2017\n\n---\n\n![family](http://cdn.chriskrycho.com/images/ta"
  },
  {
    "path": "docs/bonus/13-silly-mistakes.md",
    "chars": 10965,
    "preview": "# Bonus: I Still Make Silly Mistakes\n\nHello, I’m Chris Krycho and this is New Rustacean: a show about the Rust programmi"
  },
  {
    "path": "docs/bonus/14-my-workflow.md",
    "chars": 16444,
    "preview": "# Bonus: How the Sausage Gets Made\n\nHello, I’m Chris Krycho and this is New Rustacean: a show about the Rust Programming"
  },
  {
    "path": "docs/bonus/burnout-script.md",
    "chars": 4259,
    "preview": "# Bonus: Burnout\n\nHello, I’m Chris Krycho and this is New Rustacean: a show about the Rust Programming Language and the "
  },
  {
    "path": "docs/bonus/translating-between-languages-script.md",
    "chars": 11060,
    "preview": "# Bonus: Translating Between Languages\n\nHello, I’m Chris Krycho and this is New Rustacean: a show about the Rust Program"
  },
  {
    "path": "docs/bonus-2-script.md",
    "chars": 1487,
    "preview": "Legacy Code\n===========\n\nIntro (15s)\n-----\nHello, I'm Chris Krycho, and this is the New Rustacean podcast---a 15--20 min"
  },
  {
    "path": "docs/bonus-3-script.md",
    "chars": 3555,
    "preview": "Building as a Community\n=======================\n\nIntro (30s -> 0:30)\n-----\nHello, I'm Chris Krycho, and this is the New "
  },
  {
    "path": "docs/bonus-4-script.md",
    "chars": 7536,
    "preview": "# We *can* have nice things.\n\n## Intro {>> 15s <<}\n\nHello, I'm Chris Krycho, and this is the New Rustacean podcast---a s"
  },
  {
    "path": "docs/bonus-5-script.md",
    "chars": 8880,
    "preview": "# Better than open source contributions\n\n## Intro\n\nHello, I'm Chris Krycho, and this is the New Rustacean podcast---a sh"
  },
  {
    "path": "docs/bonus-6-script.md",
    "chars": 8995,
    "preview": "# It doesn't need to be sexy\n\n## Intro\n\nHello, I'm Chris Krycho, and this is the New Rustacean podcast---a show about le"
  },
  {
    "path": "docs/bonus-7-script.md",
    "chars": 4737,
    "preview": "# Katas---learning by doing\n\n## Intro\n\nHello, I'm Chris Krycho, and this is the New Rustacean podcast---a show about lea"
  },
  {
    "path": "docs/bonus-8-script.md",
    "chars": 11789,
    "preview": "# Giving Back (by Teaching)\n\n## Intro\n\nHello, I'm Chris Krycho, and this is the New Rustacean podcast---a show about lea"
  },
  {
    "path": "docs/bonus-9-script.md",
    "chars": 940,
    "preview": "# Outro\n\n\nThanks to this month's $10-or-more sponsors:\n\n- Anthony Deschamps\n- Chris Palmer\n- Christopher Giffard\n- Behna"
  },
  {
    "path": "docs/cysk/bindgen-cbindgen-script.md",
    "chars": 14991,
    "preview": "# CYSK: `bindgen` and `cbindgen`\n\n## Intro\n\nHello, I’m Chris Krycho and this is New Rustacean: a show about the Rust pro"
  },
  {
    "path": "docs/cysk/serde.md",
    "chars": 9104,
    "preview": "# Crates You Should Know: Serde\n\nHello, I’m Chris Krycho, and this is New Rustacean: a show about the Rust programming l"
  },
  {
    "path": "docs/cysk/wasm.md",
    "chars": 10476,
    "preview": "# Crates You Should Know: the `wasm-` tools\n\nHello, I’m Chris Krycho and this is New Rustacean: a show about the Rust pr"
  },
  {
    "path": "docs/cysk-1.md",
    "chars": 7346,
    "preview": "# `quick-xml`\n\n## Intro\n\nHello, I'm Chris Krycho, and this is the New Rustacean podcast---a 15--20 minute show about lea"
  },
  {
    "path": "docs/cysk-2.md",
    "chars": 8322,
    "preview": "# `clap`\n\nHello, I'm Chris Krycho, and this is the New Rustacean podcast---a 15--20 show about learning the Rust program"
  },
  {
    "path": "docs/cysk-3.md",
    "chars": 7910,
    "preview": "# RLS\n\nHello, I'm Chris Krycho, and this is the New Rustacean podcast---a 15--20 show about learning the Rust programmin"
  },
  {
    "path": "docs/cysk-rayon.md",
    "chars": 10440,
    "preview": "# Rayon\n#podcasts/new rustacean/crates you should know#\n\n## Intro\n\nHello, my name is Chris Krycho, and this is the New R"
  },
  {
    "path": "docs/cysk-rocket.md",
    "chars": 12524,
    "preview": "# Crates You Should Know: Rocket\n\n## Intro\n\nHello, my name is Chris Krycho, and this is the New Rustacean podcast – a sh"
  },
  {
    "path": "docs/e000-script.md",
    "chars": 3603,
    "preview": "\"Hello! I'm Chris Krycho, and this is the New Rustacean podcast---a 15--20 minute show about learning the Rust programmi"
  },
  {
    "path": "docs/e001-script.md",
    "chars": 1783,
    "preview": "# e01: Document All The Things\n\n## Intro\nHello, I'm Chris Krycho and this is the New Rustacean podcast, a 15--20 minute\n"
  },
  {
    "path": "docs/e002-script.md",
    "chars": 4664,
    "preview": "e002: Something borrowed, something... moved?\n=============================================\n\nIntro (30s)\n-----\nHello, I'"
  },
  {
    "path": "docs/e003-script.md",
    "chars": 3116,
    "preview": "No More Nulls\n=============\n\nIntro (30s)\n-----\nHello, I'm Chris Krycho, and this is the New Rustacean podcast---a 15--20"
  },
  {
    "path": "docs/e004-script.md",
    "chars": 8081,
    "preview": "Functionalized\n==============\n\nIntro (30s)\n-----\nHello, I'm Chris Krycho, and this is the New Rustacean podcast---a 15--"
  },
  {
    "path": "docs/e005-script.md",
    "chars": 11116,
    "preview": "Allocate It Where?\n==================\n\nIntro (30s)\n-----\nHello, I'm Chris Krycho, and this is the New Rustacean podcast-"
  },
  {
    "path": "docs/e006-script.md",
    "chars": 11824,
    "preview": "Modularize this!\n================\n\nIntro (30s)\n-----\nHello, I'm Chris Krycho, and this is the New Rustacean podcast---a "
  },
  {
    "path": "docs/e007-script.md",
    "chars": 15191,
    "preview": "Testify\n=======\n\nIntro (15s)\n-----\nHello, I'm Chris Krycho, and this is the New Rustacean podcast---a 15--20 minute\nshow"
  },
  {
    "path": "docs/e008-script.md",
    "chars": 14709,
    "preview": "Just like something else\n========================\n\nIntro (15s)\n-----\nHello, I'm Chris Krycho, and this is the New Rustac"
  },
  {
    "path": "docs/e009-script.md",
    "chars": 13542,
    "preview": "Composing a Rustic tune\n=======================\n\nIntro (30s)\n-----\nHello, I'm Chris Krycho, and this is the New Rustacea"
  },
  {
    "path": "docs/e010-script.md",
    "chars": 15237,
    "preview": "Macros rule!\n============\n\nIntro (30s -> 0:30)\n-----\n\nHello, I'm Chris Krycho, and this is the New Rustacean podcast---a"
  },
  {
    "path": "docs/e011-script.md",
    "chars": 15681,
    "preview": "Once upon a type\n================\n\n\nIntro {>> 30s → 0:30 <<}\n-----\n\nHello, I'm Chris Krycho, and this is the New Rustace"
  },
  {
    "path": "docs/e011-transcript.md",
    "chars": 15469,
    "preview": "New Rustacean 11\nTranscript by @jeremywsherman\n\n hello, I'm Chris Krycho, and this is the New Rustacean podcast, a fifte"
  },
  {
    "path": "docs/e012-script.md",
    "chars": 14433,
    "preview": "I'm not familiar with that expression\n=====================================\n\nIntro {>> 15s → 0:15 <<}\n-----\n\nHello, I'm "
  },
  {
    "path": "docs/e014-script.md",
    "chars": 15380,
    "preview": "# Stringing things along\n\n## Intro {>> 15s → 0:15 <<}\n\nHello, I'm Chris Krycho, and this is the New Rustacean podcast---"
  },
  {
    "path": "docs/e015-script.md",
    "chars": 15155,
    "preview": "# Not Dumb Pointers\n\n## Intro\n\nHello, I'm Chris Krycho, and this is the New Rustacean podcast---a 15--20 minute show abo"
  },
  {
    "path": "docs/e016-script.md",
    "chars": 15060,
    "preview": "# `RefCell`s and code smells\n\n## Intro\n\nHello, I'm Chris Krycho, and this is the New Rustacean podcast---a 15--20 minute"
  },
  {
    "path": "docs/e017-script.md",
    "chars": 15127,
    "preview": "# Point me where I need to go\n\n## Intro\n\nHello, I'm Chris Krycho, and this is the New Rustacean podcast---a 15--20 minut"
  },
  {
    "path": "docs/e018-script.md",
    "chars": 15411,
    "preview": "# `Borrow`, `AsRef`, `Deref`: my head hurts now\n\n## Intro\n\nHello, I'm Chris Krycho, and this is the New Rustacean podcas"
  },
  {
    "path": "docs/e019-script.md",
    "chars": 16720,
    "preview": "# Let's `Clone` a `Cow`!\n\n## Intro\n\nHello, I'm Chris Krycho, and this is the New Rustacean podcast---a 15--20 minute sho"
  },
  {
    "path": "docs/e020-script.md",
    "chars": 16180,
    "preview": "# Putting Code in its Place\n\n## Intro\n\nHello, I'm Chris Krycho, and this is the New Rustacean podcast—a 15--20 minute sh"
  },
  {
    "path": "docs/e021-script.md",
    "chars": 14077,
    "preview": "# Keeping your types under cover\n\n## Intro\n\nHello, I'm Chris Krycho, and this is the New Rustacean podcast: a show about"
  },
  {
    "path": "docs/e022-script.md",
    "chars": 14431,
    "preview": "Full script for the episode.\n\n# e022: `Send` and `Sync`\n\n**Note:** In the original (recorded) version of the episode, I "
  },
  {
    "path": "docs/e023-script.md",
    "chars": 18090,
    "preview": "# e023: Traits Deep Dive, Part I\n\n## Intro\n\nHello, I’m Chris Krycho and this is New Rustacean: a show about the Rust pro"
  },
  {
    "path": "docs/e024-script.md",
    "chars": 16125,
    "preview": "# e024: Traits Deep Dive, Part II\n\n## Intro\n\nHello, I’m Chris Krycho and this is New Rustacean: a show about the Rust pr"
  },
  {
    "path": "docs/e025-script.md",
    "chars": 19363,
    "preview": "# e025: Traits Deep Dive, Part III\n\n## Sponsor: [Parity Technologies](https://paritytech.io)\n\nHello, everyone! Over the "
  },
  {
    "path": "docs/e026-script.md",
    "chars": 15692,
    "preview": "# e026: Functional Programming Ideas in Rust\n\nHello, I’m Chris Krycho, and this is New Rustacean: a show about the Rust "
  },
  {
    "path": "docs/e027-script.md",
    "chars": 18603,
    "preview": "# e027: I Promise; Trust Me\n\nHello, I’m Chris Krycho, and this is New Rustacean: a show about the Rust Programming Langu"
  },
  {
    "path": "docs/e028-script.md",
    "chars": 18383,
    "preview": "# Meet My Associates\n\nHello, I’m Chris Krycho and this is New Rustacean: a show about the Rust programming language and "
  },
  {
    "path": "docs/e029-script.md",
    "chars": 19361,
    "preview": "# e029: I’m Out To C\n\nHello, I’m Chris Krycho and this is New Rustacean: a show about the Rust programming language and "
  },
  {
    "path": "docs/e030-script.md",
    "chars": 16533,
    "preview": "# e030: Can You See Me Now?\n\nHello, I’m Chris Krycho and this is New Rustacean: a show about the Rust programming langua"
  },
  {
    "path": "docs/e031-script.md",
    "chars": 22339,
    "preview": "# e031: FFI Deep Dive!\n\n## Intro\n\nHello, I’m Chris Krycho and this is New Rustacean: a show about the Rust programming l"
  },
  {
    "path": "docs/interview/diesel-1.0/master.md",
    "chars": 1489,
    "preview": "# News: Rust 1.23\n\nHello, I’m Chris Krycho and this is New Rustacean: a show about the Rust programming language and the"
  },
  {
    "path": "docs/interview/diesel-1.0/part-1.md",
    "chars": 1533,
    "preview": "# Interview: Diesel 1.0, with Sean Griffin, Part 1\n\nHello, I’m Chris Krycho and this is New Rustacean: a show about the "
  },
  {
    "path": "docs/interview/diesel-1.0/part-2.md",
    "chars": 1533,
    "preview": "# Interview: Diesel 1.0, with Sean Griffin, Part 2\n\nHello, I’m Chris Krycho and this is New Rustacean: a show about the "
  },
  {
    "path": "docs/interview-1-part-1-script.md",
    "chars": 1179,
    "preview": "Closing\n-------\n...if you want to hear Sean answer that question, you'll have to come back for\npart 2, which should be u"
  },
  {
    "path": "docs/interview-1-part-2-script.md",
    "chars": 2310,
    "preview": "Opening\n-------\n\nHello, I'm Chris Krycho, and this is the New Rustacean podcast---a show about\nlearning the Rust program"
  },
  {
    "path": "docs/interview-3-script.md",
    "chars": 1461,
    "preview": "## Intro\n\nHello, I'm Chris Krycho, and this is the New Rustacean podcast---a show about learning the Rust programming la"
  },
  {
    "path": "docs/interview-4-part-1.md",
    "chars": 1902,
    "preview": "# RLS\n\nHello, I'm Chris Krycho, and this is the New Rustacean podcast---a 15--20 show about learning the Rust programmin"
  },
  {
    "path": "docs/interview-4-part-2.md",
    "chars": 1843,
    "preview": "Hello, I'm Chris Krycho, and this is the New Rustacean podcast: a show about learning the Rust Programming Language. Thi"
  },
  {
    "path": "docs/interview-4-part-3.md",
    "chars": 1897,
    "preview": "Hello, I'm Chris Krycho, and this is the New Rustacean podcast, a show about the Rust programming language. This is Inte"
  },
  {
    "path": "docs/interview-4-sponsors.md",
    "chars": 1820,
    "preview": "# RLS\n\nHello, I'm Chris Krycho, and this is the New Rustacean podcast---a 15--20 show about learning the Rust programmin"
  },
  {
    "path": "docs/irr_2017/anna-liao.md",
    "chars": 1539,
    "preview": "# Increasing Rust's Reach: Anna Liao\n\nHello, I'm Chris Krycho and this is New Rustacean: a show about the Rust programmi"
  },
  {
    "path": "docs/irr_2017/lee-baillie.md",
    "chars": 1543,
    "preview": "# Increasing Rust's Reach: Lee Baillie\n\nHello, I'm Chris Krycho and this is New Rustacean: a show about the Rust program"
  },
  {
    "path": "docs/irr_2017/matt-gathu.md",
    "chars": 1542,
    "preview": "# Increasing Rust's Reach: Lee Baillie\n\nHello, I'm Chris Krycho and this is New Rustacean: a show about the Rust program"
  },
  {
    "path": "docs/meta-2.md",
    "chars": 9620,
    "preview": "# Meta 2: Two Milestones\n\nHello, I'm Chris Krycho and this is New Rustacean: a podcast about the Rust programming langua"
  },
  {
    "path": "docs/meta-3.md",
    "chars": 12732,
    "preview": "# Meta 3: Happy Coding!\n\n## Intro\n\nHello, I’m Chris Krycho, and this is the *final* episode of New Rustacean: a show abo"
  },
  {
    "path": "docs/news/1-script.md",
    "chars": 21431,
    "preview": "# One year and counting\n\n## Intro\n\nHello, I'm Chris Krycho, and this is the New Rustacean podcast---a 15--20 minute show"
  },
  {
    "path": "docs/news/2-script.md",
    "chars": 18647,
    "preview": "# Let's Talk Roadmap\n\n## Intro\n\nHello, I'm Chris Krycho, and this is the New Rustacean podcast---a 15--20 minute show ab"
  },
  {
    "path": "docs/news/increasing-rusts-reach.md",
    "chars": 9081,
    "preview": "\n## Intro\n\nHello, I'm Chris Krycho, and this is the New Rustacean podcast, a show about learning the Rust programming la"
  },
  {
    "path": "docs/news/rust-1-20.md",
    "chars": 9856,
    "preview": "# Rust 1.20\n\n## Intro\n\nHello, my name is Chris Krycho, and this is the New Rustacean podcast – a show about learning the"
  },
  {
    "path": "docs/news/rust-1-21-1-22.md",
    "chars": 11948,
    "preview": "# News: Rust 1.21 and 1.22\n\nHello, I'm Chris Krycho, and this is New Rustacean, a show about the Rust programming langua"
  },
  {
    "path": "docs/news/rust-1-23.md",
    "chars": 12340,
    "preview": "# News: Rust 1.23\n\nHello, I’m Chris Krycho and this is New Rustacean: a show about the Rust programming language and the"
  },
  {
    "path": "docs/news/rust-1-24.md",
    "chars": 14955,
    "preview": "# Rust 1.24\n\nHello, I’m Chris Krycho and this is New Rustacean: a show about the Rust programming language and the peopl"
  },
  {
    "path": "docs/news/rust-1-25.md",
    "chars": 10810,
    "preview": "# News: Rust 1.25\n\nHello, I’m Chris Krycho and this is New Rustacean: a show about the Rust programming language and the"
  },
  {
    "path": "docs/news/rust-1-26.md",
    "chars": 12584,
    "preview": "# Rust 1.26\n\nHello, I’m Chris Krycho and this is New Rustacean, a show about the Rust Programming Language and the peopl"
  },
  {
    "path": "docs/news/rust-1-27.md",
    "chars": 13494,
    "preview": "# Rust 1.27\n\nHello, I’m Chris Krycho and this is New Rustacean, a show about the Rust Programming Language and the peopl"
  },
  {
    "path": "docs/news/rust-1-28.md",
    "chars": 14316,
    "preview": "# Rust 1.28\n\nHello, I’m Chris Krycho and this is New Rustacean: a show about the Rust programming language and the peopl"
  },
  {
    "path": "docs/news/rust-1-31/part-1.md",
    "chars": 17916,
    "preview": "# News: Rust 1.31 – The 2018 Edition, Part I\n\nHello, I’m Chris Krycho, and this is New Rustacean: a show about the Rust "
  },
  {
    "path": "docs/news/rust-1-31/part-2.md",
    "chars": 18719,
    "preview": "# News: Rust 1.31 – The 2018 Edition, Part II\n\nHello, I’m Chris Krycho, and this is New Rustacean: a show about the Rust"
  },
  {
    "path": "docs/news/rust-1-32.md",
    "chars": 15171,
    "preview": "# News: Rust 1.32\n\nHello! I’m Chris Krycho and this is New Rustacean: a show about the Rust Programming Language and the"
  },
  {
    "path": "docs/news/rust-1.33-and-1.34.md",
    "chars": 15215,
    "preview": "# News: Rust 1.33 and 1.34\n\nHello, I’m Chris Krycho and this is New Rustacean: a show about the Rust programming languag"
  },
  {
    "path": "docs/news/rust-1.35.md",
    "chars": 15816,
    "preview": "# News: Rust 1.35\n\n## Intro\n\nHello, I’m Chris Krycho and this is New Rustacean: a show about the Rust programming langua"
  },
  {
    "path": "docs/news/rust_1_29_1_30.md",
    "chars": 14427,
    "preview": "# Rust 1.29 and 1.30\n\nHello, I’m Chris Krycho, and this is New Rustacean: a show about the Rust Programming language and"
  },
  {
    "path": "docs/rbr_2017/andrew-hobden.md",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "docs/rbr_2017/anthony-deschamps.md",
    "chars": 3086,
    "preview": "# Anthony Deschamps\n\n**Chris:** hello! Can you tell me your name and a little bit about yourself?\n\n**Anthony:** My name "
  },
  {
    "path": "docs/rbr_2017/arun-kulshreshtha.md",
    "chars": 3958,
    "preview": "# Arun Kulshreshtha\n\n**Chris:** Hi, can you tell us your name and where you work and how you got into Rust?\n\n**Arun:** S"
  },
  {
    "path": "docs/rbr_2017/ben-striegel.md",
    "chars": 4524,
    "preview": "# Ben Striegel\n\nC: Hello!\n\nB: Hello!\n\nC: Can you tell me your name and a little about yourself?\n\nB: Ben Striegel, I curr"
  },
  {
    "path": "docs/rbr_2017/colin-dean.md",
    "chars": 4398,
    "preview": "Read the episode transcript!\n\n# Colin Dean\n\n**Chris:** Can you tell me your name?\n\n**Colin:** I am Colin Dean.\n\n**Chris:"
  },
  {
    "path": "docs/rbr_2017/holden-marcsisin.md",
    "chars": 3994,
    "preview": "# Holden Marcsisin\n\nC: Hello! Can you tell us your name and a little bit about yourself?\n\nH: Um, I’m Holden, I’m a stude"
  },
  {
    "path": "docs/rbr_2017/jess-saxeter.md",
    "chars": 2728,
    "preview": "# Jess Saxeter\n\n**Chris:** Hello! Can you tell us your name, and where you work or where you’re from?\n\n**Jess:** Hi, my "
  },
  {
    "path": "docs/rbr_2017/master-script.md",
    "chars": 1560,
    "preview": "# Rust Belt Rust: Micro-interviews\n\nHello, I'm Chris Krycho and this is New Rustacean: a podcast about the Rust programm"
  },
  {
    "path": "docs/rbr_2017/pete-lyons.md",
    "chars": 2588,
    "preview": "# Pete Lyons\n\n**Chris:** Hello! Can you tell us your name and a little bit about yourself?\n\n**Pete:** Uh, my name is Pet"
  },
  {
    "path": "landing/index.html",
    "chars": 4325,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <title>New Rustacean: A Podcast About Learning Rust</title>\n\n  "
  },
  {
    "path": "landing/landing.css",
    "chars": 7247,
    "preview": "/**\n * Copyright 2013 The Rust Project Developers. See the COPYRIGHT\n * file at the top-level directory of this distribu"
  },
  {
    "path": "landing/sponsors.html",
    "chars": 9440,
    "preview": "<!DOCTYPE html>\n<html>\n\n<head>\n  <meta charset=\"utf-8\">\n  <title>New Rustacean: A Podcast About Learning Rust</title>\n\n "
  },
  {
    "path": "resources/.nojekyll",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "resources/CNAME",
    "chars": 17,
    "preview": "newrustacean.com\n"
  },
  {
    "path": "resources/feed.xml",
    "chars": 529413,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<rss xmlns:atom=\"http://www.w3.org/2005/Atom\" xmlns:itunes=\"http://www.itunes.com"
  },
  {
    "path": "resources/media-playback.css",
    "chars": 237,
    "preview": ".playback-rate-controls ul {\n    margin: 0;\n    padding: 0;\n    list-style: none;\n    text-align: center;\n}\n.playback-ra"
  },
  {
    "path": "resources/media-playback.js",
    "chars": 733,
    "preview": "function setPlaybackSpeed(speed) {\n  [].slice.call(document.querySelectorAll(\"audio,video\")).map(function(e, idx) {\n    "
  },
  {
    "path": "rust-toolchain.toml",
    "chars": 43,
    "preview": "[toolchain]\nchannel = \"nightly-2024-06-10\"\n"
  },
  {
    "path": "src/bonus/_1.rs",
    "chars": 1906,
    "preview": "//! Polyglot programming promises and perils\n//!\n//!   - **Date:** November 25, 2015\n//!   - **Subject:** The delights a"
  },
  {
    "path": "src/bonus/_10.rs",
    "chars": 4870,
    "preview": "//! \"Becoming a Contributor\"\n//!\n//!   - **Date:** March 17, 2018\n//!   - **Subject:** My Rust Belt Rust 2017 talk!\n//! "
  },
  {
    "path": "src/bonus/_13.rs",
    "chars": 7929,
    "preview": "//! I Still Make Silly Mistakes\n//!\n//! - **Date:** February 28, 2019\n//! - **Subject:** A story about parsing command-l"
  },
  {
    "path": "src/bonus/_14.rs",
    "chars": 8358,
    "preview": "//! How the Sausage Gets Made\n//!\n//! - **Date:** March 23, 2019\n//! - **Subject:** How I make the show, and why you won"
  },
  {
    "path": "src/bonus/_2.rs",
    "chars": 1756,
    "preview": "//! Legacy code\n//!\n//!   - **Date:** December 6, 2015\n//!   - **Subject:** Paying off technical debt, refactoring, and "
  },
  {
    "path": "src/bonus/_3.rs",
    "chars": 1908,
    "preview": "//! Building as a community\n//!\n//!   - **Date:** January 31, 2016\n//!   - **Subject:** The value of a good community, a"
  },
  {
    "path": "src/bonus/_4.rs",
    "chars": 2826,
    "preview": "//! We *can* have nice things\n//!\n//!   - **Date:** April 19, 2016\n//!   - **Subject:** Just how good Rust is, and how y"
  },
  {
    "path": "src/bonus/_5.rs",
    "chars": 3016,
    "preview": "//! Better than open source contributions\n//!\n//!   - **Date:** May 9, 2016\n//!   - **Subject:** Some things matter more"
  },
  {
    "path": "src/bonus/_6.rs",
    "chars": 3905,
    "preview": "//! It doesn't have to be sexy\n//!\n//!   - **Date:** August 20, 2016\n//!   - **Subject:** Building (and celebrating) all"
  },
  {
    "path": "src/bonus/_7.rs",
    "chars": 4735,
    "preview": "//! Katas---or: learning by doing\n//!\n//!   - **Date:** September 10, 2016\n//!   - **Subject:** Building (and celebratin"
  },
  {
    "path": "src/bonus/_8.rs",
    "chars": 3708,
    "preview": "//! Giving back (by teaching)\n//!\n//!   - **Date:** March 19, 2017\n//!   - **Subject:** On the responsibilities and oppo"
  },
  {
    "path": "src/bonus/_9.rs",
    "chars": 4402,
    "preview": "//! Open source is mostly just normal people\n//!\n//!   - **Date:** August 14, 2017\n//!   - **Subject:** My experience wi"
  },
  {
    "path": "src/bonus/burnout.rs",
    "chars": 6054,
    "preview": "//! Burnout\n//!\n//!   - **Date:** September 22, 2018\n//!   - **Subject:** What burnout is, the many ways it can happen t"
  },
  {
    "path": "src/bonus/mod.rs",
    "chars": 281,
    "preview": "//! Bonus episodes: shorter, and usually more about community or philosophy.\n\npub mod _1;\npub mod _10;\npub mod _13;\npub "
  },
  {
    "path": "src/bonus/translating_between_languages.rs",
    "chars": 6058,
    "preview": "//! Translating Between Languages\n//!\n//! - **Date:** October 23, 2018\n//! - **Subject:** Musings inspired by a project "
  },
  {
    "path": "src/cysk/_1.rs",
    "chars": 2988,
    "preview": "//! quick-xml\n//!\n//!   - **Date:** January 8, 2017\n//!   - **Subject:** A pull-parser for reading and writing XML.\n//! "
  },
  {
    "path": "src/cysk/_2.rs",
    "chars": 3763,
    "preview": "//! clap\n//!\n//!   - **Date:** Feburary 14, 2017\n//!   - **Subject:** A Command-Line Argument Parser.\n//!   - [**Audio**"
  },
  {
    "path": "src/cysk/_3.rs",
    "chars": 4458,
    "preview": "//! Rust Language Service\n//!\n//!   - **Date:** April 18, 2017\n//!   - **Subject:** Where the RLS came from, what it can"
  },
  {
    "path": "src/cysk/bindgen_cbindgen.rs",
    "chars": 8673,
    "preview": "//! bindgen and cbindgen\n//!\n//! - **Date:** May 17, 2019\n//! - **Subject:** Automatic generation of FFI types between R"
  },
  {
    "path": "src/cysk/mod.rs",
    "chars": 203,
    "preview": "//! Brief discussions of important and useful crates around the Rust ecosystem.\n\npub mod _1;\npub mod _2;\npub mod _3;\npub"
  },
  {
    "path": "src/cysk/rayon.rs",
    "chars": 4701,
    "preview": "//! Rayon\n//!\n//!   - **Date:** September 16, 2017\n//!   - **Subject:** Safe, threaded, parallel code in Rust!\n//!   - ["
  },
  {
    "path": "src/cysk/rocket.rs",
    "chars": 4367,
    "preview": "//! Rocket\n//!\n//!   - **Date:** June 30, 2017\n//!   - **Subject:** An accessible, well-designed web framework in Rust!\n"
  },
  {
    "path": "src/cysk/serde.rs",
    "chars": 5015,
    "preview": "//! Serde\n//!\n//!   - **Date:** February 10, 2018\n//!   - **Subject:** The library for serialization and deserialization"
  },
  {
    "path": "src/cysk/wasm.rs",
    "chars": 5118,
    "preview": "//! The wasm tools\n//!\n//!   - **Date:** March 31, 2018\n//!   - **Subject:** wasm intro, `wasm-bindgen`, and `wasm-pack`"
  },
  {
    "path": "src/e000.rs",
    "chars": 1978,
    "preview": "//! Hello, world!\n//!\n//!   - **Date:** September 24, 2015\n//!   - **Subject:** The host, the language, and the show!\n//"
  },
  {
    "path": "src/e001.rs",
    "chars": 5694,
    "preview": "//! Document all the things!\n//!\n//!   - **Date:** October 3, 2015\n//!   - **Subject:** Documentation in general, and `r"
  },
  {
    "path": "src/e002.rs",
    "chars": 10184,
    "preview": "//! Something borrowed, something... moved?\n//!\n//!   - **Date:** October 12, 2015\n//!   - **Subject:** The `struct` dat"
  },
  {
    "path": "src/e003.rs",
    "chars": 11228,
    "preview": "//! No. more. nulls.\n//!\n//!   - **Date:** October 21, 2015\n//!   - **Subject:** Enumerated (`enum`) types, pattern matc"
  },
  {
    "path": "src/e004.rs",
    "chars": 10233,
    "preview": "//! Functionalized\n//!\n//!   - **Date:** October 29, 2015\n//!   - **Subject:** Functions, methods, closures, and functio"
  },
  {
    "path": "src/e005.rs",
    "chars": 6599,
    "preview": "//! Allocate it where?\n//!\n//!   - **Date:** November 8, 2015\n//!   - **Subject:** Returning functions from other functi"
  },
  {
    "path": "src/e006.rs",
    "chars": 8265,
    "preview": "//! Modularize this!\n//!\n//!   - **Date:** November 16, 2015\n//!   - **Subject:** Designing APIs, and using packages (\"c"
  },
  {
    "path": "src/e007.rs",
    "chars": 6955,
    "preview": "//! Testify\n//!\n//!   - **Date:** December 13, 2015\n//!   - **Subject:** Testing and benchmarking, and compiler attribut"
  },
  {
    "path": "src/e008.rs",
    "chars": 8380,
    "preview": "//! Just like something else\n//!\n//!   - **Date:** 2015-12-27\n//!   - **Subject:** Generics, traits, and shared behavior"
  },
  {
    "path": "src/e009.rs",
    "chars": 7756,
    "preview": "//! Composing a Rustic tune\n//!\n//!   - **Date:** 2016-01-09\n//!   - **Subject:** Getting into the nitty-gritty with Rus"
  },
  {
    "path": "src/e010.rs",
    "chars": 8519,
    "preview": "//! Macros rule!\n//!\n//!   - **Date:** 2016-01-18\n//!   - **Subject:** Using Rust's macro system, its limitations, and i"
  },
  {
    "path": "src/e011.rs",
    "chars": 7543,
    "preview": "//! Once upon a type\n//!\n//!   - **Date:** March 6, 2016\n//!   - **Subject:** Type systems: strong vs. weak, dynamic vs."
  },
  {
    "path": "src/e012.rs",
    "chars": 6669,
    "preview": "//! I'm not familiar with that expression\n//!\n//!   - **Date:** March 21, 2016\n//!   - **Subject:** What it means to be "
  },
  {
    "path": "src/e013.rs",
    "chars": 5376,
    "preview": "/*!\n Staying alive\n\n - **Date:** April 4, 2016\n - **Subject:** Reasoning about and using lifetimes in Rust (and why we n"
  },
  {
    "path": "src/e014.rs",
    "chars": 6000,
    "preview": "//! Stringing things along\n//!\n//!   - **Date:** April 24, 2016\n//!   - **Subject:** `Strings` `&str`s and `Vec`s and sl"
  },
  {
    "path": "src/e015.rs",
    "chars": 8408,
    "preview": "//! Not dumb pointers.\n//!\n//!   - **Date:** June 17, 2016\n//!   - **Subject:** `Box`, `String`, `Vec`, `Rc`, and `Arc` "
  },
  {
    "path": "src/e016.rs",
    "chars": 9362,
    "preview": "//! `RefCell`s and code smells\n//!\n//!   - **Date:** July 23, 2016\n//!   - **Subject:** Digging deeper on smart pointers"
  },
  {
    "path": "src/e017.rs",
    "chars": 6217,
    "preview": "//! Point me where I need to go\n//!\n//!   - **Date:** August 5, 2016\n//!   - **Subject:** A deep dive on references and "
  },
  {
    "path": "src/e018.rs",
    "chars": 7032,
    "preview": "//! `Borrow`, `AsRef`, `Deref`: my head hurts now\n//!\n//!   - **Date:** January 31, 2017\n//!   - **Subject:** Three trai"
  },
  {
    "path": "src/e019.rs",
    "chars": 12103,
    "preview": "//! Let's `Clone` a `Cow`!\n//!\n//!   - **Date:** February 28, 2017\n//!   - **Subject:** The final pieces of the story fo"
  },
  {
    "path": "src/e020.rs",
    "chars": 3950,
    "preview": "//! Putting code in its place\n//!\n//!   - **Date:** April 1, 2017\n//!   - **Subject:** How do we organize code in Rust? "
  },
  {
    "path": "src/e021.rs",
    "chars": 8499,
    "preview": "//! Keeping your types under cover\n//!\n//!   - **Date:** July 17, 2017\n//!   - **Subject:** Using type aliases and creat"
  },
  {
    "path": "src/e022.rs",
    "chars": 7658,
    "preview": "//! `Send` and `Sync`\n//!\n//!   - **Date:** January 31, 2018\n//!   - **Subject:** The “marker traits” that Rust uses for"
  },
  {
    "path": "src/e023.rs",
    "chars": 8292,
    "preview": "//! Traits Deep Dive, Part 1\n//!\n//!   - **Date:** April 28, 2018\n//!   - **Subject:** Defining and using your own trait"
  },
  {
    "path": "src/e024.rs",
    "chars": 6640,
    "preview": "//! Traits Deep Dive, Part 2\n//!\n//!   - **Date:** June 19, 2018\n//!   - **Subject:** Operators as sugar for traits, tra"
  },
  {
    "path": "src/e025.rs",
    "chars": 7966,
    "preview": "//! Traits Deep Dive, Part 3\n//!\n//!   - **Date:** July 4, 2018\n//!   - **Subject:** Closure traits, `impl trait`, `dyn "
  },
  {
    "path": "src/e026.rs",
    "chars": 6148,
    "preview": "//! Functional Programming Ideas\n//!\n//!   - **Date:** July 24, 2018\n//!   - **Subject:** How Rust both borrows from FP "
  },
  {
    "path": "src/e027.rs",
    "chars": 8567,
    "preview": "//! Trust Me; I Promise!\n//!\n//! - **Date:** November 30, 2018\n//! - **Subject:** An intro to `unsafe` Rust and Rust's i"
  },
  {
    "path": "src/e028.rs",
    "chars": 8357,
    "preview": "//! Meet My Associates\n//!\n//! - **Date:** February 21, 2019\n//! - **Subject:** Associated items: functions and methods,"
  },
  {
    "path": "src/e029/ffi-demo.c",
    "chars": 166,
    "preview": "#include \"ffi-demo.h\"\n\nint add(int a, int b) {\n    return a + b;\n}\n\nvoid translate(Point * point, float byX, float byY) "
  },
  {
    "path": "src/e029/ffi-demo.h",
    "chars": 136,
    "preview": "int add(int a, int b);\n\ntypedef struct Point {\n    float x;\n    float y;\n} Point;\n\nvoid translate(Point * point, float b"
  },
  {
    "path": "src/e029/mod.rs",
    "chars": 13594,
    "preview": "//! I’m Out to C\n//!\n//! - **Date:** April 3, 2019\n//! - **Subject:** Using Rust’s Foreign Function Interface (FFI) with"
  },
  {
    "path": "src/e030.rs",
    "chars": 12059,
    "preview": "//! Can You See Me Now?\n//!\n//! - **Date:** April 26, 2019\n//! - **Subject:** Item visibility and `pub(<restricted>)` as"
  },
  {
    "path": "src/e031/e031.c",
    "chars": 4489,
    "preview": "#include <stdbool.h>\n#include <stdio.h>\n\n#include \"e031.h\"\n\nvoid section() { printf(\"\\n---\\n\\n\"); }\n\nint main() {\n    //"
  },
  {
    "path": "src/e031/e031.h",
    "chars": 1276,
    "preview": "/// The `add_in_rust` function exported by the Rust crate.\nextern int add_in_rust(int a, int b);\n\n/// The `concat_string"
  },
  {
    "path": "src/e031/mod.rs",
    "chars": 16686,
    "preview": "//! FFI Deep Dive\n//!\n//! - **Date:** May 11, 2019\n//! - **Subject:** Exposing Rust types and functions to C API consume"
  },
  {
    "path": "src/includes/media-playback-speed.html",
    "chars": 124,
    "preview": "<link rel=\"stylesheet\" href=\"/media-playback.css\">\n<script type=\"text/javascript\" src=\"/media-playback.js\" defer></scrip"
  },
  {
    "path": "src/interview/_1/mod.rs",
    "chars": 50,
    "preview": "//! Sean Griffin\n\npub mod part_1;\npub mod part_2;\n"
  },
  {
    "path": "src/interview/_1/part_1.rs",
    "chars": 3148,
    "preview": "//! Sean Griffin on Rust, ORMs, and Web Frameworks\n//!\n//!   - **Date:** February 15, 2016\n//!   - **Subject:** Rust, OR"
  },
  {
    "path": "src/interview/_1/part_2.rs",
    "chars": 3355,
    "preview": "//! Sean Griffin on type systems and hopes for Rust's future\n//!\n//!   - **Date:** February 25, 2016\n//!   - **Subject:*"
  },
  {
    "path": "src/interview/_2/mod.rs",
    "chars": 49,
    "preview": "//! Raph Levien\n\npub mod part_1;\npub mod part_2;\n"
  },
  {
    "path": "src/interview/_2/part_1.rs",
    "chars": 5153,
    "preview": "//! Raph Levien on using Rust to build the Xi editor\n//!\n//!   - **Date:** June 24, 2016\n//!   - **Subject:** The Xi Edi"
  },
  {
    "path": "src/interview/_2/part_2.rs",
    "chars": 3700,
    "preview": "//! Raph Levien on Rust's current strengths and places it can improve\n//!\n//!   - **Date:** July 4, 2016\n//!   - **Subje"
  },
  {
    "path": "src/interview/_3.rs",
    "chars": 6031,
    "preview": "//! Carol (Nichols || Goulding)\n//!\n//!   - **Date:** September 30, 2016\n//!   - **Subject:** Learning Rust, teaching Ru"
  },
  {
    "path": "src/interview/_4/mod.rs",
    "chars": 138,
    "preview": "//! Jonathan Turner\n//!\n//! Jonathan's history, his work on Rust, and his work on Servo.\n\npub mod part_1;\npub mod part_2"
  },
  {
    "path": "src/interview/_4/part_1.rs",
    "chars": 5070,
    "preview": "//! Part 1: Getting to Rust\n//!\n//!   - **Date:** April 30, 2017\n//!   - **Subject:** Background, TypeScript, coming to "
  },
  {
    "path": "src/interview/_4/part_2.rs",
    "chars": 5642,
    "preview": "//! Part 2: Making Rust Better\n//!\n//!   - **Date:** May 30, 2017\n//!   - **Subject:** Rust as the fusion of systems and"
  },
  {
    "path": "src/interview/_4/part_3.rs",
    "chars": 5251,
    "preview": "//! Part 3: Smoothing the Rust dev story\n//!\n//!   - **Date:** June 17, 2017\n//!   - **Subject:** Future work on the RLS"
  },
  {
    "path": "src/interview/diesel_1_0/mod.rs",
    "chars": 67,
    "preview": "//! Diesel 1.0, with Sean Griffin\n\npub mod part_1;\npub mod part_2;\n"
  },
  {
    "path": "src/interview/diesel_1_0/part_1.rs",
    "chars": 6193,
    "preview": "//! Part 1: The past and present of Diesel\n//!\n//!   - **Date:** January 13, 2018\n//!   - **Subject:** Growing Diesel's "
  },
  {
    "path": "src/interview/diesel_1_0/part_2.rs",
    "chars": 6525,
    "preview": "//! Part 2: The future of Diesel\n//!\n//!   - **Date:** January 21, 2018\n//!   - **Subject:** Getting Diesel to 1.0, writ"
  },
  {
    "path": "src/interview/integer32.rs",
    "chars": 7237,
    "preview": "//! Integer32: Carol Nichols || Goulding and Jake Goulding\n//!\n//! - **Date:** December 31, 2018\n//! - **Subject:** Talk"
  },
  {
    "path": "src/interview/irr_2017/anna_liao.rs",
    "chars": 5461,
    "preview": "//! Anna Liao\n//!\n//!   - **Date:** December 20, 2017\n//!   - **Subject:** Anna's experience learning Rust while porting"
  },
  {
    "path": "src/interview/irr_2017/lee_baillie.rs",
    "chars": 5285,
    "preview": "//! Lee Baillie\n//!\n//!   - **Date:** December 26, 2017\n//!   - **Subject:** Lee's experience designing a new website fo"
  },
  {
    "path": "src/interview/irr_2017/matt_gathu.rs",
    "chars": 5076,
    "preview": "//! Matt Gathu\n//!\n//!   - **Date:** December 30, 2017\n//!   - **Subject:** Matt's experience porting wget to Rust.\n//! "
  },
  {
    "path": "src/interview/irr_2017/mod.rs",
    "chars": 271,
    "preview": "//! Increasing Rust's Reach 2017\n//!\n//! For background on the Increasing Rust's Reach program, see [this blog post]!\n//"
  },
  {
    "path": "src/interview/mod.rs",
    "chars": 188,
    "preview": "//! Interviews: hearing from people around the Rust community!\n\npub mod _1;\npub mod _2;\npub mod _3;\npub mod _4;\n\npub mod"
  },
  {
    "path": "src/interview/rbr_2017/andrew_hobden.rs",
    "chars": 565,
    "preview": "//! Andrew Hobden\n//!\n//!   - **Date:** December 13, 2017 (recorded October 27, 2017)\n//!   - [**Audio**][mp3]\n//!\n//! ["
  },
  {
    "path": "src/interview/rbr_2017/anthony_deschamps.rs",
    "chars": 586,
    "preview": "//! Anthony Deschamps\n//!\n//!   - **Date:** November 13, 2017 (recorded October 27, 2017)\n//!   - [**Audio**][mp3]\n//!\n/"
  },
  {
    "path": "src/interview/rbr_2017/arun_kulshreshthra.rs",
    "chars": 588,
    "preview": "//! Arun Kulshreshtha\n//!\n//!   - **Date:** November 14, 2017 (recorded October 27, 2017)\n//!   - [**Audio**][mp3]\n//!\n/"
  },
  {
    "path": "src/interview/rbr_2017/ben_beckwith.rs",
    "chars": 473,
    "preview": "//! Ben Beckwith\n//!\n//!   - **Date:** December 14, 2017 (recorded October 27, 2017)\n//!   - [**Audio**][mp3]\n//!\n//! [m"
  },
  {
    "path": "src/interview/rbr_2017/ben_striegel.rs",
    "chars": 561,
    "preview": "//! Ben Striegel\n//!\n//!   - **Date:** December 10, 2017 (recorded October 27, 2017)\n//!   - [**Audio**][mp3]\n//!\n//! [m"
  },
  {
    "path": "src/interview/rbr_2017/colin_dean.rs",
    "chars": 551,
    "preview": "//! Colin Dean\n//!\n//!   - **Date:** November 11, 2017 (recorded October 27, 2017)\n//!   - [**Audio**][mp3]\n//!\n//! [mp3"
  },
  {
    "path": "src/interview/rbr_2017/esty_thomas.rs",
    "chars": 468,
    "preview": "//! Esty Thomas\n//!\n//!   - **Date:** December 7, 2017 (recorded October 27, 2017)\n//!   - [**Audio**][mp3]\n//!\n//! [mp3"
  },
  {
    "path": "src/interview/rbr_2017/holden_marcsisin.rs",
    "chars": 581,
    "preview": "//! Holden Marcsisin\n//!\n//!   - **Date:** December 9, 2017 (recorded October 27, 2017)\n//!   - [**Audio**][mp3]\n//!\n//!"
  }
]

// ... and 33 more files (download for full content)

About this extraction

This page contains the full source code of the chriskrycho/newrustacean.com GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 233 files (2.0 MB), approximately 541.1k tokens, and a symbol index with 297 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!