[
  {
    "path": ".circleci/config.yml",
    "content": "version: 2\n\n.template:\n  test: &cargo-test\n    docker:\n      - image: circleci/rust:1.32.0\n    steps:\n      - checkout\n      - restore_cache:\n          key: cargo-cache-1.32.0\n      - run: rustc --version --verbose\n      - run: cargo --version --verbose\n      - run: |\n          echo $WORK_DIR;\n          cd $WORK_DIR;\n          cargo clean;\n          cargo test\n          cargo test --examples\n      - save_cache:\n          key: cargo-cache\n          paths:\n            - \"~/.cargo\"\n\n\njobs:\n  ch02/hello:\n    <<: *cargo-test\n    environment:\n      - WORK_DIR: ch02/hello\n\n  ch02/ex02:\n    <<: *cargo-test\n    environment:\n      - WORK_DIR: ch02/ex02\n\n  ch02/rpn:\n    <<: *cargo-test\n    environment:\n      - WORK_DIR: ch02/rpn\n\n  ch03/bitonic-sorter:\n    <<: *cargo-test\n    environment:\n      - WORK_DIR: ch03/bitonic-sorter\n\n  ch04/ex04:\n    <<: *cargo-test\n    environment:\n      - WORK_DIR: ch04/ex04\n\n  ch05/ex05:\n    <<: *cargo-test\n    environment:\n      - WORK_DIR: ch05/ex05\n\n  ch06/leap-year:\n    <<: *cargo-test\n    environment:\n      - WORK_DIR: ch06/leap-year\n\n  ch07/ex07:\n    <<: *cargo-test\n    environment:\n      - WORK_DIR: ch07/ex07\n\n  ch07/toy-vec:\n    <<: *cargo-test\n    environment:\n      - WORK_DIR: ch07/toy-vec\n\n  ch08/ex08:\n    <<: *cargo-test\n    environment:\n      - WORK_DIR: ch08/ex08\n\n  ch08/Overload:\n    docker:\n      - image: circleci/openjdk:11\n    steps:\n      - checkout\n      - run: javac -version\n      - run:\n          name: test ch08/ex08/examples-java/Overload.java\n          command: |\n            javac Overload.java\n            java Overload\n          working_directory: ch08/ex08/examples-java/\n\n  # TODO: Add an integration test for the bin target.\n  ch09/parser:\n    <<: *cargo-test\n    environment:\n      - WORK_DIR: ch09/parser\n\n  ch10/wordcount:\n    <<: *cargo-test\n    environment:\n      - WORK_DIR: ch10/wordcount\n\n  # TODO: Add an integration test for the bin target.\n  ch11/log-collector:\n    <<: *cargo-test\n    environment:\n      - WORK_DIR: ch11/log-collector\n\n  # TODO: Add an integration test for the bin target.\n  ch11/start-aw:\n    <<: *cargo-test\n    environment:\n      - WORK_DIR: ch11/start-aw\n\n  # TODO: Add an integration test for the bin target.\n  ch11/static-files:\n    <<: *cargo-test\n    environment:\n      - WORK_DIR: ch11/static-files\n\n  # TODO: Add an integration test for the bin target.\n  ch11/templates:\n    <<: *cargo-test\n    environment:\n      - WORK_DIR: ch11/templates\n\n  # TODO: Add an integration test for the bin target.\n  ch12/c-api:\n    <<: *cargo-test\n    environment:\n      - WORK_DIR: ch12/c-api\n\n  # TODO: Add an integration test for the bin target.\n  ch12/cffi-ownership:\n    <<: *cargo-test\n    environment:\n      - WORK_DIR: ch12/cffi-ownership\n\n  # TODO: Add an integration test for the bin target.\n  ch12/ffi-global:\n    <<: *cargo-test\n    environment:\n      - WORK_DIR: ch12/ffi-global\n\n  ch12/onigmo:\n    docker:\n      - image: circleci/rust:1.32.0\n    steps:\n      - checkout\n      - restore_cache:\n          key: cargo-cache\n\n      - run: rustc --version --verbose\n      - run: cargo --version --verbose\n      - run:\n          name: install onigmo 6.1.3\n          command: |\n            sudo apt-get install -y curl make;\n            curl -L -O https://github.com/k-takata/Onigmo/archive/Onigmo-6.1.3.tar.gz\n            tar xf Onigmo-*.tar.gz\n            cd Onigmo-O*\n            ./configure\n            make\n            sudo make install\n          working_directory: /tmp/onigmo-build\n      - run:\n          name: install libclang for bindgen, clang for stddef.h\n          command: |\n            sudo apt-get install libclang-dev clang\n      - run:\n          name: test onigmo-sys\n          command: |\n              cargo clean;\n              cargo test --all-targets\n          working_directory: ch12/onigmo-rs/onigmo-sys\n      - run:\n          name: test onigmo\n          command: |\n              cargo clean;\n              cargo test --all-targets\n          working_directory: ch12/onigmo-rs/onigmo\n      - save_cache:\n          key: cargo-cache\n          paths:\n            - \"~/.cargo\"\n\n\n  # TODO: Add an integration test for the bin target.\n  ch12/opaque:\n    <<: *cargo-test\n    environment:\n      - WORK_DIR: ch12/opaque\n\n  # TODO: Add an integration test for the bin target.\n  ch12/repr-c:\n    <<: *cargo-test\n    environment:\n      - WORK_DIR: ch12/repr-c\n\n  # TODO: Add an integration test for the bin target.\n  ch12/static-link:\n    <<: *cargo-test\n    environment:\n      - WORK_DIR: ch12/static-link\n\n  # TODO: Add an integration test for the bin target.\n  ch12/cffi-readline:\n    docker:\n      - image: circleci/rust:1.32.0\n    steps:\n      - checkout\n      - restore_cache:\n          key: cargo-cache\n\n      - run: rustc --version --verbose\n      - run: cargo --version --verbose\n      - run:\n          name: test ch12/cffi_readline.rs\n          command: |\n              rustc --test cffi_readline.rs\n              ./cffi_readline\n          working_directory: ch12/\n      - save_cache:\n          key: cargo-cache\n          paths:\n            - \"~/.cargo\"\n\n  # TODO: Add an integration test for the bin target.\n  ch12/ptr_ownership:\n    docker:\n      - image: circleci/rust:1.32.0\n    steps:\n      - checkout\n      - restore_cache:\n          key: cargo-cache\n      - run:\n          name: test ch12/ptr_ownership.rs\n          command: |\n              rustc --test ptr_ownership.rs\n              ./ptr_ownership\n          working_directory: ch12/\n      - run: rustc --version --verbose\n      - run: cargo --version --verbose\n      - save_cache:\n          key: cargo-cache\n          paths:\n            - \"~/.cargo\"\n\n  # TODO: Add an integration test for the bin target.\n  ch12/smal_-cffi:\n    docker:\n      - image: circleci/rust:1.32.0\n    steps:\n      - checkout\n      - restore_cache:\n          key: cargo-cache\n      - run:\n          name: test ch12/small_cffi\n          command: |\n              rustc --test small_cffi.rs\n              ./small_cffi\n          working_directory: ch12/\n      - run: rustc --version --verbose\n      - run: cargo --version --verbose\n      - save_cache:\n          key: cargo-cache\n          paths:\n            - \"~/.cargo\"\n\nworkflows:\n  version: 2\n  build_and_test:\n    jobs:\n      - ch02/hello\n      - ch02/ex02\n      - ch02/rpn\n      - ch03/bitonic-sorter\n      - ch04/ex04\n      - ch05/ex05\n      - ch06/leap-year\n      - ch07/ex07\n      - ch07/toy-vec\n      - ch08/ex08\n      - ch08/Overload\n      - ch09/parser\n      - ch10/wordcount\n      - ch11/log-collector\n      - ch11/start-aw\n      - ch11/static-files\n      - ch11/templates\n      - ch12/c-api\n      - ch12/cffi-ownership\n      - ch12/ffi-global\n      - ch12/onigmo\n      - ch12/opaque\n      - ch12/repr-c\n      - ch12/static-link\n      - ch12/cffi-readline\n      - ch12/ptr_ownership\n      - ch12/smal_-cffi\n"
  },
  {
    "path": ".gitignore",
    "content": "# Visual Studio Codeの設定ファイルが置かれる\n.vscode/\n\n# rustfmtが作成するバックアップファイル\n*.rs.bk\n\n# Emacsが作成するバックアップファイル\n*~\n\n# macOSのFinderが作成する管理ファイル\n.DS_Store\n"
  },
  {
    "path": "LICENSE",
    "content": "BSD 3-Clause License\n\nCopyright (c) 2019, ghmagazine\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n1. Redistributions of source code must retain the above copyright notice, this\n   list of conditions and the following disclaimer.\n\n2. Redistributions in binary form must reproduce the above copyright notice,\n   this list of conditions and the following disclaimer in the documentation\n   and/or other materials provided with the distribution.\n\n3. Neither the name of the copyright holder nor the names of its\n   contributors may be used to endorse or promote products derived from\n   this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\nAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\nFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\nOR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
  },
  {
    "path": "README.md",
    "content": "# 『実践Rust入門』のサンプルプログラム\n\n**実践Rust入門**</br>\n[言語仕様から開発手法まで]</br></br>\nκeen(著)、河野達也(著)、小松礼人(著)</br>\nB5判／576ページ／本体価格3,980円＋税</br>\nISBN番号 978-4-297-10559-4</br>\n技術評論社、2019年5月8日発行\n\n## サンプルプログラム\n\n本GitHubリポジトリでは『**実践Rust入門**』（以降 **本書**）に掲載されているサンプルプログラムを収録しています。\n本書の各章に対応する`ch章番号`ディレクトリを参照してください。\n\n### ダウンロード方法\n\n[リリースページ][releases-page] にある`*.zip`または`*.tar.gz`のアーカイブファイルをダウンロード後、解凍してください。\nどちらのアーカイブも内容は同じです。\nWindowsとmacOSをお使いなら`*.zip`を、Linuxをお使いなら`*.tar.gz`をダウンロードすることをお勧めします。\n\nそれぞれのリリースの内容については [RELEASES.mdファイル][releases-md] を参照してください。\n\n[releases-page]: https://github.com/ghmagazine/rustbook/releases\n[releases-md]: ./RELEASES.md\n\n### 改行文字について\n\nソースファイルの改行文字はLinuxやmacOS環境で使用されている`LF`文字になります。Windows環境ではアプリケーションによっては正しく改行されないかもしれません。2章を参考に、Visual Studio Code（VS Code）などのソースコードエディタを使われることをお勧めします。\n\n## 本書で使用する追加ソフトウェアについて\n\n### インストール方法\n\n本書で使用する追加ソフトウェアのインストール方法については以下を参考にしてください。\n\n- [DockerとDocker Composeのインストール][docker]（11章で使用）\n- Windows MSVC：[vcpkgパッケージマネージャのインストール][vcpkg]（11章で使用）\n\n[docker]: ./install/docker.md\n[vcpkg]: ./install/windows10-vcpkg.md\n\nなお、Rustツールチェインとリンカのインストール方法については本書の2章を参照してください。\n\n### 使いかたなど\n\n追加ソフトウェアの使いかたについては以下を参考にしてください。\n\n- Windows MSVC：[C/C++コンパイラをコマンドプロンプトから実行する方法][msvc-compiler]（12章で使用）\n\n[msvc-compiler]: ./howto/running-msvc-compiler.md\n\n## 動作確認の環境について\n\nサンプルプログラムは以下のRust/OSバージョンにて動作確認済みです。\n\n- Rust 1.32.0（2019年1月16日リリース）\n  * 2018 Editionを指定\n- x86-64系のプロセッサで動作する以下のOS\n  * Ubuntu \"Bionic\" 18.04 LTS（64ビット）\n  * macOS Mojave 10.14\n  * Windows 10 （64ビット、Microsoft Visual C++ 2017）\n\n## ご質問や不具合報告など\n\n本書やサンプルプログラムの内容についてご質問などあるときは、以下の方法でご確認・ご連絡ください。\n\n- [本書の公式サポートページの正誤表][errata] で報告・訂正されていないかご確認\n- Slack **rust-jp**チームの `#rust-bicycle-book` チャネルで著者らに質問\n  * 参加登録URL： http://rust-jp.herokuapp.com/\n- [本書の公式サポートページのお問い合わせフォーム][inquiry-form] で編集部へお問い合わせ\n- サンプルプログラムの明らかなバグなら、本リポジトリの [issueページ][gh-issues] で直接ご報告いただいても構いません。（その場合でもSlackなどでご一報いただいてからの方がスムーズに対応できるかもしれません）\n\n[errata]: https://gihyo.jp/book/2019/978-4-297-10559-4/support\n[inquiry-form]: https://gihyo.jp/site/inquiry/book?ISBN=978-4-297-10559-4\n[gh-issues]: https://github.com/ghmagazine/rustbook/issues\n\n## 本書の書籍案内ページ\n\nhttps://gihyo.jp/book/2019/978-4-297-10559-4\n\n本書の概要や目次、正誤表などが掲載されています。\n\n## ライセンス\n\n本リポジトリのコンテンツは特に断り書きがない限り **三条項BSDライセンス** のもとで公開されています。\n\n- https://github.com/ghmagazine/rustbook/blob/master/LICENSE\n\n以下のディレクトリ配下のコンテンツは異なるライセンスで公開されています。\n\n- `ch10/wordcount`： **MIT** と **Apache-2.0** のデュアルライセンス\n"
  },
  {
    "path": "RELEASES.md",
    "content": "# 1.0.0 (2019-04-24)\n\n* サンプルプログラムの初版を公開\n* サンプルプログラムの内容は以下を除いて書籍の**初版**に掲載されているものと同等\n  * `ch12/onigmo-rs/onigmo-sys/build.rs`：`bindgen_test_layout_max_align_t`のテスト失敗を防ぐためにRust 1.28.0以上向けにコードを生成するよう修正（[diff][v1-0-0-onigmo-sys-build-diff]）\n  * 書籍2-2-7項に掲載されている`ch02/examples/bin/println.rs`のファイルパスを、他の章のファイルのネーミングルールに合わせて[`ch02/ex02/examples/println.rs`][v1-0-0-ex02-println]に変更\n\n[v1-0-0-onigmo-sys-build-diff]: https://github.com/ghmagazine/rustbook/commit/9bebf5b7c2a5f9f8a74323aa9613808f2aa2897b\n[v1-0-0-ex02-println]: ./ch02/ex02/examples/println.rs\n"
  },
  {
    "path": "ch02/ex02/.gitignore",
    "content": "# Cargoが選択した依存ライブラリのバージョン郡\nCargo.lock\n\n# コンパイラが生成する成果物や中間ファイルが置かれる\ntarget/\n"
  },
  {
    "path": "ch02/ex02/Cargo.toml",
    "content": "[package]\nname = \"ex02\"\nversion = \"0.1.0\"\nauthors = [\"Rust Bicycle Book <bicycle-book@example.com>\"]\nedition = \"2018\"\n\n[dependencies]\n\n[dev-dependencies]\ncli_test_dir = \"0.1\"\n"
  },
  {
    "path": "ch02/ex02/examples/println.rs",
    "content": "fn main() {\n    // 引数としてフォーマット文字列と1つの文字列を受け取る\n    println!(\n        \"Hello, {}!\",\n        \"Takashi\",\n    );\n    // → 実行すると「Hello, Takashi!」と表示される\n\n    // 引数としてフォーマット文字列と3つの数値を受け取る\n    println!(\n        // {:.1}で小数点以下1桁まで表示\n        \"半径 {:.1}、円周率 {:.3}、面積 {:.3}\",\n        3.2,\n        std::f64::consts::PI,\n        // 半径の自乗 × 円周率\n        3.2f64.powi(2) * std::f64::consts::PI,\n    );\n    // → 実行すると「半径 3.2、円周率 3.142、面積 32.170」と表示される\n}\n"
  },
  {
    "path": "ch02/ex02/tests/integration_tests.rs",
    "content": "use cli_test_dir::*;\n\n// バイナリを実行して入出力を確認するテスト\n// `cargo test` で実行できる\n\nconst CMD: &'static str = \"./examples/println\";\n\n#[test]\nfn verify_output() {\n    let testdir = TestDir::new(CMD, \"Verify output\");\n    let output = testdir\n        .cmd()\n        // .tee_output()   // stdoutとstderrorを順に表示する。デバッグに便利\n        .expect_success();\n    assert_eq!(\n        output.stdout_str(),\n        r#\"Hello, Takashi!\n半径 3.2、円周率 3.142、面積 32.170\n\"#\n    );\n}\n"
  },
  {
    "path": "ch02/examples/README.md",
    "content": "# 可変個引数の例について\n\n**2019年4月22日**\n\n本書 初版 第2章 2-2-7項で`println!`マクロの可変個引数のコード例が紹介されていますが、ディレクトリ名とファイル名に誤りがありましたので、訂正いたします。\n\n- 誤：`ch02/examples/bin/println.rs`\n- 正：[`ch02/ex02/examples/println.rs`][ex02-println]\n\n正しい方のファイルをご覧ください。\n\n[ex02-println]: ../ex02/examples/println.rs\n"
  },
  {
    "path": "ch02/hello/.gitignore",
    "content": "# コンパイラが生成する成果物や中間ファイルが置かれる\ntarget/\n"
  },
  {
    "path": "ch02/hello/Cargo.toml",
    "content": "[package]             # パッケージセクションの始まり\nname = \"hello\"        # 名前\nversion = \"0.1.0\"     # バージョン\nauthors = [\"Rust Bicycle Book <bicycle-book@example.com>\"]  # 作者（複数指定可）\nedition = \"2018\"      # エディション\n\n[dependencies]        # 依存クレートセクションの始まり（いまは空）\n\n[dev-dependencies]    # ビルド時のみ必要な依存クレートセクションの始まり\ncli_test_dir = \"0.1\"  # 結合テスト（tests/integration_tests.rs）が必要とするクレート\n"
  },
  {
    "path": "ch02/hello/src/main.rs",
    "content": "// エントリポイントとなる関数\nfn main() {\n    // println!はマクロ。stdout（標準出力）に\"Hello, world!\"と出力する\n    println!(\"Hello, world!\");\n}\n"
  },
  {
    "path": "ch02/hello/tests/integration_tests.rs",
    "content": "use cli_test_dir::*;\n\n// バイナリを実行して入出力を確認するテスト\n// `cargo test` で実行できる\n\n#[test]\nfn run_hello() {\n    let testdir = TestDir::new(\"./hello\", \"Run hello\");\n    let output = testdir\n        .cmd()\n        // .tee_output()    // stdoutとstderrorを順に表示する。デバッグに便利\n        .expect_success();\n    assert_eq!(output.stdout_str(), \"Hello, world!\\n\");\n    assert!(output.stderr_str().is_empty());\n}\n"
  },
  {
    "path": "ch02/rpn/.gitignore",
    "content": "# コンパイラが生成する成果物や中間ファイルが置かれる\ntarget/\n"
  },
  {
    "path": "ch02/rpn/Cargo.toml",
    "content": "[package]\nname = \"rpn\"\nversion = \"0.1.0\"\nauthors = [\"Rust Bicycle Book <bicycle-book@example.com>\"]\nedition = \"2018\"\n\n[dependencies]\n\n[dev-dependencies]\ncli_test_dir = \"0.1\"\n"
  },
  {
    "path": "ch02/rpn/src/main.rs",
    "content": "fn main() {\n    // 変数expをRPN形式の文字列に束縛する\n    // このRPNは数式 6.1 + 5.2 * 4.3 - 3.4 / 2.5 * 1.6 と等しい\n    let exp = \"6.1 5.2 4.3 * + 3.4 2.5 / 1.6 * -\";\n\n    // rpn関数を呼び出して計算する。返された値にans変数を束縛する\n    let ans = rpn(exp);\n\n    // デバッグビルド時のみ、答えが正しいかチェックする\n    // 浮動小数点の計算誤差を考慮し、ここでは小数点以下4桁までの値を文字列に変換している\n    debug_assert_eq!(\"26.2840\", format!(\"{:.4}\", ans));\n\n    // expとansの値を表示する。ansは小数点以下4桁まで表示する\n    println!(\"{} = {:.4}\", exp, ans);\n}\n\n// RPN形式の文字列expを受け取り、f64型の計算結果を返す\nfn rpn(exp: &str) -> f64 {\n    // 変数stackを空のスタックに束縛する\n    // stackはミュータブル（mutable、可変）の変数で、値の変更を許す\n    let mut stack = Vec::new();\n\n    // expの要素をスペースで分割し、tokenをそれらに順に束縛する\n    // 要素がなくなるまで繰り返す\n    for token in exp.split_whitespace() {\n        // tokenがf64型の数値ならスタックに積む\n        if let Ok(num) = token.parse::<f64>() {\n            stack.push(num);\n        } else {\n            // tokenが数値でないなら、演算子なのか調べる\n            match token {\n                // tokenが演算子ならapply2関数で計算する\n                // |x, y| x + y はクロージャ\n                // 引数x、yを取り、x + yを計算して答えを返す\n                \"+\" => apply2(&mut stack, |x, y| x + y),\n                \"-\" => apply2(&mut stack, |x, y| x - y),\n                \"*\" => apply2(&mut stack, |x, y| x * y),\n                \"/\" => apply2(&mut stack, |x, y| x / y),\n\n                // tokenが演算子でないなら、エラーを起こして終了する\n                _ => panic!(\"Unknown operator: {}\", token),\n            }\n        }\n    }\n    // スタックから数値を1つ取り出す。失敗したらエラーを起こして終了する\n    stack.pop().expect(\"Stack underflow\")\n}\n\n// スタックから数値を2つ取り出し、F型のクロージャfunで計算し、結果をスタックに積む\nfn apply2<F>(stack: &mut Vec<f64>, fun: F)\n// F型のトレイト境界。本文参照\nwhere\n    F: Fn(f64, f64) -> f64,\n{\n    // 変数yとxをスタックの最後の2要素に束縛する\n    if let (Some(y), Some(x)) = (stack.pop(), stack.pop()) {\n        // クロージャfunで計算し、その結果に変数zを束縛する。\n        let z = fun(x, y);\n        // 変数zの値をスタックに積む\n        stack.push(z);\n    } else {\n        // スタックから要素が取り出せなかったときはエラーを起こして終了する\n        panic!(\"Stack underflow\");\n    }\n}\n"
  },
  {
    "path": "ch02/rpn/tests/integration_tests.rs",
    "content": "use cli_test_dir::*;\n\n// バイナリを実行して入出力を確認するテスト\n// `cargo test` で実行できる\n\n#[test]\nfn run_rpn() {\n    let testdir = TestDir::new(\"./rpn\", \"Run rpn\");\n    let output = testdir\n        .cmd()\n        // .tee_output()    // stdoutとstderrorを順に表示する。デバッグに便利\n        .expect_success();\n    assert_eq!(output.stdout_str(), \"6.1 5.2 4.3 * + 3.4 2.5 / 1.6 * - = 26.2840\\n\");\n    assert!(output.stderr_str().is_empty());\n}\n"
  },
  {
    "path": "ch03/bitonic-sorter/.gitignore",
    "content": "# コンパイラが生成する成果物や中間ファイルが置かれる\ntarget/\n"
  },
  {
    "path": "ch03/bitonic-sorter/Cargo.toml",
    "content": "[package]\nname = \"bitonic-sorter\"\nversion = \"0.1.0\"\nauthors = [\"Rust Bicycle Book <bicycle-book@example.com>\"]\nedition = \"2018\"\n\n[dependencies]\nnum_cpus = \"1.8\"\nrand = \"0.6\"\nrand_pcg = \"0.1\"\nrayon = \"1.0\"\n\n[dev-dependencies]\ncli_test_dir = \"0.1\"\nregex = \"1\"\n"
  },
  {
    "path": "ch03/bitonic-sorter/examples/benchmark.rs",
    "content": "use num_cpus;\n\nuse bitonic_sorter::SortOrder;\n// 第3段階のsort関数をseq_sortという別名で使用する\nuse bitonic_sorter::third::sort as seq_sort;\n// 第4段階のsort関数をpar_sortという別名で使用する\nuse bitonic_sorter::fourth::sort as par_sort;\nuse bitonic_sorter::utils::{is_sorted_ascending, new_u32_vec};\n\nuse std::{env, f64};\nuse std::str::FromStr;\nuse std::time::Instant;\n\nfn main() {\n    // 1つ目のコマンドライン引数を文字列として取得する\n    if let Some(n) = env::args().nth(1) {\n        // 文字列型からu32型への変換を試み、成功したらbitsに束縛する\n        // もし失敗したならエラーを起こして終了する\n        let bits = u32::from_str(&n).expect(\"error parsing argument\");\n        // 順次ソートと並列ソートを実行する\n        run_sorts(bits);\n    } else {\n        // コマンドライン引数が指定されてなかったらヘルプメッセージを表示して\n        // ステータスコード1で終了する\n        eprintln!(\n            \"Usage {} <number of elements in bits>\",\n            env::args().nth(0).unwrap()\n        );\n        std::process::exit(1);\n    }\n}\n\nfn run_sorts(bits: u32) {\n    // 指定されたビット数からデータの要素数を求める\n    // 例：\n    // 28ビット → 要素数 268,435,456\n    // 26ビット → 要素数  67,108,864\n    let len = 2.0_f64.powi(bits as i32) as usize;\n\n    // ソートする要素数とデータの見積もりサイズを表示する\n    println!(\n        \"sorting {} integers ({:.1} MB)\",\n        len,\n        (len * std::mem::size_of::<u32>()) as f64 / 1024.0 / 1024.0\n    );\n\n    // プロセッサの物理コア数と論理コア数を表示する\n    println!(\n        \"cpu info: {} physical cores, {} logical cores\",\n        num_cpus::get_physical(),\n        num_cpus::get()\n    );\n\n    // 順次ソートを実行して、処理にかかった時間を得る\n    let seq_duration = timed_sort(&seq_sort, len, \"seq_sort\");\n\n    // 並列ソートを実行して、処理にかかった時間を得る\n    let par_duration = timed_sort(&par_sort, len, \"par_sort\");\n\n    // 並列ソートが順次ソートに対して何倍速かったのか表示する\n    println!(\"speed up: {:.2}x\", seq_duration / par_duration);\n}\n\nfn timed_sort<F>(sorter: &F, len: usize, name: &str) -> f64\nwhere\n    F: Fn(&mut [u32], &SortOrder) -> Result<(), String>,\n{\n    // 要素数lenのu32型ベクタを生成する\n    let mut x = new_u32_vec(len);\n\n    // sorter関数を呼び出すことで、ソートを実行する\n    // かかった時間（dur）を記録する\n    let start = Instant::now();\n    sorter(&mut x[..], &SortOrder::Ascending).expect(\"Failed to sort: \");\n    let dur = start.elapsed();\n\n    // ソートした要素数とかかった時間（秒）を表示する\n    let nano_secs = dur.subsec_nanos() as f64 + dur.as_secs() as f64 * 1e9_f64;\n    println!(\n        \"{}: sorted {} integers in {} seconds\",\n        name,\n        len,\n        nano_secs / 1e9\n    );\n\n    // ソート結果が正しいか検証する\n    assert!(is_sorted_ascending(&x[..]));\n\n    nano_secs\n}\n"
  },
  {
    "path": "ch03/bitonic-sorter/py-src/.gitignore",
    "content": "*.pyc\n"
  },
  {
    "path": "ch03/bitonic-sorter/py-src/bitonic_sorter.py",
    "content": "# -*- coding:utf-8-unix -*-\nu\"Bitonic Merge Sortモジュール。\"\n\n# Pythonによるsort関数\ndef sort(x, up):\n    u\"\"\"\n    リストxの要素を、upで指定された向きにソートする。upがTrueなら昇順、\n    Falseなら降順になる。xの要素数は2のべき乗でなければならない\n    （さもなければソート結果がおかしくなる）\n    \"\"\"\n    if len(x) <= 1:\n        # 要素数が1以下になったら終わり\n        return x\n    else:\n        # ステップ1a\n        # リストの前半（first）は昇順、後半（second）は降順でソートする\n        mid_point = len(x) // 2        # `//`は整数除算\n        first = sort(x[:mid_point], True)\n        second = sort(x[mid_point:], False)\n\n        # ステップ1b\n        # 2分割したリストを1つに結合する\n        x1 = first + second\n\n        # ステップ2：サブソートに進む\n        return _sub_sort(x1, up)\n\ndef _sub_sort(x, up):\n    u\"\"\"\n    バイトニックにソートされたリストxの前半と後半を、upで指定された向きに\n    比較、交換し、前半と後半それぞれについて再帰的にサブソートを適用する\n    \"\"\"\n    if len(x) == 1:\n        # 要素数が1以下になったら終わり\n        return x\n    else:\n        # ステップ2a\n        # 要素数nのバイトニック列の要素をn/2要素おきに比較して\n        # upで指定された順序（昇順または降順）になるように交換する\n        _compare_and_swap(x, up)\n\n        # ステップ2b\n        # データ列を半分に分割し、それぞれに対して_sub_sortを繰り返す\n        mid_point = len(x) // 2\n        first = _sub_sort(x[:mid_point], up)\n        second = _sub_sort(x[mid_point:], up)\n\n        # ステップ2c\n        # 2分割したデータ列を1つに結合する\n        return first + second\n\ndef _compare_and_swap(x, up):\n    u\"\"\"\n    要素数nのバイトニック列の要素をn/2要素おきに比較して、upで指定された\n    順序（昇順または降順）になるよう交換する（ステップ2a）\n    \"\"\"\n    mid_point = len(x) // 2\n    for i in range(mid_point):\n        if (x[i] > x[mid_point + i]) == up:\n            # 要素を交換する\n            x[i], x[mid_point + i] = x[mid_point + i], x[i]\n"
  },
  {
    "path": "ch03/bitonic-sorter/src/first.rs",
    "content": "// pubはこのsort関数が他のモジュールからアクセスできることを示す\n// 引数xの型 `&mut [u32]` について\n//   &は値をポインタ経由で借用することを示す（借用については7章で説明）\n//   mutは値が変更可能であることを示す\n//   u32型は32ビット符号なし整数\n//   [u32]型はu32のスライス（現時点でスライスは1次元の配列と考えてよい）\npub fn sort(x: &mut [u32], up: bool) {\n    if x.len() > 1 {\n        let mid_point = x.len() / 2;\n        sort(&mut x[..mid_point], true);\n        sort(&mut x[mid_point..], false);\n        sub_sort(x, up);\n    }\n}\n\nfn sub_sort(x: &mut [u32], up: bool) {\n    if x.len() > 1 {\n        compare_and_swap(x, up);\n        let mid_point = x.len() / 2;\n        sub_sort(&mut x[..mid_point], up);\n        sub_sort(&mut x[mid_point..], up);\n    }\n}\n\nfn compare_and_swap(x: &mut [u32], up: bool) {\n    let mid_point = x.len() / 2;\n    for i in 0..mid_point {\n        if (x[i] > x[mid_point + i]) == up {\n            // 要素を交換する\n            x.swap(i, mid_point + i);\n        }\n    }\n}\n\n// このモジュールはcargo testを実行したときのみコンパイルされる\n#[cfg(test)]\nmod tests {\n    // 親モジュール（first）のsort関数を使用する\n    use super::sort;\n\n    // #[test]の付いた関数はcargo testとしたときに実行される\n    #[test]\n    fn sort_u32_ascending() {\n        // テストデータとしてu32型のベクタを作成しxに束縛する\n        // sort関数によって内容が更新されるので、可変を表すmutキーワードが必要\n        let mut x = vec![10, 30, 11, 20, 4, 330, 21, 110];\n\n        // xのスライスを作成し、sort関数を呼び出す\n        // `&mut x`は`&mut x[..]`と書いてもいい\n        sort(&mut x, true);\n\n        // xの要素が昇順にソートされていることを確認する\n        assert_eq!(x, vec![4, 10, 11, 20, 21, 30, 110, 330]);\n    }\n\n    #[test]\n    fn sort_u32_descending() {\n        let mut x = vec![10, 30, 11, 20, 4, 330, 21, 110];\n        sort(&mut x, false);\n        // xの要素が降順にソートされていることを確認する\n        assert_eq!(x, vec![330, 110, 30, 21, 20, 11, 10, 4]);\n    }\n}\n"
  },
  {
    "path": "ch03/bitonic-sorter/src/fourth.rs",
    "content": "use super::SortOrder;\nuse rayon;\nuse std::cmp::Ordering;\n\n// 並列に処理するかを決める、しきい値\nconst PARALLEL_THRESHOLD: usize = 4096;\n\npub fn sort<T: Ord + Send>(x: &mut [T], order: &SortOrder) -> Result<(), String> {\n    match *order {\n        SortOrder::Ascending  => sort_by(x, &|a, b| a.cmp(b)),\n        SortOrder::Descending => sort_by(x, &|a, b| b.cmp(a)),\n    }\n}\n\npub fn sort_by<T, F>(x: &mut [T], comparator: &F) -> Result<(), String>\n    where T: Send,\n          F: Sync + Fn(&T, &T) -> Ordering\n{\n    if x.len().is_power_of_two() {\n        do_sort(x, true, comparator);\n        Ok(())\n    } else {\n        Err(format!(\"The length of x is not a power of two. (x.len(): {})\", x.len()))\n    }\n}\n\nfn do_sort<T, F>(x: &mut [T], forward: bool, comparator: &F)\n    where T: Send,\n          F: Sync + Fn(&T, &T) -> Ordering\n{\n    if x.len() > 1 {\n        let mid_point = x.len() / 2;\n        // xをmid_pointを境にした2つの可変の借用に分割し\n        // firstとsecondに束縛する\n        let (first, second) = x.split_at_mut(mid_point);\n        // xの分割後の要素数をしきい値（PARALLEL_THRESHOLD）と比較する\n        if mid_point >= PARALLEL_THRESHOLD {\n            // しきい値以上なら並列にソートする（並列処理）\n            rayon::join(|| do_sort(first, true, comparator),\n                        || do_sort(second, false, comparator));\n        } else {\n            // しきい値未満なら順番にソートする（順次処理）\n            do_sort(first, true, comparator);\n            do_sort(second, false, comparator);\n        }\n        sub_sort(x, forward, comparator);\n    }\n}\n\nfn sub_sort<T, F>(x: &mut [T], forward: bool, comparator: &F)\n    where T: Send,\n          F: Sync + Fn(&T, &T) -> Ordering\n{\n    if x.len() > 1 {\n        compare_and_swap(x, forward, comparator);\n        let mid_point = x.len() / 2;\n        let (first, second) = x.split_at_mut(mid_point);\n        if mid_point >= PARALLEL_THRESHOLD {\n            rayon::join(|| sub_sort(first, forward, comparator),\n                        || sub_sort(second, forward, comparator));\n        } else {\n            sub_sort(first, forward, comparator);\n            sub_sort(second, forward, comparator);\n        }\n    }\n}\n\nfn compare_and_swap<T, F>(x: &mut [T], forward: bool, comparator: &F)\n    where F: Fn(&T, &T) -> Ordering\n{\n    let swap_condition = if forward {\n        Ordering::Greater\n    } else {\n        Ordering::Less\n    };\n    let mid_point = x.len() / 2;\n    for i in 0..mid_point {\n        if comparator(&x[i], &x[mid_point + i]) == swap_condition {\n            x.swap(i, mid_point + i);\n        }\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::{sort, sort_by};\n    use crate::SortOrder::*;\n    use crate::utils::{new_u32_vec, is_sorted_ascending, is_sorted_descending};\n\n    #[derive(Debug, PartialEq)]\n    struct Student {\n        first_name: String,\n        last_name:  String,\n        age: u8,\n    }\n\n    impl Student {\n        fn new(first_name: &str, last_name: &str, age: u8) -> Self {\n            Self {\n                first_name: first_name.to_string(),\n                last_name:  last_name.to_string(),\n                age,\n            }\n        }\n    }\n\n    #[test]\n    fn sort_to_fail() {\n        let mut x = vec![10, 30, 11]; // x.len() が2のべき乗になっていない。\n        assert!(sort(&mut x, &Ascending).is_err());\n    }\n\n    #[test]\n    fn sort_u32_ascending() {\n        let mut x: Vec<u32> = vec![10, 30, 11, 20, 4, 330, 21, 110];\n        assert_eq!(sort(&mut x, &Ascending), Ok(()));\n        assert_eq!(x, vec![4, 10, 11, 20, 21, 30, 110, 330]);\n    }\n\n    #[test]\n    fn sort_u32_descending() {\n        let mut x: Vec<u32> = vec![10, 30, 11, 20, 4, 330, 21, 110];\n        assert_eq!(sort(&mut x, &Descending), Ok(()));\n        assert_eq!(x, vec![330, 110, 30, 21, 20, 11, 10, 4]);\n    }\n\n    #[test]\n    fn sort_u32_large() {\n        {\n            let mut x = new_u32_vec(65536);\n            assert_eq!(sort(&mut x, &Ascending), Ok(()));\n            assert!(is_sorted_ascending(&x));\n        }\n        {\n            let mut x = new_u32_vec(65536);\n            assert_eq!(sort(&mut x, &Descending), Ok(()));\n            assert!(is_sorted_descending(&x));\n        }\n    }\n\n    #[test]\n    fn sort_str_ascending() {\n        let mut x = vec![\"Rust\", \"is\", \"fast\", \"and\", \"memory-efficient\", \"with\", \"no\", \"GC\"];\n        assert_eq!(sort(&mut x, &Ascending), Ok(()));\n        assert_eq!(x, vec![\"GC\", \"Rust\", \"and\", \"fast\", \"is\", \"memory-efficient\", \"no\", \"with\"]);\n    }\n\n    #[test]\n    fn sort_str_descending() {\n        let mut x = vec![\"Rust\", \"is\", \"fast\", \"and\", \"memory-efficient\", \"with\", \"no\", \"GC\"];\n        assert_eq!(sort(&mut x, &Descending), Ok(()));\n        assert_eq!(x, vec![\"with\", \"no\", \"memory-efficient\", \"is\", \"fast\", \"and\", \"Rust\", \"GC\"]);\n    }\n\n    #[test]\n    fn sort_students_by_age_ascending() {\n        let taro = Student::new(\"Taro\", \"Yamada\", 16);\n        let hanako = Student::new(\"Hanako\", \"Yamada\", 14);\n        let kyoko = Student::new(\"Kyoko\", \"Ito\", 15);\n        let ryosuke = Student::new(\"Ryosuke\", \"Hayashi\", 17);\n\n        let mut x = vec![&taro, &hanako, &kyoko, &ryosuke];\n        let expected = vec![&hanako, &kyoko, &taro, &ryosuke];\n        assert_eq!(\n            // sort_by関数でソートする。第2引数はソート順を決めるクロージャ\n            // 引数に2つのStudent構造体をとり、ageフィールドの値をcmpメソッドで\n            // 比較することで大小を決定する\n            sort_by(&mut x, &|a, b| a.age.cmp(&b.age)),\n            Ok(())\n        );\n        assert_eq!(x, expected);\n    }\n\n    #[test]\n    fn sort_students_by_name_ascending() {\n        let taro = Student::new(\"Taro\", \"Yamada\", 16);\n        let hanako = Student::new(\"Hanako\", \"Yamada\", 14);\n        let kyoko = Student::new(\"Kyoko\", \"Ito\", 15);\n        let ryosuke = Student::new(\"Ryosuke\", \"Hayashi\", 17);\n\n        let mut x = vec![&taro, &hanako, &kyoko, &ryosuke];\n        let expected = vec![&ryosuke, &kyoko, &hanako, &taro];\n\n        assert_eq!(sort_by(&mut x,\n            // まずlast_nameを比較する\n            &|a, b| a.last_name.cmp(&b.last_name)\n                // もしlast_nameが等しくない（LessまたはGreater）ならそれを返す\n                // last_nameが等しい（Equal）ならfirst_nameを比較する\n                .then_with(|| a.first_name.cmp(&b.first_name))), Ok(())\n        );\n        assert_eq!(x, expected);\n    }\n}\n"
  },
  {
    "path": "ch03/bitonic-sorter/src/lib.rs",
    "content": "pub mod utils;\n\n// 第1段階：初歩的な実装。u32型の値のソートのみに対応\npub mod first;\n\n// 第2段階：ジェネリクスでさまざまなデータ型に対応\npub mod second;\n\n// 第3段階：クロージャでソート順をカスタマイズ\npub mod third;\n\n// 最終形：並列ソート\npub mod fourth;\n\npub enum SortOrder {\n    Ascending,   // 昇順\n    Descending,  // 降順\n}\n"
  },
  {
    "path": "ch03/bitonic-sorter/src/second.rs",
    "content": "use super::SortOrder;\n\n// 成功時はOK(())を、失敗時はErr(文字列)を返す\npub fn sort<T: Ord>(x: &mut [T], order: &SortOrder) -> Result<(), String> {\n    if x.len().is_power_of_two() {\n        match *order {\n            SortOrder::Ascending  => do_sort(x, true),\n            SortOrder::Descending => do_sort(x, false),\n        };\n        Ok(())\n    } else {\n        Err(format!(\"The length of x is not a power of two. (x.len(): {})\", x.len()))\n    }\n}\n\nfn do_sort<T: Ord>(x: &mut [T], up: bool) {\n    if x.len() > 1 {\n        let mid_point = x.len() / 2;\n        do_sort(&mut x[..mid_point], true);\n        do_sort(&mut x[mid_point..], false);\n        sub_sort(x, up);\n    }\n}\n\nfn sub_sort<T: Ord>(x: &mut [T], up: bool) {\n    if x.len() > 1 {\n        compare_and_swap(x, up);\n        let mid_point = x.len() / 2;\n        sub_sort(&mut x[..mid_point], up);\n        sub_sort(&mut x[mid_point..], up);\n    }\n}\n\nfn compare_and_swap<T: Ord>(x: &mut [T], up: bool) {\n    let mid_point = x.len() / 2;\n    for i in 0..mid_point {\n        if (x[i] > x[mid_point + i]) == up {\n            x.swap(i, mid_point + i);\n        }\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::sort;\n    use crate::SortOrder::*;\n\n    #[test]\n    fn sort_to_fail() {\n        let mut x = vec![10, 30, 11]; // x.len() が2のべき乗になっていない。\n        assert!(sort(&mut x, &Ascending).is_err());  // 戻り値はErr\n    }\n\n    #[test]\n    fn sort_u32_ascending() {\n        let mut x: Vec<u32> = vec![10, 30, 11, 20, 4, 330, 21, 110];\n        assert_eq!(sort(&mut x, &Ascending), Ok(()));\n        assert_eq!(x, vec![4, 10, 11, 20, 21, 30, 110, 330]);\n    }\n\n    #[test]\n    fn sort_u32_descending() {\n        let mut x: Vec<u32> = vec![10, 30, 11, 20, 4, 330, 21, 110];\n        assert_eq!(sort(&mut x, &Descending), Ok(()));\n        assert_eq!(x, vec![330, 110, 30, 21, 20, 11, 10, 4]);\n    }\n\n    #[test]\n    fn sort_str_ascending() {\n        // 文字列のベクタを作り、ソートする\n        let mut x = vec![\"Rust\", \"is\", \"fast\", \"and\", \"memory-efficient\", \"with\", \"no\", \"GC\"];\n        assert_eq!(sort(&mut x, &Ascending), Ok(()));\n        assert_eq!(x, vec![\"GC\", \"Rust\", \"and\", \"fast\", \"is\", \"memory-efficient\", \"no\", \"with\"]);\n    }\n\n    #[test]\n    fn sort_str_descending() {\n        let mut x = vec![\"Rust\", \"is\", \"fast\", \"and\", \"memory-efficient\", \"with\", \"no\", \"GC\"];\n        assert_eq!(sort(&mut x, &Descending), Ok(()));\n        assert_eq!(x, vec![\"with\", \"no\", \"memory-efficient\", \"is\", \"fast\", \"and\", \"Rust\", \"GC\"]);\n    }\n}\n"
  },
  {
    "path": "ch03/bitonic-sorter/src/third.rs",
    "content": "use super::SortOrder;\nuse std::cmp::Ordering;\n\npub fn sort<T: Ord>(x: &mut [T], order: &SortOrder) -> Result<(), String> {\n    // do_sortを呼ぶ代わりに、sort_by を呼ぶようにする\n    // is_power_of_twoはsort_byが呼ぶので、ここからは削除した\n    match *order {\n        // 昇順ならa.cmp(b)、降順ならb.cmp(a)を行う\n        SortOrder::Ascending  => sort_by(x, &|a, b| a.cmp(b)),\n        SortOrder::Descending => sort_by(x, &|a, b| b.cmp(a)),\n    }\n}\n\npub fn sort_by<T, F>(x: &mut [T], comparator: &F) -> Result<(), String>\n    where F: Fn(&T, &T) -> Ordering\n{\n    if x.len().is_power_of_two() {\n        do_sort(x, true, comparator);\n        Ok(())\n    } else {\n        Err(format!(\"The length of x is not a power of two. (x.len(): {})\", x.len()))\n    }\n}\n\nfn do_sort<T, F>(x: &mut [T], forward: bool, comparator: &F)\n    where F: Fn(&T, &T) -> Ordering\n{\n    if x.len() > 1 {\n        let mid_point = x.len() / 2;\n\n        // xをバイトニックにソートする\n        // 第2引数がtrueのときはcomparatorで示される順序でソート\n        do_sort(&mut x[..mid_point], true, comparator);\n        // 第2引数がfalseのときはcomparatorとは逆順でソート\n        do_sort(&mut x[mid_point..], false, comparator);\n        sub_sort(x, forward, comparator);\n    }\n}\n\nfn sub_sort<T, F>(x: &mut [T], forward: bool, comparator: &F)\n    where F: Fn(&T, &T) -> Ordering\n{\n    if x.len() > 1 {\n        compare_and_swap(x, forward, comparator);\n        let mid_point = x.len() / 2;\n        sub_sort(&mut x[..mid_point], forward, comparator);\n        sub_sort(&mut x[mid_point..], forward, comparator);\n    }\n}\n\nfn compare_and_swap<T, F>(x: &mut [T], forward: bool, comparator: &F)\n    where F: Fn(&T, &T) -> Ordering\n{\n    // 比較に先立ちforward（bool値）をOrdering値に変換しておく\n    let swap_condition = if forward {\n        Ordering::Greater\n    } else {\n        Ordering::Less\n    };\n    let mid_point = x.len() / 2;\n    for i in 0..mid_point {\n        // comparatorクロージャで2要素を比較し、返されたOrderingのバリアントが\n        // swap_conditionと等しいなら要素を交換する\n        if comparator(&x[i], &x[mid_point + i]) == swap_condition {\n            x.swap(i, mid_point + i);\n        }\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::{sort, sort_by};\n    use crate::SortOrder::*;\n    use crate::utils::{new_u32_vec, is_sorted_ascending, is_sorted_descending};\n\n    // 構造体Studentを定義する\n    // 構造体は関連する値を1つにまとめたデータ構造。複数のデータフィールドを持つ\n\n    // deriveアトリビュートを使い、DebugトレイトとPartialEqトレイトの実装を自動導出する\n    #[derive(Debug, PartialEq)]\n    struct Student {\n        first_name: String,  // first_name（名前）フィールド。String型\n        last_name:  String,  // last_name（苗字）フィールド。String型\n        age: u8,             // age（年齢）フィールド。u8型（8ビット符号なし整数）\n    }\n\n    // implブロックを使うと対象の型に関連関数やメソッドを実装できる\n    impl Student {\n\n        // 関連関数newを定義する\n        fn new(first_name: &str, last_name: &str, age: u8) -> Self {\n            // 構造体Studentを初期化して返す。Selfはimpl対象の型（Student）の別名\n            Self {\n                // to_stringメソッドで&str型の引数からString型の値を作る。詳しくは5章で説明\n                first_name: first_name.to_string(),  // first_nameフィールドに値を設定\n                last_name:  last_name.to_string(),   // last_nameフィールドに値を設定\n                age,  // ageフィールドにage変数の値を設定\n                      // フィールドと変数が同じ名前のときは、このように省略形で書ける\n            }\n        }\n    }\n\n    #[test]\n    fn sort_to_fail() {\n        let mut x = vec![10, 30, 11]; // x.len() が2のべき乗になっていない。\n        assert!(sort(&mut x, &Ascending).is_err());\n    }\n\n    #[test]\n    fn sort_u32_ascending() {\n        let mut x: Vec<u32> = vec![10, 30, 11, 20, 4, 330, 21, 110];\n        assert_eq!(sort(&mut x, &Ascending), Ok(()));\n        assert_eq!(x, vec![4, 10, 11, 20, 21, 30, 110, 330]);\n    }\n\n    #[test]\n    fn sort_u32_descending() {\n        let mut x: Vec<u32> = vec![10, 30, 11, 20, 4, 330, 21, 110];\n        assert_eq!(sort(&mut x, &Descending), Ok(()));\n        assert_eq!(x, vec![330, 110, 30, 21, 20, 11, 10, 4]);\n    }\n\n    #[test]\n    fn sort_u32_large() {\n        {\n            // 乱数で65,536要素のデータ列を作る（65,536は2の16乗）\n            let mut x = new_u32_vec(65536);\n            // 昇順にソートする\n            assert_eq!(sort(&mut x, &Ascending), Ok(()));\n            // ソート結果が正しいことを検証する\n            assert!(is_sorted_ascending(&x));\n        }\n        {\n            let mut x = new_u32_vec(65536);\n            assert_eq!(sort(&mut x, &Descending), Ok(()));\n            assert!(is_sorted_descending(&x));\n        }\n    }\n\n    #[test]\n    fn sort_str_ascending() {\n        let mut x = vec![\"Rust\", \"is\", \"fast\", \"and\", \"memory-efficient\", \"with\", \"no\", \"GC\"];\n        assert_eq!(sort(&mut x, &Ascending), Ok(()));\n        assert_eq!(x, vec![\"GC\", \"Rust\", \"and\", \"fast\", \"is\", \"memory-efficient\", \"no\", \"with\"]);\n    }\n\n    #[test]\n    fn sort_str_descending() {\n        let mut x = vec![\"Rust\", \"is\", \"fast\", \"and\", \"memory-efficient\", \"with\", \"no\", \"GC\"];\n        assert_eq!(sort(&mut x, &Descending), Ok(()));\n        assert_eq!(x, vec![\"with\", \"no\", \"memory-efficient\", \"is\", \"fast\", \"and\", \"Rust\", \"GC\"]);\n    }\n\n    #[test]\n    // 年齢で昇順にソートする\n    fn sort_students_by_age_ascending() {\n\n        // 4人分のテストデータを作成\n        let taro = Student::new(\"Taro\", \"Yamada\", 16);\n        let hanako = Student::new(\"Hanako\", \"Yamada\", 14);\n        let kyoko = Student::new(\"Kyoko\", \"Ito\", 15);\n        let ryosuke = Student::new(\"Ryosuke\", \"Hayashi\", 17);\n\n        // ソート対象のベクタを作成する\n        let mut x = vec![&taro, &hanako, &kyoko, &ryosuke];\n\n        // ソート後の期待値を作成する\n        let expected = vec![&hanako, &kyoko, &taro, &ryosuke];\n\n        assert_eq!(\n            // sort_by関数でソートする。第2引数はソート順を決めるクロージャ\n            // 引数に2つのStudent構造体をとり、ageフィールドの値をcmpメソッドで\n            // 比較することで大小を決定する\n            sort_by(&mut x, &|a, b| a.age.cmp(&b.age)),\n            Ok(())\n        );\n\n        // 結果を検証する\n        assert_eq!(x, expected);\n    }\n\n    #[test]\n    fn sort_students_by_name_ascending() {\n        let taro = Student::new(\"Taro\", \"Yamada\", 16);\n        let hanako = Student::new(\"Hanako\", \"Yamada\", 14);\n        let kyoko = Student::new(\"Kyoko\", \"Ito\", 15);\n        let ryosuke = Student::new(\"Ryosuke\", \"Hayashi\", 17);\n\n        let mut x = vec![&taro, &hanako, &kyoko, &ryosuke];\n        let expected = vec![&ryosuke, &kyoko, &hanako, &taro];\n\n        assert_eq!(sort_by(&mut x,\n            // まずlast_nameを比較する\n            &|a, b| a.last_name.cmp(&b.last_name)\n                // もしlast_nameが等しくない（LessまたはGreater）ならそれを返す\n                // last_nameが等しい（Equal）ならfirst_nameを比較する\n                .then_with(|| a.first_name.cmp(&b.first_name))), Ok(())\n        );\n        assert_eq!(x, expected);\n    }\n}\n"
  },
  {
    "path": "ch03/bitonic-sorter/src/utils.rs",
    "content": "use rand::{Rng, SeedableRng};\nuse rand::distributions::Standard;\nuse rand_pcg::Pcg64Mcg;\n\npub fn new_u32_vec(n: usize) -> Vec<u32> {\n    // RNGを初期化する。再現性を持たせるため毎回同じシード値を使う\n    let mut rng = Pcg64Mcg::from_seed([0; 16]);\n\n    // rng.sample_iter()は乱数を無限に生成するイテレータを返す\n    // take(n)は元のイテレータから最初のn要素だけを取り出すイテレータを返す\n    // collect()はイテレータから値を収集して、ベクタやハッシュマップのような\n    // コレクションに格納する\n    rng.sample_iter(&Standard).take(n).collect()\n}\n\npub fn is_sorted_ascending<T: Ord>(x: &[T]) -> bool {\n    // windows(2)は元のイテレータから1要素刻みで2要素ずつ値を取り出す\n    // 新しいイテレータを返す。たとえば元が[1, 2, 3, 4]なら\n    // [1, 2]、[2, 3], [3, 4]を順に返す\n    //\n    // all(..)はイテレータから値（例：[1, 2]）を取り出し、クロージャに渡す\n    // クロージャがfalseを返したら、そこで処理を打ち切りfalseを返す\n    // クロージャがtrueを返している間は、イテレータから次の値を取り出し\n    // クロージャへ与え続ける。イテレータの値が尽きるまで（Noneになるまで）\n    // クロージャが一度もfalseを返さなかったら、all(..)はtrueを返す\n    x.windows(2).all(|pair| pair[0] <= pair[1])\n}\n\npub fn is_sorted_descending<T: Ord>(x: &[T]) -> bool {\n    x.windows(2).all(|pair| pair[0] >= pair[1])\n}"
  },
  {
    "path": "ch03/bitonic-sorter/tests/integration_tests.rs",
    "content": "use cli_test_dir::*;\n\n// バイナリを実行して入出力を確認するテスト\n// `cargo test` で実行できる\n\n#[test]\nfn run_benchmark() {\n    let testdir = TestDir::new(\"./examples/benchmark\", \"Run benchmark\");\n    let output = testdir\n        .cmd()\n        .arg(\"20\")\n        // .tee_output()    // stdoutとstderrorを順に表示する。デバッグに便利\n        .expect_success();\n\n    use regex::Regex;\n    let re = Regex::new(\n        r#\"(?m)\\Asorting 1048576 integers \\(4.0 MB\\)\ncpu info: \\d+ physical cores, \\d+ logical cores\nseq_sort: sorted 1048576 integers in \\d+\\.\\d+ seconds\npar_sort: sorted 1048576 integers in \\d+\\.\\d+ seconds\nspeed up: \\d+\\.\\d+x\n\\z\"#,\n    )\n    .expect(\"Failed to compile a regex pattern\");\n\n    assert!(re.is_match(output.stdout_str()));\n    assert!(output.stderr_str().is_empty());\n}\n"
  },
  {
    "path": "ch04/ex04/.gitignore",
    "content": "# Cargoが選択した依存ライブラリのバージョン郡\nCargo.lock\n\n# コンパイラが生成する成果物や中間ファイルが置かれる\ntarget/\n"
  },
  {
    "path": "ch04/ex04/Cargo.toml",
    "content": "[package]\nname = \"ex04\"\nversion = \"0.1.0\"\nauthors = [\"Rust Bicycle Book <bicycle-book@example.com>\"]\nedition = \"2018\"\n\n[dependencies]\n\n[dev-dependencies]\ncli_test_dir = \"0.1\"\nregex = \"1\"\n"
  },
  {
    "path": "ch04/ex04/examples/ch04_01_unit.rs",
    "content": "// 戻り値の型を省略。コンパイラは戻り値がユニット型だと解釈する\nfn hello() {\n    println!(\"Hello\");\n}\n\nfn main() {\n    // 関数を呼び出し、（ないはずの）戻り値に変数retを束縛する\n    let ret = hello();\n    // アサーションでretの値がユニット値と等しいことを検査する\n    assert_eq!(ret, ());\n\n    // size_of::<型>()は、その型の値がメモリ上で占める大きさをバイト数で返す\n    assert_eq!(std::mem::size_of::<()>(), 0);  // 0バイト\n}\n"
  },
  {
    "path": "ch04/ex04/examples/ch04_02_bool.rs",
    "content": "#[allow(unused_variables)]\nfn main() {\n    let b1 = true;\n    let b2 = !b1;       // false、否定\n\n    let n1 = 8;\n    let n2 = 12;\n    let b3 = n1 >= 10;  // false\n    let b4 = n2 >= 10;  // true\n    let b5 = b3 && b4;  // false、ショートサーキット論理積\n    let b6 = b3 || b4;  // true、ショートサーキット論理和\n\n    assert_eq!(std::mem::size_of::<bool>(), 1);  // サイズは1バイト\n}\n"
  },
  {
    "path": "ch04/ex04/examples/ch04_03_integer.rs",
    "content": "#[allow(unused_variables)]\nfn main() {\n    let n1 = 10_000;     // i32型（整数リテラルのデフォルトの型）\n    let n2 = 0u8;        // u8型（サフィックスで型を指定）\n    let n3 = -100_isize; // isize型（同上）\n\n    // 型推論が働く例\n    let n4 = 10;         // n4はisize型になる。なぜなら、\n    let n5 = n3 + n4;    // ここでisize型のn3に加算しているから\n\n    let h1 = 0xff;                  // i32型、16進数\n    let o1 = 0o744;                 // i32型、8進数\n    let b1 = 0b1010_0110_1110_1001; // i32型、2進数\n\n    let n6 = b'A';  // ASCII文字'A'の文字コード65u8を得る\n    assert_eq!(n6, 65u8);\n}\n"
  },
  {
    "path": "ch04/ex04/examples/ch04_04_overflowed1.rs",
    "content": "fn main() {\n    let n1 = std::u8::MAX;  // u8型の最大値は255u8\n    let n2 = 1u8;\n    // 答えは256だがu8型では表現できない（オーバーフロー）\n    let n3 = n1 + n2;\n    println!(\"{}\", n3);\n}\n"
  },
  {
    "path": "ch04/ex04/examples/ch04_05_overflowed2.rs",
    "content": "fn main() {\n    let n1 = 200u8;\n    let n2 = 3u8;\n\n    // n1 × n2 = 600を計算する\n    // std::u8::MAXは255なので桁あふれする\n\n    // 検査付き乗算 → Noneになる。\n    assert_eq!(n1.checked_mul(n2), None);\n\n    // 飽和乗算 → u8の最大値255にはり付く\n    assert_eq!(n1.saturating_mul(n2), std::u8::MAX);\n\n    // ラッピング乗算 → 600を256で割った余りの88になる\n    assert_eq!(n1.wrapping_mul(n2), 88);\n\n    // 桁あふれ乗算 → 88と桁あふれを示すtrueのペアを返す\n    assert_eq!(n1.overflowing_mul(n2), (88, true));\n}\n"
  },
  {
    "path": "ch04/ex04/examples/ch04_06_float.rs",
    "content": "#[allow(unused_variables)]\nfn main() {\n    let f1 = 10.0;         // f64型（小数リテラルのデフォルトの型）\n    let f2 = -1_234.56f32; // f32型（サフィックスで型を指定）\n    let f3 = 578.6E+77;    // f64型（指数部も指定できる）\n}\n"
  },
  {
    "path": "ch04/ex04/examples/ch04_07_char.rs",
    "content": "#[allow(unused_variables)]\nfn main() {\n    let c1 = 'A';               // char型\n    let c2 = 'a';\n    assert!(c1 < c2);           // 文字コード順で大小比較\n    assert!(c1.is_uppercase()); // 大文字か検査\n\n    let c3 = '0';\n    assert!(c3.is_digit(10));   // 10進数の数字か検査\n\n    let c4 = '\\t';              // タブ文字\n    let c5 = '\\n';              // 改行（LF）文字\n    let c6 = '\\'';              // シングルクオート（'）\n    let c7 = '\\\\';              // バックスラッシュ（\\）\n    let c8 = '\\x7F';            // 制御文字delを8ビットコードで表現（16進数で2桁）\n\n    let c9 = '漢';              // ソースコードに直接漢字も書ける（ファイルはUTF-8形式で\n                                // エンコードしておくこと）\n    let c10 = '\\u{5b57}';       // '字'をユニコードのエスケープコードで表現（16進数で最大6桁）\n    let c11 = '\\u{1f600}';      // 絵文字 😀\n\n    assert_eq!(std::mem::size_of::<char>(), 4);  // サイズは4バイト\n}\n"
  },
  {
    "path": "ch04/ex04/examples/ch04_08_reference1.rs",
    "content": "// 関数f1は呼び出し元の値のコピーを引数nに束縛し、1に変更する\n#[allow(unused_assignments)]\nfn f1(mut n: u32) {\n    n = 1;\n    println!(\"f1:       n = {}\", n);\n}\n\n// 関数f2は呼び出し元の値を指すポインタを受け取り、ポインタが指す\n// 場所に2を格納する\nfn f2(n_ptr: &mut u32) {\n    println!(\"f2:   n_ptr = {:p}\", n_ptr);\n\n    // *を付けると参照先にアクセスできる。これを参照外し（dereference）と呼ぶ\n    *n_ptr = 2;\n    println!(\"f2:  *n_ptr = {}\", *n_ptr);\n}\n\nfn main() {\n    let mut n = 0;\n    println!(\"main:     n = {}\", n);\n\n    f1(n);\n    println!(\"main:     n = {}\", n);\n\n    // `&mut n`でnの値を指す可変のポインタを作成する\n    f2(&mut n);\n    println!(\"main:     n = {}\", n);\n}\n"
  },
  {
    "path": "ch04/ex04/examples/ch04_09_reference2.rs",
    "content": "fn main() {\n    let c1 = 'A';         // char型\n    let c1_ptr = &c1;     // &char型。不変の参照（イミュータブルな参照）\n    assert_eq!(*c1_ptr, 'A');\n\n    let mut n1 = 0;       // i32型\n    let n1_ptr = &mut n1; // &mut i32型。可変の参照（ミュータブルな参照）\n    assert_eq!(*n1_ptr, 0);\n\n    // 可変の参照では参照先の値を変更できる\n    *n1_ptr = 1_000;\n    assert_eq!(*n1_ptr, 1_000);\n}\n"
  },
  {
    "path": "ch04/ex04/examples/ch04_10_raw_pointer.rs",
    "content": "fn main() {\n    let c1 = 'A';                   // char型\n    // `&`で参照を作り、型強制で生ポインタに変換する\n    let c1_ptr: *const char = &c1;  // *const char型。不変の生ポインタ\n    // 生ポインタの参照外しはunsafeな操作\n    assert_eq!(unsafe { *c1_ptr }, 'A');\n\n    let mut n1 = 0;                 // i32型\n    let n1_ptr: *mut i32 = &mut n1; // *mut i32型。可変の生ポインタ\n    assert_eq!(unsafe { *n1_ptr }, 0);\n\n    // 可変の生ポインタでは参照先の値を変更できる\n    unsafe {\n        *n1_ptr = 1_000;\n        assert_eq!(*n1_ptr, 1_000);\n    }\n}\n"
  },
  {
    "path": "ch04/ex04/examples/ch04_11_fn_pointer.rs",
    "content": "// この関数は引数を2倍した値を返す\nfn double(n: i32) -> i32 {\n    n + n\n}\n\n// この関数は引数の絶対値を返す\nfn abs(n: i32) -> i32 {\n    if n >= 0 { n } else { -n }\n}\n\nfn main() {\n    // 変数に型注釈として関数ポインタ型を指定することで、関数名から関数ポインタを得られる。\n    let mut f: fn(i32) -> i32 = double;\n    assert_eq!(f(-42), -84); // double関数で2倍された\n\n    f = abs;\n    assert_eq!(f(-42), 42); // abs関数で絶対値を得た\n\n    // 関数ポインタのサイズはusizeと同じ（x86_64アーキテクチャなら8バイト）\n    assert_eq!(std::mem::size_of_val(&f), std::mem::size_of::<usize>());\n\n    // 変数に型注釈を付けないと関数ポインタ型（fn pointer）ではなく\n    // 関数定義型（fn item）だと推論される\n    #[allow(unused_mut)]\n    let mut f_bad = double;\n\n    // 関数定義型は関数ごとに異なる型になるので、変数f_badに別の関数定義型を\n    // 束縛できない\n    // f_bad = abs;  // 型が合わず、コンパイルエラーになる\n    // error[E0308]: mismatched types（型の不一致）\n    //    = note: expected type `fn(i32) -> i32 {double}`\n    //               found type `fn(i32) -> i32 {abs}`\n\n    // 関数定義型の値のサイズは0バイト\n    assert_eq!(std::mem::size_of_val(&f_bad), 0);\n}\n"
  },
  {
    "path": "ch04/ex04/examples/ch04_12_fn_pointer_vs_closure.rs",
    "content": "fn main() {\n    let x = 4; // 変数xを4に束縛する\n\n    // クロージャを定義する。するとxがクロージャの環境に捕捉される（キャプチャされる）\n    let adder = |n| n + x;\n    assert_eq!(adder(2), 4 + 2);\n\n    let mut state = false;\n    // 別のクロージャを定義する。このクロージャは引数を取らない\n    let mut flipflop = || {\n        // stateが補足される\n        state = !state; // 状態を反転する\n        state\n    };\n\n    // クロージャを呼ぶたびに返る値が反転する\n    assert!(flipflop());  // true\n    assert!(!flipflop()); // false\n    assert!(flipflop());  // true\n\n    // クロージャが返す値だけでなく、stateの値も変化している\n    assert!(state); // true\n\n    let b = 5;\n\n    // クロージャは1つ1つが独自の匿名の型を持つため、変数fの型はこのクロージャの匿名型になる\n    #[allow(unused_mut)]\n    let mut f = |a| a * 3 + b;\n    // 別のクロージャでは変数fと型が合わず、コンパイルエラーになる\n    // f = |a| a * 4 + b;\n    // → error[E0308]: mismatched types（型の不一致）\n    //   = note: expected type `[closure@src/main.rs:5:17: 5:30 b:_]`\n    //              found type `[closure@src/main.rs:6:9: 6:22 b:_]`\n    //   = note: no two closures, even if identical, have the same type\n    //     （2つのクロージャは、たとえ見た目が同じでも、同じ型を持つことはない）\n    f(6);\n\n    // 環境になにも捕捉しないクロージャは関数ポインタ型になれる\n    #[allow(unused_mut)]\n    let mut f: fn(i32) -> i32 = |n| n * 3;\n    assert_eq!(f(-42), -126);\n\n    // 環境になにかを捕捉するクロージャは関数ポインタ型になれない\n    #[allow(unused_variables)]\n    let x = 4;\n    // f = |n| n * x;  // xを捕捉している\n    // → error[E0308]: mismatched types\n    //   expected fn pointer, found closure\n    //  （関数ポインタを期待しているのに、クロージャが見つかった）\n\n    let v = vec![\"I\", \"love\", \"Rust!\"]\n        .into_iter()\n        // .map(|s| s.len())  // &str型の引数sを取るクロージャ\n\n        // len()メソッドは&str型の引数を1つだけ取るので、len()メソッドへの\n        // 関数ポインタでも型が一致する\n        .map(str::len)\n        .collect::<Vec<_>>();\n    assert_eq!(v, vec![1, 4, 5]);\n}\n"
  },
  {
    "path": "ch04/ex04/examples/ch04_13_tuple.rs",
    "content": "fn main() {\n    let t1 = (88, true);\n\n    // フィールド0の要素（左から数えて最初の要素）を取り出す\n    assert_eq!(t1.0, 88);\n\n    // フィールド1の要素（2番目の要素）を取り出す\n    assert_eq!(t1.1, true);\n\n    // フィールド名にはコンパイル時の定数のみ使える。変数は不可\n    #[allow(unused_variables)]\n    let i = 0;\n    // let t1a = t1.i;\n    //   → コンパイルエラー\n    //       no field `i` on type `({integer}, bool)`\n    //      `({整数}, bool)`型には`i`という名のフィールドはありません\n\n    // 要素を書き換えるので、変数t1に`mut`を付けて可変にする\n    let mut t1 = (88, true);\n\n    // フィールド0の要素を書き換える\n    t1.0 += 100;  // 現在の値に100を足す\n\n    assert_eq!(t1, (188, true));\n\n    let (n1, b1) = (88, true);\n    assert_eq!(n1, 88);\n    assert_eq!(b1, true);\n\n    let ((x1, y1), (x2, y2)) = ((0, 5), (10, -1));\n    assert_eq!(x1, 0);\n    assert_eq!(y1, 5);\n    assert_eq!(x2, 10);\n    assert_eq!(y2, -1);\n\n    // 不要な値はアンダースコアを使うと無視できる\n    #[allow(unused_variables)]\n    let ((x1, y1), _) = ((0, 5), (10, -1));\n\n    // 要素を書き換えるので、変数t1に`mut`を付けて可変にする\n    let mut t1 = ((0, 5), (10, -1));\n\n    // 要素を指す可変の参照を得るためにref mutを追加する\n    let ((ref mut x1_ptr, ref mut y1_ptr), _) = t1;\n\n    // *を付けることでポインタが指すアドレスにあるデータにアクセスできる\n    *x1_ptr += 3;\n    *y1_ptr *= -1;\n\n    assert_eq!(t1, ((3, -5), (10, -1)));\n}\n"
  },
  {
    "path": "ch04/ex04/examples/ch04_14_array.rs",
    "content": "fn main() {\n    #[allow(unused_variables)]\n    let a1 = [false, true, false];     // [bool; 3]型\n    let a2 = [0.0, -1.0, 1.0, 0.5];    // [f64; 4]型\n\n    // `len()`で配列の長さを得られる\n    assert_eq!(a2.len(), 4);\n\n    // 長さ100の配列を作り、全要素を0i32で初期化する\n    // （要素の型はCopyトレイトを実装していなければならない）\n    let a3 = [0; 100];                 // [i32; 100]型\n    assert_eq!(a3.len(), 100);\n\n    // 配列は入れ子にできる\n    #[allow(unused_variables)]\n    let a4 = [['a', 'b'], ['c', 'd']]; // [[char; 2]; 2]型。2次元配列\n\n    // 配列は同じ型の要素の並び。異なる型の要素は持てない\n    // let a5 = [false, 'a'];\n    //   → コンパイルエラー E0308：型の不一致。boolでなくcharがある\n\n    // 配列の長さは実行時に指定できない\n    let size = 100;\n    // let a1 = [0; size];\n    //   → コンパイルエラー E0435：\n    //     コンパイル時定数が要求される場所に定数でない値がある\n\n    // ベクタなら実行時に長さを指定できる\n    let mut v1 = vec![0; size];    // Vec<i32>型\n    assert_eq!(v1.len(), 100);     // 長さは100\n\n    // ベクタには要素を追加したり、削除したりできる。\n    v1.push(1);                    // ベクタの最後尾に要素を追加する\n    assert_eq!(v1.len(), 101);     // 長さは101になる\n    assert_eq!(v1.pop(), Some(1)); // ベクタの最後尾から要素を取り除く\n    assert_eq!(v1.len(), 100);     // 長さは100に戻る\n\n    let array1 = ['H', 'e', 'l', 'l', 'o'];\n    assert_eq!(array1[1], 'e');\n\n    let mut array2 = [0, 1, 2];\n    array2[1] = 10;\n    assert_eq!(array2, [0, 10, 2]);\n\n    // インデックスは定数でなくてもかまわない\n    let mut index = 0;\n    assert_eq!(array2[index], 0);\n    index += 1;\n    assert_eq!(array2[index], 10);\n\n    let array3 = [0, 1];\n    // array3[2];\n    // → コンパイルエラー：インデックスが範囲外。長さは2だがインデックスが2である\n    #[allow(unused_variables)]\n    let index = 2;\n    // array3[index];\n    // → コンパイルエラーにはならずにパニックする\n\n\n    assert_eq!(array3.get(1), Some(&1));  // get()はインデックスが範囲内の時はSome(&値)を返す\n    assert_eq!(array3.get(2), None);      // さもなければNoneを返す\n\n    let array4 = ['a'; 50];    // 長さ50\n\n    // iter()で要素が不変のイテレータを作成\n    for ch in array4.iter() {\n        print!(\"{},\", *ch);\n    }\n\n    let mut array5 = [1; 50];  // 長さ50\n\n    // iter_mut()で要素が可変のイテレータを作成\n    for n in array5.iter_mut() {\n        *n *= 2;\n    }\n}\n"
  },
  {
    "path": "ch04/ex04/examples/ch04_15_slice1.rs",
    "content": "// この関数は&[char]型のスライスを引数に取り、その情報を表示する\nfn print_info(name: &str, sl: &[char]) {\n    println!(\n        \"  {:9} - {}, {:?}, {:?}, {:?}\",\n        name,\n        sl.len(),    // 長さ（バイト数）  usize型\n        sl.first(),  // 最初の要素       Option<char>型\n        sl[1],       // 2番目の要素      char型\n        sl.last()    // 最後の要素       Option<char>型\n    );\n}\n\nfn main() {\n    // 配列\n    let a1 = ['a', 'b', 'c', 'd'];       // 参照元のデータ。[char; 4]型\n    println!(\"a1: {:?}\", a1);\n\n    print_info(\"&a1[..]\",   &a1[..]);    // &[char]型。全要素のスライス\n    print_info(\"&a1\",       &a1);        // 同上\n    print_info(\"&a1[1..3]\", &a1[1..3]);  // 'b'と'c'を要素とする長さ2のスライス\n\n    // ベクタ\n    let v1 = vec!['e', 'f', 'g', 'h'];   // 参照元のデータ。Vec<char>型\n    println!(\"\\nv1: {:?}\", v1);\n\n    print_info(\"&v1[..]\",   &v1[..]);    // &[char]型。全要素のスライス\n    print_info(\"&v1\",       &v1);        // 同上\n    print_info(\"&v1[1..3]\", &v1[1..3]);  // &[char]型。'f'と'g'を要素とする長さ2のスライス\n}\n"
  },
  {
    "path": "ch04/ex04/examples/ch04_16_slice2.rs",
    "content": "fn main() {\n    let mut a1 = [5, 4, 3, 2];      // 配列。[i32; 4]型\n    let s1 = &mut a1[1..3];         // 可変のスライス。&mut[i32]型\n    s1[0] = 6;                      // スライスの最初の要素を6にする\n    s1[1] *= 10;                    // 2番目の要素を10倍する\n    s1.swap(0, 1);                  // 要素を交換する\n    assert_eq!(s1, [30, 6]);        // スライスの内容を確認\n\n    // 参照元の配列の内容を確認\n    assert_eq!(a1, [5, 30, 6, 2]);  // スライスを通じて配列の内容が変更された\n\n    let a2: [i32; 0] = [];\n    let s2 = &a2;                              // 不変のスライスを作成\n    assert!(s2.is_empty());                    // 空のスライス\n    assert_eq!(s2.len(),   0);                 // 長さは0\n    assert_eq!(s2.first(), None);              // 最初の要素は存在しない\n\n    let a3 = [\"zero\", \"one\", \"two\", \"three\", \"four\"];\n    let s3 = &a3[1..4];                        // 不変のスライスを作成\n    assert!(!s3.is_empty());                   // 空ではない\n    assert_eq!(s3.len(),   3);                 // 長さは3\n    assert_eq!(s3.first(), Some(&\"one\"));      // 最初の要素\n\n    assert_eq!(s3[1],      \"two\");             // 2番目の要素\n    // assert_eq!(s3[3],   \"?\");               // 4番目の要素。存在しないのでpanicする\n    assert_eq!(s3.get(1),  Some(&\"two\"));      // 2番目の要素を得る別の方法\n    assert_eq!(s3.get(3),  None);              // 4番目の要素。存在しないのでNone\n\n    assert!(s3.contains(&\"two\"));              // \"two\"を要素に持つ\n    assert!(s3.starts_with(&[\"one\", \"two\"]));  // \"one\", \"two\"で始まる\n    assert!(s3.ends_with(&[\"two\", \"three\"]));  // \"two\", \"three\"で終わる\n\n    let mut a4 = [6, 4, 2, 8, 0, 9, 4, 3, 7, 5, 1, 7];\n\n    // 一部の要素を昇順にソートする\n    &mut a4[2..6].sort();\n    assert_eq!(&a4[2..6], &[0, 2, 8, 9]);\n\n    // スライスを2つの可変スライスへ分割する\n    #[allow(unused_variables)]\n    let (s4a, s4b) = &mut a4.split_at_mut(5);\n\n    // &mutを省略しても結果は同じ。型強制によって自動的にスライスが作られる\n    a4[2..6].sort();\n    let (s4a, s4b) = a4.split_at_mut(5);\n\n    // 前半を逆順にする\n    s4a.reverse();\n    assert_eq!(s4a, &[8, 2, 0, 4, 6]);\n\n    // 後半を昇順にソートする\n    s4b.sort_unstable();\n    assert_eq!(s4b, &[1, 3, 4, 5, 7, 7, 9]);\n\n    // sort()とsort_unstable()の違い\n    // sort()は安定ソートなので同順なデータのソート前の順序がソート後も保存される\n    // soft_unstable()は安定ソートではないが、一般的にsort()より高速\n}\n"
  },
  {
    "path": "ch04/ex04/examples/ch04_17_str.rs",
    "content": "fn main() {\n    let s1 = \"abc1\";   // &'static str型\n    let s2 = \"abc2\";\n    assert!(s1 < s2);\n    assert!(s1 != s2);\n\n    let s3 = \"文字列を複数行に渡って書くと\n    改行やスペースが入る\";\n    let s4 = \"行末にバックスラッシュを付けると\\\n            改行などが入らない\";\n\n    assert_eq!(s3, \"文字列を複数行に渡って書くと\\n    改行やスペースが入る\");\n    assert_eq!(s4, \"行末にバックスラッシュを付けると改行などが入らない\");\n\n    let s5 = \"文字列に\\\"と\\\\を含める\";  // バックスラッシュでエスケープ\n    let s6 = r#\"文字列に\"と\\を含める\"#; // raw文字列リテラル。正規表現などに便利\n    assert_eq!(s5, s6);\n\n    let s7 = r###\"このように#の数を増やすと\"##\"があっても大丈夫\"###;\n    assert_eq!(s7, \"このように#の数を増やすと\\\"##\\\"があっても大丈夫\");\n\n    #[allow(unused_variables)]\n    let s8 = \"もちろん絵文字\\u{1f600}も使える\"; // もちろん絵文字😀も使える\n\n    let fruits = \"あかりんご, あおりんご\\nラズベリー, ブラックベリー\";\n\n    // lines()メソッドは改行コード（\\n）を含む文字列から1行ずつ\n    // 取り出せるイテレータを作る\n    let mut lines = fruits.lines();\n    // イテレータのnext()メソッドで次の行を得る\n    let apple_line = lines.next();\n    assert_eq!(apple_line,   Some(\"あかりんご, あおりんご\"));\n    assert_eq!(lines.next(), Some(\"ラズベリー, ブラックベリー\"));\n    // 次の行がないならNoneが返る。\n    assert_eq!(lines.next(), None);\n\n    // りんごの行（Some(..)）の中身を取り出す\n    if let Some(apples) = apple_line {\n        // 「あか」で始まるかチェック\n        assert!(apples.starts_with(\"あか\"));\n        // 「りんご」の文字を含むかチェック\n        assert!(apples.contains(\"りんご\"));\n        // 「あお」が最初に出現する位置（UTF-8表現で何バイト目）を得る\n        assert_eq!(apples.find(\"あお\"), Some(17)); // 0始まりなので18バイト目\n\n        // 文字列をカンマ（,）で分割するイテレータを作る\n        let mut apple_iter = apples.split(\",\");\n        assert_eq!(apple_iter.next(), Some(\"あかりんご\"));\n\n        let green = apple_iter.next();\n        // 左側に余白がある。\n        assert_eq!(green, Some(\" あおりんご\"));\n        // Some(..)の内容にstrのtrim()メソッドを適用して余白を取り除く\n        assert_eq!(green.map(str::trim), Some(\"あおりんご\"));\n\n        assert_eq!(apple_iter.next(), None);\n    } else {\n        unreachable!();  // もしここに到達したらパニックで強制終了する\n    }\n\n    // s1からs4はどれも画面上では1文字として表示される\n                    // UTF-8表現\n    let s1 = \"a\";   // 61\n    let s2 = \"あ\";  // E3 81 82\n    let s3 = \"😀\";  // F0 9F 98 80\n    let s4 = \"🇯🇵\";  // F0 9F 87 AF F0 9F 87 B5\n\n    // len()メソッドはUTF-8のバイト数を返す\n    assert_eq!(s1.len(), 1);\n    assert_eq!(s2.len(), 3);\n    assert_eq!(s3.len(), 4);\n    assert_eq!(s4.len(), 8);\n\n    let s = \"abcあいう\";\n    assert_eq!(s.get(0..1), Some(\"a\"));\n    assert_eq!(s.get(3..6), Some(\"あ\"));\n    assert_eq!(s.get(3..4), None);  // UTF-8として解釈できない場合\n\n    let s = \"かか\\u{3099}く\";  // \\u{3099}は濁点文字\n    println!(\"{}\", s);        // かがく\n\n    let mut iter = s.chars();\n    assert_eq!(iter.next(), Some('か'));\n    assert_eq!(iter.next(), Some('か'));\n    assert_eq!(iter.next(), Some('\\u{3099}'));\n    assert_eq!(iter.next(), Some('く'));\n    assert_eq!(iter.next(), None);\n\n    let utf8: [u8; 4] = [0x61, 0xe3, 0x81, 0x82];\n    assert_eq!(std::str::from_utf8(&utf8), Ok(\"aあ\"));\n\n    let bad_utf8: [u8; 2] = [0x81, 0x33];  // でたらめなバイト列\n    let result2 = std::str::from_utf8(&bad_utf8);\n    assert!(result2.is_err());\n    println!(\"{:?}\", result2);\n    // → \"Err(Utf8Error { valid_up_to: 0, error_len: Some(1) })\"\n\n    // 文字列リテラル（&'static str）から&mut strは直接は得られない\n    // まず文字列リテラルをStringへ変換し、そこから&mut strを取り出す\n    let mut s1 = \"abcあいう\".to_string();  // String型\n\n    // &mut strを得る。これはStringが持つUTF-8バイト列を指す可変スライス\n    let s2 = s1.as_mut_str();         // &mut str型\n\n    // 英小文字を大文字に変更\n    s2.make_ascii_uppercase();\n    assert_eq!(s2, \"ABCあいう\");\n\n    // &mut strのUTF-8バイト列を直接操作して\"あ\"（3バイト）を\"*a*\"に変更する\n    let b = unsafe { s2.as_bytes_mut() };\n    b[3] = b'*';\n    b[4] = b'a';\n    b[5] = b'*';\n\n    // 大元のStringが変更されている\n    assert_eq!(s1, \"ABC*a*いう\");\n}\n"
  },
  {
    "path": "ch04/ex04/tests/integration_tests.rs",
    "content": "use cli_test_dir::*;\n\n// バイナリを実行して入出力を確認するテスト\n// `cargo test` で実行できる\n\n#[test]\nfn run_ch04_01() {\n    let testdir = TestDir::new(\"./examples/ch04_01_unit\", \"Run ch04_01\");\n    let output = testdir.cmd().expect_success();\n    assert_eq!(output.stdout_str(), \"Hello\\n\");\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch04_02() {\n    let testdir = TestDir::new(\"./examples/ch04_02_bool\", \"Run ch04_02\");\n    let output = testdir.cmd().expect_success();\n    assert!(output.stdout_str().is_empty());\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch04_03() {\n    let testdir = TestDir::new(\"./examples/ch04_03_integer\", \"Run ch04_03\");\n    let output = testdir.cmd().expect_success();\n    assert!(output.stdout_str().is_empty());\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch04_04() {\n    let testdir = TestDir::new(\"./examples/ch04_04_overflowed1\", \"Run ch04_04\");\n    let output = testdir\n        .cmd()\n        // .tee_output()\n        .expect_failure(); // debugビルドではpanicする\n    assert!(output.stdout_str().is_empty());\n    assert!(output.stderr_str().contains(\"thread 'main' panicked at 'attempt to add with overflow', examples/ch04_04_overflowed1.rs:\"));\n}\n\n#[test]\nfn run_ch04_05() {\n    let testdir = TestDir::new(\"./examples/ch04_05_overflowed2\", \"Run ch04_05\");\n    let output = testdir.cmd().expect_success();\n    assert!(output.stdout_str().is_empty());\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch04_06() {\n    let testdir = TestDir::new(\"./examples/ch04_06_float\", \"Run ch04_06\");\n    let output = testdir.cmd().expect_success();\n    assert!(output.stdout_str().is_empty());\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch04_07() {\n    let testdir = TestDir::new(\"./examples/ch04_07_char\", \"Run ch04_07\");\n    let output = testdir.cmd().expect_success();\n    assert!(output.stdout_str().is_empty());\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch04_08() {\n    let testdir = TestDir::new(\"./examples/ch04_08_reference1\", \"Run ch04_08\");\n    let output = testdir.cmd().expect_success();\n\n    use regex::Regex;\n    let re = Regex::new(\n        r#\"(?m)\\Amain:     n = 0\nf1:       n = 1\nmain:     n = 0\nf2:   n_ptr = 0x[0-9a-f]+\nf2:  \\*n_ptr = 2\nmain:     n = 2\n\\z\"#,\n    )\n    .expect(\"Failed to compile a regex pattern\");\n\n    assert!(re.is_match(output.stdout_str()));\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch04_09() {\n    let testdir = TestDir::new(\"./examples/ch04_09_reference2\", \"Run ch04_09\");\n    let output = testdir.cmd().expect_success();\n    assert!(output.stdout_str().is_empty());\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch04_10() {\n    let testdir = TestDir::new(\"./examples/ch04_10_raw_pointer\", \"Run ch04_10\");\n    let output = testdir.cmd().expect_success();\n    assert!(output.stdout_str().is_empty());\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch04_11() {\n    let testdir = TestDir::new(\"./examples/ch04_11_fn_pointer\", \"Run ch04_11\");\n    let output = testdir.cmd().expect_success();\n    assert!(output.stdout_str().is_empty());\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch04_12() {\n    let testdir = TestDir::new(\"./examples/ch04_12_fn_pointer_vs_closure\", \"Run ch04_12\");\n    let output = testdir.cmd().expect_success();\n    assert!(output.stdout_str().is_empty());\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch04_13() {\n    let testdir = TestDir::new(\"./examples/ch04_13_tuple\", \"Run ch04_13\");\n    let output = testdir.cmd().expect_success();\n    assert!(output.stdout_str().is_empty());\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch04_14() {\n    let testdir = TestDir::new(\"./examples/ch04_14_array\", \"Run ch04_14\");\n    let output = testdir.cmd().expect_success();\n    assert_eq!(\n        output.stdout_str(),\n        \"a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,\",\n    );\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch04_15() {\n    let testdir = TestDir::new(\"./examples/ch04_15_slice1\", \"Run ch04_15\");\n    let output = testdir.cmd().expect_success();\n    assert_eq!(\n        output.stdout_str(),\n        r#\"a1: ['a', 'b', 'c', 'd']\n  &a1[..]   - 4, Some('a'), 'b', Some('d')\n  &a1       - 4, Some('a'), 'b', Some('d')\n  &a1[1..3] - 2, Some('b'), 'c', Some('c')\n\nv1: ['e', 'f', 'g', 'h']\n  &v1[..]   - 4, Some('e'), 'f', Some('h')\n  &v1       - 4, Some('e'), 'f', Some('h')\n  &v1[1..3] - 2, Some('f'), 'g', Some('g')\n\"#\n    );\n    assert!(output.stderr_str().is_empty());\n}\n\n/*\n\n\n*/\n\n#[test]\nfn run_ch04_16() {\n    let testdir = TestDir::new(\"./examples/ch04_16_slice2\", \"Run ch04_16\");\n    let output = testdir.cmd().expect_success();\n    assert!(output.stdout_str().is_empty());\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch04_17() {\n    let testdir = TestDir::new(\"./examples/ch04_17_str\", \"Run ch04_17\");\n    let output = testdir.cmd().expect_success();\n    assert_eq!(\n        output.stdout_str(),\n        \"かか\\u{3099}く\\nErr(Utf8Error { valid_up_to: 0, error_len: Some(1) })\\n\",\n    );\n    assert!(output.stderr_str().is_empty());\n}\n"
  },
  {
    "path": "ch05/ex05/.gitignore",
    "content": "# Cargoが選択した依存ライブラリのバージョン郡\nCargo.lock\n\n# コンパイラが生成する成果物や中間ファイルが置かれる\ntarget/\n"
  },
  {
    "path": "ch05/ex05/Cargo.toml",
    "content": "[package]\nname = \"ex05\"\nversion = \"0.1.0\"\nauthors = [\"Rust Bicycle Book <bicycle-book@example.com>\"]\nedition = \"2018\"\n\n[dependencies]\n\n[dev-dependencies]\ncli_test_dir = \"0.1\"\nregex = \"1\"\n"
  },
  {
    "path": "ch05/ex05/examples/ch05_01_box.rs",
    "content": "fn main() {\n    let t1 = (5, \"birds\".to_string());  // (i32, String)型のタプル。スタックに置かれる\n    let mut b1 = Box::new(t1);          // Boxポインタを作る。タプルがヒープに移動する\n    (*b1).0 += 1;                       // *で参照外し\n    assert_eq!(*b1, (6, \"birds\".to_string()));\n\n    // Box::new()の実行後にt1にアクセスしようとするとコンパイルエラーになる\n    // println!(\"{:?}\", t1);\n    //   → error[E0382]: borrow of moved value: `t1`\n}\n"
  },
  {
    "path": "ch05/ex05/examples/ch05_02_vec.rs",
    "content": "fn main() {\n    #[allow(unused_variables)]\n    let v1 = vec![false, true, false];    // Vec<bool>型\n    let v2 = vec![0.0, -1.0, 1.0, 0.5];   // Vec<f64>型\n\n    assert_eq!(v2.len(), 4);              // v2ベクタの長さは4\n\n    // 長さ100のベクタを作り、全要素を0i32で初期化する\n    // （要素の型はCloneトレイトを実装していなければならない）\n    let v3 = vec![0; 100];                // Vec<i32>型\n    assert_eq!(v3.len(), 100);\n\n    // ベクタは入れ子にできる。子の要素数はそれぞれが異なってもかまわない\n    #[allow(unused_variables)]\n    let v4 = vec![vec!['a', 'b', 'c'], vec!['d']]; // Vec<Vec<char>>型\n\n    // ベクタは同じ型の要素の並び。異なる型の要素は持てない\n    // let v5 = vec![false, 'a'];\n    //   → error[E0308]: mismatched types\n\n    let mut v6 = vec!['a', 'b', 'c'];      // Vec<char>型\n    v6.push('d');                          // 最後尾に値を追加\n    v6.push('e');\n    assert_eq!(v6, ['a', 'b', 'c', 'd', 'e']);  // v6の現在の値\n\n    assert_eq!(v6.pop(), Some('e'));       // 最後尾から値を取り出し\n    v6.insert(1, 'f');                     // インデックス1の位置に要素を挿入\n    assert_eq!(v6.remove(2), 'b');         // インデックス2の要素を削除。返り値は削除した値\n    assert_eq!(v6, ['a', 'f', 'c', 'd']);  // v6の現在の値\n\n    let mut v7 = vec!['g', 'h'];           // 別のベクタv7を作成\n    v6.append(&mut v7);                    // v6の最後尾にv7の全要素を追加\n    assert_eq!(v6, ['a', 'f', 'c', 'd', 'g', 'h']);\n    assert_eq!(v7, []);                    // v7は空になった（全要素がv6へ移動した）\n\n    let a8 = ['i', 'j'];                   // 固定長配列a8を作成\n    v6.extend_from_slice(&a8);             // v6の最後尾にa8の全要素を追加\n    assert_eq!(v6, ['a', 'f', 'c', 'd', 'g', 'h', 'i', 'j']);\n    assert_eq!(a8, ['i', 'j']);            // a8は変更なし（a8の要素がコピーされた）\n}\n"
  },
  {
    "path": "ch05/ex05/examples/ch05_03_boxed_slice.rs",
    "content": "fn main() {\n    // 4要素のベクタVec<i32>を作り、要素を1つ足して5要素に拡張する\n    let mut v1 = vec![0, 1, 2, 3];\n    v1.push(4);\n    println!(\"v1 len: {}, capacity: {}\", v1.len(), v1.capacity());\n    // →「v1 len: 5, capacity: 8」と表示される。5要素だが8要素分のメモリを確保している\n\n    // Box<[i32]>に変換する。余分なメモリを持たなくするためにVecのshrink_to_fit()\n    // メソッドが実行されてからBox化される\n    let s1 = v1.into_boxed_slice();\n\n    // 余分なメモリを持ってないことを確認するためにVec<i32>に戻す\n    let v2 = s1.into_vec();\n    println!(\"v1 len: {}, capacity: {}\", v2.len(), v2.capacity());\n    // →「v2 len: 5, capacity: 5」と表示される。5要素ぴったりのメモリを確保していることが分かる\n}\n"
  },
  {
    "path": "ch05/ex05/examples/ch05_04_hash_map.rs",
    "content": "fn main() {\n    use std::collections::HashMap;\n\n    let mut m1 = HashMap::new();        // またはwith_capacity(要素数)\n\n    // 要素を2つ追加する\n    m1.insert(\"a\", 1);                  // キー：\"a\"、バリュー：1\n    m1.insert(\"b\", 3);\n    assert_eq!(m1.len(), 2);            // 要素数は2\n\n    // キーに対応する値を取り出す\n    assert_eq!(m1.get(\"b\"), Some(&3));\n    assert_eq!(m1.get(\"c\"), None);      // キーが存在しないのでNone\n\n    // \"d\"が存在するならその値への参照を得る。存在しないなら\"d\"に対して0を登録してから参照を返す\n    let d = m1.entry(\"d\").or_insert(0);\n    *d += 7;\n\n    assert_eq!(m1.get(\"d\"), Some(&7));\n\n    #[allow(unused_variables)]\n    let m2 = vec![(\"a\", 1), (\"b\", 3)].into_iter().collect::<HashMap<_, _>>();\n}\n"
  },
  {
    "path": "ch05/ex05/examples/ch05_05_string1.rs",
    "content": "fn main() {\n    // strリテラルからStringを作る。どちらの方法でも結果は同じ\n    let mut s1 = \"ラズベリー\".to_string();\n    let mut s2 = String::from(\"ブラックベリー\");\n\n    // Rust 1.19より前のバージョンでは性能上の理由からto_string()よりも\n    // to_owned()が推奨されていた。現在のバージョンではそのような配慮は不要\n    let s3 = \"ストロベリー\".to_owned();\n\n    s1.push_str(\"タルト\");    // String型の文字列にに&str型の文字列を追加\n    assert_eq!(s1, \"ラズベリータルト\");\n\n    s2.push('と');           // Stringにcharを追加する\n\n    // push_str()が受け付けるのは&str型のみ。以下はコンパイルエラーになる\n    // s2.push_str(s3);         // s3はString型\n    // → error[E0308]: mismatched types\n    //   expected &str, found struct `std::string::String`\n\n    // &を付けると型強制というしくみによって&Stringから&strへ変換される\n    s2.push_str(&s3);\n    assert_eq!(s2, \"ブラックベリーとストロベリー\");\n}\n"
  },
  {
    "path": "ch05/ex05/examples/ch05_06_string2.rs",
    "content": "fn main() {\n    let i = 42;           // i32型\n    assert_eq!(i.to_string(), \"42\");\n\n    let f = 4.3 + 0.1;    // f64型\n    assert_eq!(f.to_string(),       \"4.3999999999999995\");\n    assert_eq!(format!(\"{:.2}\", f), \"4.40\");  // format!マクロが便利\n\n    let t = (1, \"ABC\");\n    // 2要素のタプル型はDebugトレイトを実装しているのでformat!マクロで変換できる\n    assert_eq!(format!(\"{:?}\", t), r#\"(1, \"ABC\")\"#);\n\n    let s1 = \"42\";\n    assert_eq!(s1.parse::<i32>(), Ok(42)); // &str型からi32型へ変換\n\n    let s2 = \"abc\";\n    let r2: Result<f64, _> = s2.parse();   // 変数の型から型推論できるならparseの型パラメータは不要\n    assert!(r2.is_err());                  // 数値として解釈できないときはエラーが返る\n    println!(\"{:?}\", r2);                  // → Err(ParseFloatError { kind: Invalid })\n\n    let cs = ['t', 'r', 'u', 's', 't'];      // [char; 5]型\n    assert_eq!(cs.iter().collect::<String>(),       \"trust\");\n    assert_eq!(&cs[1..].iter().collect::<String>(), \"rust\" );\n\n    let bad_utf8: [u8; 7] = [\n        b'a',              // a\n        0xf0, 0x90, 0x80,  // でたらめなバイト列\n        0xe3, 0x81, 0x82,  // あ\n    ];\n\n    // 不正なバイト列はUnicodeのU+FFFD Replacement Characterに置き換わる\n    let s = String::from_utf8_lossy(&bad_utf8);\n    assert_eq!(s, \"a\\u{fffd}あ\");\n}\n"
  },
  {
    "path": "ch05/ex05/examples/ch05_07_string3.rs",
    "content": "// この関数は引数として&str型の名前を取り、&str型の\"Hello, 名前!\"を返す\n// fn f1(name: &str) -> &str {\n//     let s = format!(\"Hello, {}!\", name); // format!はStringを作る\n//     &s   // Stringから&strを作成し、戻り値として返す\n//     // → コンパイルエラー：`s` does not live long enough.（sの生存期間が不十分）\n// }\n\n// この関数は引数として&str型の名前を取り、String型の\"Hello, 名前!\"を返す\nfn f1(name: &str) -> String {\n    format!(\"Hello, {}!\", name)\n}\n\nfn main() {\n    f1(\"ken\");\n}\n"
  },
  {
    "path": "ch05/ex05/examples/ch05_08_string4.rs",
    "content": "fn main() {\n    let utf16: Vec<u16> = vec![0x61, 0x62, 0x6f22, 0x5b57];\n\n    // Vec<u16>の値をUTF-16と解釈しStringを作成する（UTF-8へ変換される）\n    if let Ok(s) = String::from_utf16(&utf16) {\n        assert_eq!(s, \"ab漢字\");\n    } else {\n        unreachable!();\n    }\n\n    // バイト文字列リテラル。ASCII文字以外のバイトは「\\x2桁の16進数」で記述する\n    let bs1 = b\"abc\\xe3\\x81\\x82\";  // &[u8; 6]型。UTF-8表現で\"abcあ\"\n    assert_eq!(bs1, &[b'a', b'b', b'c', 0xe3, 0x81, 0x82]);\n\n    // rawバイト文字列リテラル。エスケープ文字（\\）を特別扱いしないので、\\nは\n    // 改行文字ではなく文字どおり\\nと解釈される。\n    let bs2 = br#\"ab\\ncd\"#;        // &[u8; 6]型\n    assert_eq!(bs2, &[b'a', b'b', b'\\\\', b'n', b'c', b'd']);\n}\n"
  },
  {
    "path": "ch05/ex05/examples/ch05_09_range.rs",
    "content": "fn main() {\n    let a = ['a', 'b', 'c', 'd', 'e'];\n\n    // 糖衣構文と実際の範囲の対応\n    assert_eq!(a[ ..  ], ['a', 'b', 'c', 'd', 'e'] );\n    assert_eq!(a[ .. 3], ['a', 'b', 'c',         ] );\n    assert_eq!(a[ ..=3], ['a', 'b', 'c', 'd'     ] );\n    assert_eq!(a[1..  ], [     'b', 'c', 'd', 'e'] );\n    assert_eq!(a[1.. 3], [     'b', 'c'          ] );\n    assert_eq!(a[1..=3], [     'b', 'c', 'd'     ] );\n\n    // 糖衣構文とRange*型の対応\n    assert_eq!(   ..   , std::ops::RangeFull                   );\n    assert_eq!(   .. 3 , std::ops::RangeTo { end: 3 }          );\n    assert_eq!(   ..=3 , std::ops::RangeToInclusive { end: 3 } );\n    assert_eq!(  1..   , std::ops::RangeFrom { start: 1 }      );\n    assert_eq!(  1.. 3 , std::ops::Range { start: 1, end: 3 }  );\n    assert_eq!(  1..=3 , std::ops::RangeInclusive::new(1, 3)   );\n}\n"
  },
  {
    "path": "ch05/ex05/examples/ch05_10_option.rs",
    "content": "fn main() {\n    let a1 = ['a', 'b', 'c', 'd'];\n    assert_eq!(a1.get(0), Some(&'a'));  // インデックス0は配列a1の範囲内なので`Some(&値)`が返る\n    assert_eq!(a1.get(4), None);        // インデックス4は範囲外なので`None`が返る\n\n    let mut o1 = Some(10);              // Option<i32>型\n    match o1 {                          // match式でバリアントが判別できる\n        Some(s) => assert_eq!(s, 10),   // パターンマッチで中の値を取り出す\n        None => unreachable!(),\n    }\n\n    o1 = Some(20);\n    if let Some(s) = o1 {                // if let式でもバリアントの判別と値の取り出しができる\n        assert_eq!(s, 20);\n    }\n\n    let mut o2 = Some(String::from(\"Hello\"));  // Option<String>型\n    assert_eq!(o2.unwrap(), \"Hello\");          // unwrap()でSomeの中の値が取り出せる\n\n    // しかしunwrap()はNoneのときにpanicするので、できるだけ使わない方がいい\n    o2 = None;\n    // o2.unwrap();\n    // → thread 'main' panicked at 'called `Option::unwrap()` on a `None` value'\n\n    // unwrap_or_else()ならNoneでもpanicしないので安心して使える\n    // Noneのときはクロージャを実行し、Noneの代わりになる値を得る\n    assert_eq!(o2.unwrap_or_else(|| String::from(\"o2 is none\")), \"o2 is none\");\n\n    // Someで包まれた値を操作するならmap()やand_then()などのコンビネータが便利\n\n    // map()はSome(値)のときは値にクロージャを適用し、クロージャが返した値をSomeで包み直す\n    let mut o3 = Some(25);\n    assert_eq!(o3.map(|n| n * 10), Some(250));\n\n    // NoneならなにもせずNoneを返す\n    o3 = None;\n    assert_eq!(o3.map(|n| n * 10), None);\n\n    o3 = Some(10);\n    assert_eq!(\n        o3.map(|n| n * 10)\n            // and_then()はSome(値)のときは値にクロージャを適用し\n            // クロージャが返した値（Some(新しい値)、または、None）をそのまま返す\n            .and_then(|n| if n >= 200 { Some(n) } else { None }),\n        None\n    );\n\n    // インデックス0と3の両方に値があるので、それらの合計がSomeで包まれて返される\n    assert_eq!(add_elems(&[3, 7, 31, 127]), Some(3 + 127));\n\n    // インデックス3がないのでNoneが返される\n    assert_eq!(add_elems(&[7, 11]), None);\n}\n\nfn add_elems(s: &[i32]) -> Option<i32> {\n    // 複数のOption値を扱うときは?演算子が便利\n    // Some(値)なら値を取り出し、Noneならこの関数からすぐに戻る（Noneを返す）\n    let s0 = s.get(0)?;\n    let s3 = s.get(3)?;\n    Some(s0 + s3)\n}\n"
  },
  {
    "path": "ch05/ex05/examples/ch05_11_result.rs",
    "content": "fn main() {\n    // str::parse()は文字列を指定した型（ここではi32型）に変換する\n    assert_eq!(\"10\".parse::<i32>(), Ok(10));    // 変換できたらOK(値)が返される\n    let res0 = \"a\".parse::<i32>();              // 変換できなかったら`Err(エラーを表す値)`が返される\n    assert!(res0.is_err());\n    println!(\"{:?}\", res0); // → Err(ParseIntError { kind: InvalidDigit })\n\n    // 複数のResult値を扱うときは?演算子が便利\n    // Ok(値)なら値を取り出し、Err(エラーを表す値)ならこの関数からリターンする\n    fn add0(s0: &str, s1: &str) -> Result<i32, std::num::ParseIntError> {\n        let s0 = s0.parse::<i32>()?;\n        let s1 = s1.parse::<i32>()?;\n        Ok(s0 + s1)\n    }\n\n    assert_eq!(add0(\"3\", \"127\"), Ok(3 + 127));\n    assert!(add0(\"3\", \"abc\").is_err());\n\n    // map_err()コンビネータを使うとErr(エラーを表す値)のときに別のエラーに変換できる\n    fn add1(s0: &str, s1: &str) -> Result<i32, String> {\n        let s0 = s0.parse::<i32>().map_err(|_e| \"s0が整数ではありません\")?;\n        let s1 = s1.parse::<i32>().map_err(|_e| \"s1が整数ではありません\")?;\n        Ok(s0 + s1)\n    }\n\n    assert_eq!(add1(\"3\", \"abc\"), Err(\"s1が整数ではありません\".to_string()));\n}\n"
  },
  {
    "path": "ch05/ex05/examples/ch05_12_type_alias.rs",
    "content": "type UserName = String;\ntype Id = i64;\ntype Timestamp = i64;\ntype User = (Id, UserName, Timestamp);\n\nfn new_user(name: UserName, id: Id, created: Timestamp) -> User {\n    (id, name, created)\n}\n\nfn main() {\n    let id = 400;\n    let now = 4567890123;\n    #[allow(unused_variables)]\n    let user = new_user(String::from(\"mika\"), id, now);\n\n    // IdとTimestampは同じi64型なので、間違えてもエラーにならない\n    #[allow(unused_variables)]\n    let bad_user = new_user(String::from(\"kazuki\"), now, id); // nowとidが逆\n}\n"
  },
  {
    "path": "ch05/ex05/examples/ch05_13_struct1.rs",
    "content": "struct Polygon {\n    vertexes: Vec<(i32, i32)>,  // 頂点の座標\n    #[allow(dead_code)]\n    stroke_width: u8,           // 輪郭の太さ\n    fill: (u8, u8, u8),         // 塗りつぶしのRGB色\n}\n\n// フィールド名と同じ名前の関数引数やローカル変数がある時は以下のような\n// 省略形も使える（Rust 1.17以降）\nfn new_polygon(vertexes: Vec<(i32, i32)>) -> Polygon {\n  let stroke_width = 1;\n  let fill = (0, 0, 0);\n  Polygon { vertexes, stroke_width, fill }\n}\n\nfn main() {\n    // Polygon型の値を作り、変数triangleを束縛する\n    let triangle = Polygon {\n        vertexes: vec![(0, 0), (3, 0), (2, 2)],\n        fill: (255, 255, 255),\n        stroke_width: 1,\n    };\n\n    let quadrangle = new_polygon(vec![(5, 2), (4, 7), (10, 6), (8, 1)]);\n\n    // フィールド名でアクセス\n    assert_eq!(triangle.vertexes[0], (0, 0));\n    assert_eq!(triangle.vertexes.len(), 3);\n    assert_eq!(triangle.fill, (255, 255, 255));\n\n    // パターンマッチでアクセス。不要なフィールドは..で省略できる\n    let Polygon { vertexes: quad_vx, .. } = quadrangle;\n    assert_eq!(4, quad_vx.len());\n\n    // :以降を省略すると、フィールドと同じ名前の変数が作られフィールド値に束縛される\n    let Polygon { fill, .. } = quadrangle;\n    assert_eq!((0, 0, 0), fill);\n\n    // 構造体の値を変更するにはmutが必要\n    let mut polygon = new_polygon(vec![(-1, -5), (-4, 0)]);\n    assert_eq!(polygon.vertexes.len(), 2);\n    polygon.vertexes.push((2, 8));\n    assert_eq!(polygon.vertexes.len(), 3);\n\n    let triangle1 = Polygon {\n        vertexes: vec![(0, 0), (3, 0), (2, 2)],\n        fill: (255, 255, 255),\n        stroke_width: 5,\n    };\n\n    // triangle1を元にvertexesだけ異なる新しい値を作る\n    #[allow(unused_variables)]\n    let triangle2 = Polygon {\n        vertexes: vec![(0, 0), (-3, 0), (-2, 2)],\n        .. triangle1\n    };\n}\n"
  },
  {
    "path": "ch05/ex05/examples/ch05_14_struct2.rs",
    "content": "#[allow(dead_code)]\n// #[derive(Default)]\nstruct Polygon {\n    vertexes: Vec<(i32, i32)>,\n    stroke_width: u8,\n    fill: (u8, u8, u8),\n}\n\nimpl Default for Polygon {\n    fn default() -> Self {\n        Self {\n            stroke_width: 1,               // デフォルト値を1にする\n            vertexes: Default::default(),  // Vec<(i32, i32)>のDefault実装を使う\n            fill: Default::default(),      // (u8, u8, u8)のDefault実装を使う\n        }\n    }\n}\n\nfn main() {\n    // すべてのフィールドがデフォルト値を持つPolygonを作成する\n    #[allow(unused_variables)]\n    let polygon1: Polygon = Default::default();\n\n    // vertexesフィールドだけ別の値に設定し、他はデフォルト値にする\n    #[allow(unused_variables)]\n    let polygon2 = Polygon {\n        vertexes: vec![(0, 0), (3, 0), (2, 2)],\n        .. Default::default()\n    };\n}\n"
  },
  {
    "path": "ch05/ex05/examples/ch05_15_struct3.rs",
    "content": "struct Triangle(Vertex, Vertex, Vertex);\nstruct Vertex(i32, i32);\n\nfn main() {\n    let vx0 = Vertex(0, 0);\n    let vx1 = Vertex(3, 0);\n    let triangle = Triangle(vx0, vx1, Vertex(2, 2));\n\n    assert_eq!((triangle.1).0, 3);\n}\n"
  },
  {
    "path": "ch05/ex05/examples/ch05_16_struct4.rs",
    "content": "struct UserName(String);\nstruct Id(u64);\nstruct Timestamp(u64);\ntype User = (Id, UserName, Timestamp);\n\n#[allow(dead_code)]\nfn new_user(name: UserName, id: Id, created: Timestamp) -> User {\n    (id, name, created)\n}\n\n#[allow(unused_variables)]\nfn main() {\n    let id = Id(400);\n    let now = Timestamp(4567890123);\n\n    // nowとidの順番を間違えるとコンパイルエラーになってくれる\n    // let bad_user = new_user(UserName(String::from(\"kazuki\")), now, id);\n    // error[E0308]: mismatched types\n    // expected type `Id`, found type `Timestamp`\n}\n"
  },
  {
    "path": "ch05/ex05/examples/ch05_17_struct5.rs",
    "content": "#[derive(Debug, PartialEq)]\nstruct UniqueValue;\n// 以下の形式も可能\n// struct UniqueValue {}\n// struct UniqueValue();\n\nfn main() {\n    // フィールドがないので作れる値は1つのみ\n    let uv1 = UniqueValue;\n    let uv2 = UniqueValue;\n    assert_eq!(uv1, uv2);\n}\n"
  },
  {
    "path": "ch05/ex05/examples/ch05_18_enum1.rs",
    "content": "// 平日を表すWeekday型を定義する\n// Debugトレイトを自動導出すると\"{:?}\"で表示できるようになる\n// PartialEqトレイトを自動導出すると==演算子が使えるようになる\n#[allow(dead_code)]\n#[derive(Debug, PartialEq)]\nenum Weekday {\n    // Weekday型には以下のバリアントがある。\n    Monday, Tuesday, Wednesday, Thursday, Friday,\n}\n\n// 月を表すMonth型を定義する\n#[allow(dead_code)]\nenum Month {\n    // バリアントにisize型の整数値を割り当てられる\n    January = 1, February = 2, March = 3, /* 中略 */  December = 12,\n}\n\nfn say_something(weekday: Weekday) {\n    if weekday == Weekday::Friday {\n        println!(\"TGIF!\"); // Thank God, it’s Friday（やっと金曜日だ）\n    } else {\n        println!(\"まだ{:?}か\", weekday);\n    }\n}\n\nfn main() {\n    say_something(Weekday::Friday);\n\n    assert_eq!(3, Month::March as isize); // isize型にキャストすると割り当てた値が得られる\n}\n"
  },
  {
    "path": "ch05/ex05/examples/ch05_19_enum2.rs",
    "content": "type UserName = String;\n\n#[allow(dead_code)]\n#[derive(Debug)]\nenum Task {\n    Open,\n    AssignedTo(UserName),\n    Working {\n        assignee: UserName,\n        remaining_hours: u16,\n    },\n    Done,\n}\n\n// use宣言でTaskが持つバリアントをインポートするとバリアント名が直接書けるようになる\nuse crate::Task::*;\n\nfn main() {\n    // Task型の値を3つ作り、ベクタに格納する\n    let tasks = vec![\n        // もし上のuse宣言がなかったらTask::AssignedToと書かないといけない\n        AssignedTo(String::from(\"junko\")),\n        Working {\n            assignee: String::from(\"hiro\"),\n            remaining_hours: 18,\n        },\n        Done,\n    ];\n\n    // 個々のタスクの状況をレポートする。\n    for (i, task) in tasks.iter().enumerate() {\n        // match式によるパターンマッチでバリアントを識別し、フィールド値を取り出す\n        match task {\n            AssignedTo(assignee) => {\n                println!(\"タスク{}は{}さんにアサインされています\", i, assignee)\n            }\n            Working { assignee, remaining_hours } => {\n                println!(\"タスク{}は{}さんが作業中です。残り{}時間の見込み\",\n                        i, assignee, remaining_hours)\n            }\n            _ => println!(\"タスク{}はその他のステータス（{:?}）です\", i, task)\n        }\n    }\n}\n"
  },
  {
    "path": "ch05/ex05/examples/ch05_20_adv_types1.rs",
    "content": "#[allow(dead_code)]\n#[derive(Default)]\npub struct Polygon<T> {\n    pub vertexes: Vec<T>,\n    pub stroke_width: u8,\n    pub fill: (u8, u8, u8),\n    internal_id: String,\n}\n\n// 座標\ntrait Coordinates {}\n\n// デカルト座標\n#[allow(dead_code)]\n#[derive(Default)]\nstruct CartesianCoord {\n    x: f64,\n    y: f64,\n}\nimpl Coordinates for CartesianCoord {}\n\n// 極座標\n#[allow(dead_code)]\n#[derive(Default)]\nstruct PolarCoord {\n    r: f64,\n    theta: f64,\n}\nimpl Coordinates for PolarCoord {}\n\nfn main() {\n    let vertexes = vec![\n        CartesianCoord {x:  0.0, y:  0.0},\n        CartesianCoord {x: 50.0, y:  0.0},\n        CartesianCoord {x: 30.0, y: 20.0},\n    ];\n\n    #[allow(unused_variables)]\n    // Polygon<CartesianCoord>型\n    let poly = Polygon { vertexes, .. Default::default() };\n}\n"
  },
  {
    "path": "ch05/ex05/examples/ch05_21_adv_types2.rs",
    "content": "#[derive(Default)]\nstruct A {\n    f0: u8,\n    f1: u32,\n    f2: u8,\n}\n\nfn main() {\n    let a: A = Default::default();\n    println!(\n        \"struct A ({} bytes)\\n  f0: {:p}\\n  f1: {:p}\\n  f2: {:p}\\n\",\n        std::mem::size_of::<A>(),\n        &a.f0,\n        &a.f1,\n        &a.f2\n    );\n}\n"
  },
  {
    "path": "ch05/ex05/examples/ch05_22_type_cast1.rs",
    "content": "fn main() {\n    let i1 = 42; // i32型\n    #[allow(unused_variables)]\n    let f1 = i1 as f64 / 2.5;  // i32型からf64型へキャスト\n\n    let c1 = 'a';\n    assert_eq!(97, c1 as u32); // char型からu32型へキャスト\n\n    let i2 = 300;       // i32型\n    let u1 = i2 as u8;  // u8型へキャスト\n\n    // 300はu8型の最大値を超えているので桁あふれして44になる（300を256で割った余りは44）\n    assert_eq!(44, u1);\n}\n"
  },
  {
    "path": "ch05/ex05/examples/ch05_23_type_cast2.rs",
    "content": "fn main() {\n    let t1 = ('a', 42);\n    // let t2 = t1 as (u32, u8);\n    // → error[E0605]: non-primitive cast: `(char, i32)` as `(u32, u8)`\n\n    let v1 = vec![b'h', b'e', b'l', b'l', b'o']; // Vec<u8>型\n    // let v2 = v1 as Vec<u16>;\n    // → error[E0605]: non-primitive cast:\n    //   `std::vec::Vec<u8>` as `std::vec::Vec<u16>`\n\n    #[allow(unused_variables)]\n    let t3 = (t1.0 as u32, t1.1 as u8);\n    #[allow(unused_variables)]\n    let v3 = v1.iter().map(|&n| n as u16).collect::<Vec<u16>>();\n\n    // &str型はVec<u8>型への変換を対象としたFromトレイトを実装している\n    let v4: Vec<u8> = From::from(\"hello\");\n    assert_eq!(v1, v4);\n}\n"
  },
  {
    "path": "ch05/ex05/examples/ch05_24_transmute.rs",
    "content": "fn main() {\n    let p1 = Box::new(10);  // Box<i32>型\n\n    // boxポインタを生ポインタ*mut i32型に変換したいが型キャストできない\n    // let p2 = p1 as *mut i32;\n    // → error[E0605]: non-primitive cast: ...\n\n    // Boxポインタと*mutポインタはどちらも同じビット幅なのでtransmuteできる\n    #[allow(unused_variables)]\n    let p3: *mut i32 = unsafe { std::mem::transmute(p1) };\n\n    let f1 = 5.6789e+3_f32;  // 5678.9\n\n    // f32型からi32型へ型キャストする。小数点以下は切り捨てられる\n    let i1 = f1 as i32;\n    println!(\"{}\", i1);   // 5678と表示される\n\n    // f32型からi32型へtransmuteする\n    let i2: i32 = unsafe { std::mem::transmute(f1) };\n    println!(\"{}\", i2);   // 浮動小数点数を整数として再解釈した値1169258291が表示される\n}\n"
  },
  {
    "path": "ch05/ex05/examples/ch05_25_type_coercion1.rs",
    "content": "fn main() {\n    intro();\n    coercion_sites();\n    transitivity();\n}\n\nfn intro() {\n    // 整数リテラル3、4、5は通常はi32型と解釈されるが、\n    // 型アノテーション（型注釈）によってu8型へと型強制されている\n    let v1: Vec<u8> = vec![3, 4, 5];\n\n    // もし型強制がなかったらこう書かなければならない\n    // let v1 = vec![3u8, 4u8, 5u8];\n\n    // Vec<u8>型からスライス&[u8]型へ型強制されることによって\n    // スライスに備わったfirst(&self)メソッドが使用できる\n    assert_eq!(Some(&3u8), v1.first());\n\n    // もし型強制がなかったらこう書かなければならない\n    // assert_eq!(Some(&3u8), (&v1[..]).first());\n\n    let mut s1 = String::from(\"Type coercion \");\n    let s2 = String::from(\"is actually easy.\");\n\n    // push_str()のシグネチャはpush_str(self: &mut String, s: &str)\n    // 型強制によってs1がString型から&mut String型へ変換され、\n    // &s2は&String型から&str型へ変換される\n    s1.push_str(&s2);\n\n    // もし型強制がなかったらこう書かなければならない\n    // (&mut s1).push_str(s2.as_str());\n}\n\nfn coercion_sites() {\n    let mut _i1 = 0u8;  // i1はu8型だと型推論される\n    _i1 = 255;          // よって255はu8型へ型強制される\n}\n\nfn transitivity() {\n    let p1 = &&&&[1, 2, 3, 4];  // &&&&[i32; 4]型\n\n    // 型強制が&&&&a1 → &&&a1 → &&a1 → &a1の順に推移的に作用する\n    #[allow(unused_variables)]\n    let p2: &[i32; 4] = p1;\n\n    let p3 = &&[1, 2, 3, 4];  // &&[i32; 4]型\n\n    // 配列への参照&&[i32; 4]型からスライス&[i32]型まで段階を踏むと型強制できる\n    let p4: &[i32; 4] = p3;\n    #[allow(unused_variables)]\n    let p5: &[i32] = p4;\n\n    // しかし一度にはできない（rustc 1.31.0）\n    // let p6: &[i32] = p3;\n    // → error[E0308]: mismatched types\n    //   expected type `&[i32]`, found type `&&[i32; 4]`\n}\n"
  },
  {
    "path": "ch05/ex05/examples/ch05_26_type_coercion2.rs",
    "content": "fn f1(n: &mut usize, str: &str, slice: &[i32]) {\n    *n = str.len() + slice.len()\n}\n\nfn main() {\n    let mut b1 = Box::new(0);  // Box<usize>型\n    let s1 = String::from(\"deref\");\n    let v1 = vec![1, 2, 3];\n\n    // Derefによる型強制が起こる：\n    // - &mut Box<usize> → &mut usize\n    // - &String → &str\n    // - &Vec<i32> → &[i32]\n    f1(&mut b1, &s1, &v1);\n    assert_eq!(8, *b1);\n}\n"
  },
  {
    "path": "ch05/ex05/examples/ch05_27_type_coercion3.rs",
    "content": "fn f1(slice: &[usize]) -> usize {\n    slice.len()\n}\n\nfn f2(slice: &mut [usize]) {\n    // ポインタの弱体化により&mut [usize]型から&[usize]型へ型強制される\n    let len = f1(slice);\n    slice[0] = len;\n}\n\nfn main() {\n    let mut v = vec![0; 10];\n    f2(&mut v[..]);\n    assert_eq!(10, v[0]);\n}\n"
  },
  {
    "path": "ch05/ex05/examples/ch05_28_type_coercion4.rs",
    "content": "fn f1(p: &[i32])     -> i32 { p[0] }\nfn f2(p: Box<[i32]>) -> i32 { p[0] }\n\nfn main() {\n    let a1 = [1, 2, 3, 4];\n    assert_eq!(1, f1(&a1));           // &[i32; 4] → &[i32]\n    assert_eq!(1, f2(Box::new(a1)));  // Box<[i32; 4]> → Box<[i32]>\n\n    // dの型をDebugトレイトのトレイトオブジェクトに指定する\n    let mut _d: Box<std::fmt::Debug>;\n\n    // Debugトレイトを実装する型はトレイトオブジェクトへ型強制できる\n    _d = Box::new([1, 2]);   // Box<[i32; 2]>  → Box<dyn Debug>\n    _d = Box::new(Some(1));  // Box<Some<i32>> → Box<dyn Debug>\n}\n"
  },
  {
    "path": "ch05/ex05/examples/ch05_29_type_coercion5.rs",
    "content": "fn main() {\n    let v1: Vec<u8> = vec![3, 4, 5];\n    assert_eq!(v1.first(), Some(&3u8));  // first()メソッドのレシーバはv1が束縛されたベクタ\n}\n"
  },
  {
    "path": "ch05/ex05/tests/integration_tests.rs",
    "content": "use cli_test_dir::*;\n\n// バイナリを実行して入出力を確認するテスト\n// `cargo test` で実行できる\n\n#[test]\nfn run_ch05_01() {\n    let testdir = TestDir::new(\"./examples/ch05_01_box\", \"Run ch05_01\");\n    let output = testdir.cmd().expect_success();\n    assert!(output.stdout_str().is_empty());\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch05_02() {\n    let testdir = TestDir::new(\"./examples/ch05_02_vec\", \"Run ch05_02\");\n    let output = testdir.cmd().expect_success();\n    assert!(output.stdout_str().is_empty());\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch05_03() {\n    let testdir = TestDir::new(\"./examples/ch05_03_boxed_slice\", \"Run ch05_03\");\n    let output = testdir.cmd().expect_success();\n    assert_eq!(\n        output.stdout_str(),\n        r#\"v1 len: 5, capacity: 8\nv1 len: 5, capacity: 5\n\"#\n    );\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch05_04() {\n    let testdir = TestDir::new(\"./examples/ch05_04_hash_map\", \"Run ch05_04\");\n    let output = testdir.cmd().expect_success();\n    assert!(output.stdout_str().is_empty());\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch05_05() {\n    let testdir = TestDir::new(\"./examples/ch05_05_string1\", \"Run ch05_05\");\n    let output = testdir.cmd().expect_success();\n    assert!(output.stdout_str().is_empty());\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch05_06() {\n    let testdir = TestDir::new(\"./examples/ch05_06_string2\", \"Run ch05_06\");\n    let output = testdir.cmd().expect_success();\n    assert_eq!(\n        output.stdout_str(),\n        \"Err(ParseFloatError { kind: Invalid })\\n\"\n    );\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch05_07() {\n    let testdir = TestDir::new(\"./examples/ch05_07_string3\", \"Run ch05_07\");\n    let output = testdir.cmd().expect_success();\n    assert!(output.stdout_str().is_empty());\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch05_08() {\n    let testdir = TestDir::new(\"./examples/ch05_08_string4\", \"Run ch05_08\");\n    let output = testdir.cmd().expect_success();\n    assert!(output.stdout_str().is_empty());\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch05_09() {\n    let testdir = TestDir::new(\"./examples/ch05_09_range\", \"Run ch05_09\");\n    let output = testdir.cmd().expect_success();\n    assert!(output.stdout_str().is_empty());\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch05_10() {\n    let testdir = TestDir::new(\"./examples/ch05_10_option\", \"Run ch05_10\");\n    let output = testdir.cmd().expect_success();\n    assert!(output.stdout_str().is_empty());\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch05_11() {\n    let testdir = TestDir::new(\"./examples/ch05_11_result\", \"Run ch05_11\");\n    let output = testdir.cmd().expect_success();\n    assert_eq!(\n        output.stdout_str(),\n        \"Err(ParseIntError { kind: InvalidDigit })\\n\"\n    );\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch05_12() {\n    let testdir = TestDir::new(\"./examples/ch05_12_type_alias\", \"Run ch05_12\");\n    let output = testdir.cmd().expect_success();\n    assert!(output.stdout_str().is_empty());\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch05_13() {\n    let testdir = TestDir::new(\"./examples/ch05_13_struct1\", \"Run ch05_13\");\n    let output = testdir.cmd().expect_success();\n    assert!(output.stdout_str().is_empty());\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch05_14() {\n    let testdir = TestDir::new(\"./examples/ch05_14_struct2\", \"Run ch05_14\");\n    let output = testdir.cmd().expect_success();\n    assert!(output.stdout_str().is_empty());\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch05_15() {\n    let testdir = TestDir::new(\"./examples/ch05_15_struct3\", \"Run ch05_15\");\n    let output = testdir.cmd().expect_success();\n    assert!(output.stdout_str().is_empty());\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch05_16() {\n    let testdir = TestDir::new(\"./examples/ch05_16_struct4\", \"Run ch16_??\");\n    let output = testdir.cmd().expect_success();\n    assert!(output.stdout_str().is_empty());\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch05_17() {\n    let testdir = TestDir::new(\"./examples/ch05_17_struct5\", \"Run ch05_17\");\n    let output = testdir.cmd().expect_success();\n    assert!(output.stdout_str().is_empty());\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch05_18() {\n    let testdir = TestDir::new(\"./examples/ch05_18_enum1\", \"Run ch05_18\");\n    let output = testdir.cmd().expect_success();\n    assert_eq!(output.stdout_str(), \"TGIF!\\n\");\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch05_19() {\n    let testdir = TestDir::new(\"./examples/ch05_19_enum2\", \"Run ch05_19\");\n    let output = testdir.cmd().expect_success();\n    assert_eq!(\n        output.stdout_str(),\n        r#\"タスク0はjunkoさんにアサインされています\nタスク1はhiroさんが作業中です。残り18時間の見込み\nタスク2はその他のステータス（Done）です\n\"#,\n    );\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch05_20() {\n    let testdir = TestDir::new(\"./examples/ch05_20_adv_types1\", \"Run ch05_20\");\n    let output = testdir.cmd().expect_success();\n    assert!(output.stdout_str().is_empty());\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch05_21() {\n    let testdir = TestDir::new(\"./examples/ch05_21_adv_types2\", \"Run ch05_21\");\n    let output = testdir.cmd().expect_success();\n\n    use regex::Regex;\n    let re = Regex::new(\n        r#\"(?m)\\Astruct A \\(\\d{1,2} bytes\\)\n  f0: 0x[0-9a-f]+\n  f1: 0x[0-9a-f]+\n  f2: 0x[0-9a-f]+\n\n\\z\"#,\n    )\n    .expect(\"Failed to compile a regex pattern\");\n\n    assert!(re.is_match(output.stdout_str()));\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch05_22() {\n    let testdir = TestDir::new(\"./examples/ch05_22_type_cast1\", \"Run ch05_22\");\n    let output = testdir.cmd().expect_success();\n    assert!(output.stdout_str().is_empty());\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch05_23() {\n    let testdir = TestDir::new(\"./examples/ch05_23_type_cast2\", \"Run ch05_23\");\n    let output = testdir.cmd().expect_success();\n    assert!(output.stdout_str().is_empty());\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch05_24() {\n    let testdir = TestDir::new(\"./examples/ch05_24_transmute\", \"Run ch05_24\");\n    let output = testdir.cmd().expect_success();\n    assert_eq!(\n        output.stdout_str(),\n        r#\"5678\n1169258291\n\"#\n    );\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch05_25() {\n    let testdir = TestDir::new(\"./examples/ch05_25_type_coercion1\", \"Run ch05_25\");\n    let output = testdir.cmd().expect_success();\n    assert!(output.stdout_str().is_empty());\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch05_26() {\n    let testdir = TestDir::new(\"./examples/ch05_26_type_coercion2\", \"Run ch05_26\");\n    let output = testdir.cmd().expect_success();\n    assert!(output.stdout_str().is_empty());\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch05_27() {\n    let testdir = TestDir::new(\"./examples/ch05_27_type_coercion3\", \"Run ch05_27\");\n    let output = testdir.cmd().expect_success();\n    assert!(output.stdout_str().is_empty());\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch05_28() {\n    let testdir = TestDir::new(\"./examples/ch05_28_type_coercion4\", \"Run ch05_28\");\n    let output = testdir.cmd().expect_success();\n    assert!(output.stdout_str().is_empty());\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch05_29() {\n    let testdir = TestDir::new(\"./examples/ch05_29_type_coercion5\", \"Run ch05_29\");\n    let output = testdir.cmd().expect_success();\n    assert!(output.stdout_str().is_empty());\n    assert!(output.stderr_str().is_empty());\n}\n"
  },
  {
    "path": "ch06/leap-year/.gitignore",
    "content": "# コンパイラが生成する成果物や中間ファイルが置かれる\ntarget/\n"
  },
  {
    "path": "ch06/leap-year/Cargo.toml",
    "content": "[package]\nname = \"leap-year\"\nversion = \"0.1.0\"\nauthors = [\"Rust Bicycle Book <bicycle-book@example.com>\"]\nedition = \"2018\"\n\n[dependencies]\n\n[dev-dependencies]\ncli_test_dir = \"0.1\"\n"
  },
  {
    "path": "ch06/leap-year/src/main.rs",
    "content": "// 第6章 基本構文\n// 入力された年がうるう年かどうかを判断するプログラム\n\n// `std::io` 名前空間を `io` としてインポート\nuse std::io;\n// `std::io::Write` トレイトを使う\nuse std::io::Write;\n\n// エントリポイントとなる関数\nfn main() {\n    let mut year = String::new();\n    print!(\"Please input a year to check if it is a leap year: \");\n    io::stdout().flush().unwrap();\n    io::stdin().read_line(&mut year).unwrap();\n    let year = year.trim().parse::<u32>().unwrap();\n\n    if is_leap_year(year) {\n        println!(\"{} is a leap year!\", year);\n    } else {\n        println!(\"{} is not a leap year.\", year);\n    }\n}\n\n// うるう年の場合は `true` 、平年の場合は `false` を返す関数\nfn is_leap_year(year: u32) -> bool {\n    year % 4 == 0 && !(year % 100 == 0 && year % 400 != 0)\n}\n"
  },
  {
    "path": "ch06/leap-year/tests/integration_tests.rs",
    "content": "use cli_test_dir::*;\n\n// バイナリ（leap-year）を実行して入出力を確認するテスト\n// `cargo test` で実行できる\n\nconst CMD: &'static str = \"./leap-year\";\n\n#[test]\nfn year_2000_is_leap_year() {\n    let testdir = TestDir::new(CMD, \"Test year 2000\");\n    let output = testdir\n        .cmd()\n        .output_with_stdin(\"2000\\n\")\n        // .tee_output()   // stdoutとstderrorを順に表示する。デバッグに便利\n        .expect_success();\n    assert!(output.stdout_str().contains(\"2000 is a leap year!\"));\n}\n\n#[test]\nfn year_2019_is_not_leap_year() {\n    let testdir = TestDir::new(CMD, \"Test year 2019\");\n    let output = testdir.cmd().output_with_stdin(\"2019\\n\").expect_success();\n    assert!(output.stdout_str().contains(\"2019 is not a leap year.\"));\n}\n\n#[test]\nfn year_2020_is_leap_year() {\n    let testdir = TestDir::new(CMD, \"Test year 2020\");\n    let output = testdir.cmd().output_with_stdin(\"2020\\n\").expect_success();\n    assert!(output.stdout_str().contains(\"2020 is a leap year!\"));\n}\n\n#[test]\nfn year_2100_is_not_leap_year() {\n    let testdir = TestDir::new(CMD, \"Test year 2100\");\n    let output = testdir.cmd().output_with_stdin(\"2100\\n\").expect_success();\n    assert!(output.stdout_str().contains(\"2100 is not a leap year.\"));\n}\n"
  },
  {
    "path": "ch07/ex07/.gitignore",
    "content": "# Cargoが選択した依存ライブラリのバージョン郡\nCargo.lock\n\n# コンパイラが生成する成果物や中間ファイルが置かれる\ntarget/\n"
  },
  {
    "path": "ch07/ex07/Cargo.toml",
    "content": "[package]\nname = \"ex07\"\nversion = \"0.1.0\"\nauthors = [\"Rust Bicycle Book <bicycle-book@example.com>\"]\nedition = \"2018\"\n\n[dependencies]\nlazy_static = \"1.2.0\"\n\n[dev-dependencies]\ncli_test_dir = \"0.1\"\n"
  },
  {
    "path": "ch07/ex07/examples/ch07_01_value_scope.rs",
    "content": "// 構造体を定義する\n// println!の\"{:?}\"で表示できるようにDebugトレイトを自動導出しておく\n#[derive(Debug)]\nstruct Parent(usize, Child, Child); // Parentはusizeに加えてChildを2つ持つ\n\nuse std::ops::Drop;\n\n// Parent構造体にデストラクタを実装する\nimpl Drop for Parent {\n    fn drop(&mut self) {\n        println!(\"Dropping {:?}\", self);\n    }\n}\n\n#[derive(Debug)]\nstruct Child(usize);\n\n// Child構造体にデストラクタを実装する\nimpl Drop for Child {\n    fn drop(&mut self) {\n        println!(\"Dropping {:?}\", self);\n    }\n}\n\nfn main() {\n    let p1 = Parent(1, Child(11), Child(12));\n\n    {   // ブロックを作りp2はその中で導入する\n        let p2 = Parent(2, Child(21), Child(22));\n        println!(\"(a)  p1: {:?}, p2: {:?}\", p1, p2);  // (a)の時点\n    }\n\n    println!(\"(b)  p1: {:?}\", &p1);                   // (b)の時点\n    let p3 = Parent(3, Child(31), Child(32));\n    println!(\"(c)  p1: {:?}, p3: {:?}\", p1, p3);      // (c)の時点\n}\n"
  },
  {
    "path": "ch07/ex07/examples/ch07_02_move_semantics.rs",
    "content": "#[derive(Debug)]\nstruct Parent(usize, Child, Child);\n\nuse std::ops::Drop;\n\nimpl Drop for Parent {\n    fn drop(&mut self) {\n        println!(\"Dropping {:?}\", self);\n    }\n}\n\n#[derive(Debug)]\nstruct Child(usize);\n\nimpl Drop for Child {\n    fn drop(&mut self) {\n        println!(\"Dropping {:?}\", self);\n    }\n}\n\nfn main() {\n    println!(\"Move Semantics:\");\n    move_semantics();\n    println!(\"\\nBorrow:\");\n    borrow();\n}\n\nfn move_semantics() {\n    let mut p1 = Parent(1, Child(11), Child(12));\n    let p2 = p1;                // 値の所有権をp1からp2にムーブする\n    println!(\"p2: {:?}\", p2);\n    // println!(\"p1: {:?}\", &p1); // p1は値の所有権を失ったためアクセス不可\n    // → error[E0382]: borrow of moved value: `p1`\n\n    p1 = Parent(2, Child(21), Child(22)); // p1を別の値に束縛する\n    println!(\"p1: {:?}\", p1); // p1は別の値の所有権を持つためアクセスできる\n}\n\n// Parentへの不変の参照を引数にとる\nfn f1(p: &Parent) {\n    println!(\"p:  {:?}\", p);\n}\n\n// Parentへの可変の参照を引数にとる\nfn f2(p: &mut Parent) {\n    p.0 *= 1;\n}\n\nfn borrow() {\n    let mut p1 = Parent(1, Child(11), Child(12));\n    f1(&p1);                   // f1には所有権をムーブせず、不変の参照を渡す\n    f2(&mut p1);               // f2には所有権をムーブせず、可変の参照を渡す\n    println!(\"p1: {:?}\", p1);  // p1は値の所有権を失っていないのでアクセスできる\n}\n"
  },
  {
    "path": "ch07/ex07/examples/ch07_03_nll.rs",
    "content": "use std::collections::HashMap;\n\n// この関数はHashMapにキーに対応する値がある場合はそれを変更し\n// ない場合はデフォルト値を挿入する\nfn process_or_default(key: char, map: &mut HashMap<char, String>) {\n    // get_mutが返す可変の参照が生存している間はmapの可変の借用が有効\n    match map.get_mut(&key) {\n        // valueが可変の参照に束縛される\n        // つまりvalueが生存している間はmapの可変の借用が有効となる\n        Some(value) => value.push_str(\", world!\"),\n        None => {  // このブロック内ではselfの可変の借用は終了している\n            // insertはselfの可変の借用をとる\n            map.insert(key, Default::default());\n        }\n    }\n}\n\nfn main() {\n    let mut map = HashMap::new();\n    map.insert('h', \"Hello\".to_string());\n    process_or_default('h', &mut map);\n}\n"
  },
  {
    "path": "ch07/ex07/examples/ch07_04_static_lifetime.rs",
    "content": "#[allow(dead_code)]\nstatic I0: i32 = 42;           // static変数。'staticスコープを持つ\n\n// この関数は'staticライフタイムを持つ任意の型を引数にとる\nfn take_static<T: 'static>(_x: T) { }\n\nfn main() {\n    #[allow(unused_mut)]\n    let mut s0: &'static str;\n    let s1 = \"42\";             // &str型。文字列リテラル（データは静的領域にある）\n    let s2 = 42.to_string();   // String型（データはヒープ領域にある）\n    s0 = s1;                   // 文字列リテラルへの参照は'staticライフタイムを持つ\n    // s0 = &s2;               // コンパイルエラー。String型から&'static strは作れない\n    // → error[E0597]: `s2` does not live long enough\n    \n    println!(\"{}\", s0);\n\n    take_static(s1);           // &'static str型。OK\n    // take_static(&s2);       // &String型。コンパイルエラー（'static要求を満たせない）\n    take_static(s2);           // String型。OK\n}\n"
  },
  {
    "path": "ch07/ex07/examples/ch07_05_rc.rs",
    "content": "#[derive(Debug)]\nstruct Child(usize);\n\nimpl Drop for Child {\n    fn drop(&mut self) {\n        println!(\"Dropping {:?}\", self);\n    }\n}\n\nuse std::rc::Rc;\n\nfn main() {\n    let mut rc1 = Rc::new(Child(1));  // Rcポインタ経由でChild値をヒープ領域に格納する\n    // strong_countでこのChild値の参照カウント（共同所有者の数）が得られる\n    println!(\"(a) count: {}, rc1: {:?}\", Rc::strong_count(&rc1), rc1);\n    {\n        let rc2 = Rc::clone(&rc1);  // cloneで共同所有者を作る。参照カウントが増える\n        println!(\n            \"(b) count: {}, rc1: {:?}, rc2: {:?}\",\n            Rc::strong_count(&rc1), rc1, rc2\n        );\n    }  // rc2がスコープを抜け、参照カウントが減る\n    println!(\"(c) count: {}, rc1: {:?}\", Rc::strong_count(&rc1), rc1);\n\n    // 参照カウントが1のときは可変の参照が得られる。そうでないときはNoneが返る\n    if let Some(child) = Rc::get_mut(&mut rc1) {\n        child.0 += 1;\n    }\n    println!(\"(d) count: {}, rc1: {:?}\", Rc::strong_count(&rc1), rc1);\n\n    let weak = Rc::downgrade(&rc1);  // Rc::downgradeでWeakポインタが得られる\n    println!(\n        \"(e) count: {}, rc1: {:?}, weak: {:?}\",\n        Rc::strong_count(&rc1),  // 参照カウントは1。Weakポインタはカウントされない\n        rc1,\n        weak,\n    );\n\n    // WeakをRcにアップグレードするとChild値にアクセスできる\n    if let Some(rc3) = weak.upgrade() {\n        println!(\n            \"(f) count: {}, rc1: {:?}, rc3: {:?}\",\n            Rc::strong_count(&rc1),\n            rc1,\n            rc3,\n        );\n    }\n\n    // rc1をドロップする（スコープを抜けたのと同じ） 参照カウントが0になりChildは破棄される\n    std::mem::drop(rc1);\n    println!(\"(g) count: 0, weak.upgrade(): {:?}\", weak.upgrade());\n}\n"
  },
  {
    "path": "ch07/ex07/examples/ch07_06_simple_refcell.rs",
    "content": "use std::cell::RefCell;\n\nstruct A {\n    #[allow(dead_code)]\n    c: char,\n    #[allow(dead_code)]\n    s: String,\n}\n\nstruct B {\n    #[allow(dead_code)]\n    c: char,\n    s: RefCell<String>,   // StringをRefCellで包む\n}\n\nfn main() {\n    //\n    // RefCellを使わない場合\n    //\n    let a = A { c: 'a', s: \"alex\".to_string() };\n    #[allow(unused_variables)]\n    let r = &a;         // 不変の参照を作る\n    // r.s.push('a');   // 不変の参照経由でフィールドを変更しようとするとコンパイルエラーになる\n    // → error[E0596]: cannot borrow `r.s` as mutable, as it is behind a `&` reference\n\n    //\n    // RefCellを使った場合\n    //\n    let b = B { c: 'a', s: RefCell::new(\"alex\".to_string()) };\n    let rb = &b;\n    rb.s.borrow_mut().push('a');     // フィールドsのデータに対する可変の参照をとる\n     {\n        let rbs = b.s.borrow();      // 不変の参照をとる\n        assert_eq!(&*rbs, \"alexa\");\n\n        // RefCellでは他の参照が有効な間に可変の参照をとろうとすると実行時にパニックする\n        // b.s.borrow_mut();  // この時点で不変の参照rbsがまだ有効\n        // → thread 'main' panicked at 'already borrowed: BorrowMutError'\n\n        // try_borrow_mutならパニックせずErrを返してくれる\n        assert!(b.s.try_borrow_mut().is_err());  // Errが返る\n    }   // rbsはここでスコープを抜ける\n    assert!(b.s.try_borrow_mut().is_ok());       // Okが返る\n}\n"
  },
  {
    "path": "ch07/ex07/examples/ch07_07_tls_refcell.rs",
    "content": "use std::cell::RefCell;\nuse std::collections::HashSet;\n\nthread_local!(\n    // TLSに変数RABBITSを作成する。thread_localマクロはmutキーワードをサポートしない\n    static RABBITS: RefCell<HashSet<&'static str>> = {\n        // 初期化のコードはそのスレッドでRABBITSが初めてアクセスされたときに実行される\n        // ここでは2要素のHashSetを作成し、可変にするためにRefCellで包んでいる\n        let rb = [\"ロップイヤー\", \"ダッチ\"].iter().cloned().collect();\n        RefCell::new(rb)\n    }\n);\n\nfn main() {\n    // TLSに置いた値にアクセスするにはwithを使う。mainスレッドのRABBITSが得られる\n    RABBITS.with(|rb| {   // &RefCell<HashSet<'static str>>型\n        assert!(rb.borrow().contains(\"ロップイヤー\"));\n        rb.borrow_mut().insert(\"ネザーランド・ドワーフ\");  // 要素を追加\n    });\n\n    std::thread::spawn(||   // 別スレッドを起動し、そこでも要素を追加する\n        RABBITS.with(|rb| rb.borrow_mut().insert(\"ドワーフホト\"))\n    ).join().expect(\"Thread error\");   // スレッドの終了を待つ\n\n    // mainスレッドのRABBITSにアクセスする\n    RABBITS.with(|rb| {\n        assert!(rb.borrow().contains(\"ネザーランド・ドワーフ\"));\n        // RABBITSはスレッドごとに持つので、別スレッドで追加した要素はここにはない\n        assert!(!rb.borrow().contains(\"ドワーフホト\"));\n    });\n}\n"
  },
  {
    "path": "ch07/ex07/examples/ch07_08_arc_rwlock.rs",
    "content": "use std::collections::HashSet;\nuse std::error::Error;\nuse std::sync::{Arc, RwLock};\n\n// ?演算子を使うためmain関数からResult型を返すようにする\nfn main() -> Result<(), Box<dyn Error>> {\n    let dogs: HashSet<_> = [\"柴\", \"トイプードル\"].iter().cloned().collect();\n    // HashSetを可変にするためにRwLockで包み、スレッド間で共有するためにArcで包む\n    let dogs = Arc::new(RwLock::new(dogs));  // Arc<RwLock<HashSet<&'static str>>>型\n\n    // PoisonErrorをStringに変換するのに便利な関数を定義しておく\n    fn stringify(x: impl ToString) -> String { x.to_string() }\n\n    {\n        let ds = dogs.read().map_err(stringify)?;    // readロックを取得する\n        assert!(ds.contains(\"柴\")); \n        assert!(ds.contains(\"トイプードル\"));\n    }   // dsがスコープを外れロックが解除される\n\n    // writeロックを取得しHashSetに要素を追加する\n    dogs.write().map_err(stringify)?.insert(\"ブル・テリア\");\n\n    let dogs1 = Arc::clone(&dogs);\n    std::thread::spawn(move ||\n        // 別のスレッドでwriteロックを取得しHashSetに要素を追加する\n        dogs1.write().map(|mut ds| ds.insert(\"コーギー\")).map_err(stringify)\n    ).join().expect(\"Thread error\")?;   // スレッドの終了を待つ\n\n    // このスレッドと別スレッドの両方で追加した要素が見える\n    assert!(dogs.read().map_err(stringify)?.contains(\"ブル・テリア\"));\n    assert!(dogs.read().map_err(stringify)?.contains(\"コーギー\"));\n    Ok(())\n}\n"
  },
  {
    "path": "ch07/ex07/examples/ch07_09_static_rwlock.rs",
    "content": "use lazy_static::lazy_static;\nuse std::collections::HashSet;\nuse std::error::Error;\nuse std::sync::RwLock;\n\nlazy_static! {\n    // staticな変数DOGSを導入する。この変数はプログラム全体で共有される\n    // refは束縛モードと呼ばれ、不変の参照を意味する\n    // lazy_staticではDOGSが初めて参照外しされたときに以下の初期化コードが実行される\n    pub static ref DOGS: RwLock<HashSet<&'static str>> = {\n        // HashSetを可変にするためにRwLockで包む\n        let dogs = [\"柴\", \"トイプードル\"].iter().cloned().collect();\n        RwLock::new(dogs)\n    };\n}\n\nfn main() -> Result<(), Box<dyn Error>> {\n    {\n        let dogs = DOGS.read()?;  // readロックを取得する\n        assert!(dogs.contains(\"柴\")); \n        assert!(dogs.contains(\"トイプードル\"));\n    }   // dogsがスコープを外れreadロックが解除される\n\n    fn stringify(x: impl ToString) -> String { x.to_string() }\n\n    // writeロックを取得しHashSetに要素を追加する\n    DOGS.write()?.insert(\"ブル・テリア\");\n\n    std::thread::spawn(||\n        // 別のスレッドでwriteロックを取得しHashSetに要素を追加する\n        DOGS.write().map(|mut ds| ds.insert(\"コーギー\")).map_err(stringify)\n    ).join().expect(\"Thread error\")?;   // スレッドの終了を待つ\n\n    // このスレッドと別スレッドの両方で追加した要素が見える\n    assert!(DOGS.read()?.contains(\"ブル・テリア\"));\n    assert!(DOGS.read()?.contains(\"コーギー\"));\n    Ok(())\n}\n"
  },
  {
    "path": "ch07/ex07/examples/ch07_10_closure.rs",
    "content": "// この関数はクロージャFとcharを引数にとる\n// FはFnを実装し、引数にcharをとり、boolを返す\nfn apply_fn<F>(f: &F, ch: char) where F: Fn(char) -> bool {\n    assert!(f(ch));  // chにクロージャを適用する。trueが返されればOK\n}\n\n// この関数はFnMutを実装したクロージャFとcharを引数にとる（Fの関数シグネチャは上と同じ）\nfn apply_fn_mut<F>(f: &mut F, ch: char) where F: FnMut(char) -> bool {\n    assert!(f(ch));\n}\n\n// この関数はFnOnceを実装したクロージャFとcharを引数にとる（Fの関数シグネチャは上と同じ）\nfn apply_fn_once<F>(f: F, ch: char) where F: FnOnce(char) -> bool {\n    assert!(f(ch));\n}\n\nfn main() {\n    let s1 = \"read-only\";\n    let mut lookup = |ch| s1.find(ch).is_some();  // find(&self)は&strを読むだけ\n\n    apply_fn(&lookup, 'r');\n    apply_fn_mut(&mut lookup, 'o');  // Fnを実装するクロージャはFnMutも実装する\n    apply_fn_once(lookup, 'y');      // FnMutを実装するクロージャはFnOnceも実装する\n    assert_eq!(s1, \"read-only\");     // 環境に取り込まれた文字列（&str型）は変更されてない\n\n    let mut s2 = \"append\".to_string();\n    let mut modify = |ch| {\n        s2.push(ch);  // push(&mut self, char)はStringを可変の参照経由で変更する\n        true\n    };\n\n    // apply_fn(&modify, 'e');       // Fnをとる関数はコンパイルエラーになる\n    //   → error[E0525]: expected a closure that implements the `Fn` trait,\n    //                   but this closure only implements `FnMut`\n\n    apply_fn_mut(&mut modify, 'e');  // FnMutをとる関数はOK\n    apply_fn_once(modify, 'd');      // FnOnceをとる関数はOK\n    assert_eq!(s2, \"appended\");      // 環境に取り込まれた文字列（String型）が変更された\n\n    let s3 = \"be converted\".to_string();\n    #[allow(unused_mut)]\n    let mut consume = |ch| {\n        let bytes = s3.into_bytes(); // into_bytes(self)はStringを消費する（所有権をとる）\n        bytes.contains(&(ch as u8))\n    };\n\n    // apply_fn(&consume, 'b');      // Fnをとる関数はコンパイルエラー\n    //   → error[E0525]: expected a closure that implements the `Fn` trait,\n    //                   but this closure only implements `FnOnce`\n\n    // apply_fn_mut(&mut consume, 'c');  // FnMutをとる関数もコンパイルエラー\n    //   → error[E0525]: expected a closure that implements the `FnMut` trait,\n    //                   but this closure only implements `FnOnce`\n    \n    apply_fn_once(consume, 'd');     // FnOnceをとる関数ならOK\n\n    // assert_eq!(s3, \"error\");      // s3はムーブ済み。コンパイルエラー\n    //   → error[E0382]: borrow of moved value: `s3`\n\n    // Fnトレイトを実装するクロージャを定義する\n    // let lookup = || assert!(s1.find('d').is_some());\n    // クロージャをspawnに渡す。クロージャにmoveがないのでコンパイルエラーになる\n    // let handle = std::thread::spawn(lookup);\n    // → error[E0373]: closure may outlive the current function, but it\n    //                 borrows `s1`, which is owned by the current function\n\n    // moveを付けるとs1が環境へムーブする\n    // クロージャがs1を所有するのでライフタイム要件を満たせる\n    let lookup = move || assert!(s1.find('d').is_some());\n    let handle = std::thread::spawn(lookup);\n    handle.join().expect(\"Failed to run thread.\");\n}\n"
  },
  {
    "path": "ch07/ex07/tests/integration_tests.rs",
    "content": "use cli_test_dir::*;\n\n// examplesディレクトリ配下にあるバイナリを実行して入出力を確認するテスト\n// `cargo test` で実行できる\n\n#[test]\nfn run_ch07_01() {\n    let testdir = TestDir::new(\"./examples/ch07_01_value_scope\", \"Run ch07_01\");\n    let output = testdir\n        .cmd()\n        //.tee_output()    // stdoutとstderrorを順に表示する。デバッグに便利\n        .expect_success();\n    assert_eq!(\n        output.stdout_str(),\n        r#\"(a)  p1: Parent(1, Child(11), Child(12)), p2: Parent(2, Child(21), Child(22))\nDropping Parent(2, Child(21), Child(22))\nDropping Child(21)\nDropping Child(22)\n(b)  p1: Parent(1, Child(11), Child(12))\n(c)  p1: Parent(1, Child(11), Child(12)), p3: Parent(3, Child(31), Child(32))\nDropping Parent(3, Child(31), Child(32))\nDropping Child(31)\nDropping Child(32)\nDropping Parent(1, Child(11), Child(12))\nDropping Child(11)\nDropping Child(12)\n\"#\n    );\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch07_02() {\n    let testdir = TestDir::new(\"./examples/ch07_02_move_semantics\", \"Run ch07_02\");\n    let output = testdir.cmd().expect_success();\n    assert_eq!(\n        output.stdout_str(),\n        r#\"Move Semantics:\np2: Parent(1, Child(11), Child(12))\np1: Parent(2, Child(21), Child(22))\nDropping Parent(1, Child(11), Child(12))\nDropping Child(11)\nDropping Child(12)\nDropping Parent(2, Child(21), Child(22))\nDropping Child(21)\nDropping Child(22)\n\nBorrow:\np:  Parent(1, Child(11), Child(12))\np1: Parent(1, Child(11), Child(12))\nDropping Parent(1, Child(11), Child(12))\nDropping Child(11)\nDropping Child(12)\n\"#\n    );\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch07_03() {\n    let testdir = TestDir::new(\"./examples/ch07_03_nll\", \"Run ch07_03\");\n    let output = testdir.cmd().expect_success();\n    assert!(output.stdout_str().is_empty());\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch07_04() {\n    let testdir = TestDir::new(\"./examples/ch07_04_static_lifetime\", \"Run ch07_04\");\n    let output = testdir.cmd().expect_success();\n    assert_eq!(output.stdout_str(), \"42\\n\");\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch07_05() {\n    let testdir = TestDir::new(\"./examples/ch07_05_rc\", \"Run ch07_05\");\n    let output = testdir.cmd().expect_success();\n    assert_eq!(\n        output.stdout_str(),\n        r#\"(a) count: 1, rc1: Child(1)\n(b) count: 2, rc1: Child(1), rc2: Child(1)\n(c) count: 1, rc1: Child(1)\n(d) count: 1, rc1: Child(2)\n(e) count: 1, rc1: Child(2), weak: (Weak)\n(f) count: 2, rc1: Child(2), rc3: Child(2)\nDropping Child(2)\n(g) count: 0, weak.upgrade(): None\n\"#\n    );\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch07_06() {\n    let testdir = TestDir::new(\"./examples/ch07_06_simple_refcell\", \"Run ch07_06\");\n    let output = testdir.cmd().expect_success();\n    assert!(output.stdout_str().is_empty());\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch07_07() {\n    let testdir = TestDir::new(\"./examples/ch07_07_tls_refcell\", \"Run ch07_07\");\n    let output = testdir.cmd().expect_success();\n    assert!(output.stdout_str().is_empty());\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch07_08() {\n    let testdir = TestDir::new(\"./examples/ch07_08_arc_rwlock\", \"Run ch07_08\");\n    let output = testdir.cmd().expect_success();\n    assert!(output.stdout_str().is_empty());\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch07_09() {\n    let testdir = TestDir::new(\"./examples/ch07_09_static_rwlock\", \"Run ch07_09\");\n    let output = testdir.cmd().expect_success();\n    assert!(output.stdout_str().is_empty());\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch07_10() {\n    let testdir = TestDir::new(\"./examples/ch07_10_closure\", \"Run ch07_10\");\n    let output = testdir.cmd().expect_success();\n    assert!(output.stdout_str().is_empty());\n    assert!(output.stderr_str().is_empty());\n}\n"
  },
  {
    "path": "ch07/toy-vec/.gitignore",
    "content": "# Cargoが選択した依存ライブラリのバージョン郡\nCargo.lock\n\n# コンパイラが生成する成果物や中間ファイルが置かれる\ntarget/\n"
  },
  {
    "path": "ch07/toy-vec/Cargo.toml",
    "content": "[package]\nname = \"toy-vec\"\nversion = \"0.1.0\"\nauthors = [\"Rust Bicycle Book <bicycle-book@example.com>\"]\nedition = \"2018\"\n\n[dependencies]\n\n[dev-dependencies]\ncli_test_dir = \"0.1\"\n"
  },
  {
    "path": "ch07/toy-vec/examples/toy_vec_01.rs",
    "content": "use toy_vec::ToyVec;\n\nfn main() {\n    let mut v = ToyVec::new();\n    v.push(\"Java Finch\".to_string());  // 桜文鳥\n    v.push(\"Budgerigar\".to_string());  // セキセイインコ\n    let e = v.get(1);\n    assert_eq!(e, Some(&\"Budgerigar\".to_string()));\n}\n"
  },
  {
    "path": "ch07/toy-vec/examples/toy_vec_02.rs",
    "content": "use toy_vec::ToyVec;\n\nfn main() {\n    let _e: Option<&String>;\n    {\n        let mut v = ToyVec::new();\n        v.push(\"Java Finch\".to_string());\n        v.push(\"Budgerigar\".to_string());\n\n        _e = v.get(1);  // コンパイルエラーになる\n        // → error[E0597]: `v` does not live long enough\n\n    }  // ここでvがスコープから抜け、ToyVec構造体が破棄される\n\n    // eは解放後のメモリを参照している\n    // assert_eq!(_e, Some(&\"Budgerigar\".to_string()));\n}\n"
  },
  {
    "path": "ch07/toy-vec/examples/toy_vec_03.rs",
    "content": "use toy_vec::ToyVec;\n\nfn main() {\n    let mut v = ToyVec::new();\n    v.push(\"Java Finch\".to_string());     // 桜文鳥\n    v.push(\"Budgerigar\".to_string());     // セキセイインコ\n\n    let mut iter = v.iter();\n\n    // v.push(\"Hill Mynah\".to_string());  // 九官鳥。コンパイルエラーになる\n    // → error[E0502]: cannot borrow `v` as mutable because it is\n    //   also borrowed as immutable\n    // pushは可変の参照を得ようとするが、iterが生存しているので不変の参照が有効\n\n    assert_eq!(iter.next(), Some(&\"Java Finch\".to_string()));\n    v.push(\"Canary\".to_string());  // カナリア。iterはもう生存していないので変更できる\n}\n"
  },
  {
    "path": "ch07/toy-vec/src/lib.rs",
    "content": "use std::fmt;\n\npub struct ToyVec<T> {\n    elements: Box<[T]>,  // T型の要素を格納する領域。各要素はヒープ領域に置かれる\n    len: usize,          // ベクタの長さ（現在の要素数）\n}\n\n// implブロック内に関連関数やメソッドを定義していく。トレイト境界としてDefaultを設定する\nimpl<T: Default> ToyVec<T> {\n\n    // newはキャパシティ（容量）が0のToyVecを作る\n    pub fn new() -> Self {\n        Self::with_capacity(0)\n    }\n\n    // with_capacityは指定されたキャパシティを持つToyVecを作る\n    pub fn with_capacity(capacity: usize) -> Self {\n        Self {\n            elements: Self::allocate_in_heap(capacity),\n            len: 0,\n        }\n    }\n\n    // T型の値がsize個格納できるBox<[T]>を返す\n    fn allocate_in_heap(size: usize) -> Box<[T]> {\n        std::iter::repeat_with(Default::default)\n            .take(size)            // T型のデフォルト値をsize個作り\n            .collect::<Vec<_>>()   // Vec<T>に収集してから\n            .into_boxed_slice()    // Box<[T]>に変換する\n    }\n\n    // ベクタの長さを返す\n    pub fn len(&self) -> usize {\n        self.len\n    }\n\n    // ベクタの現在のキャパシティを返す\n    pub fn capacity(&self) -> usize {\n        self.elements.len()   // elementsの要素数（len）がToyVecのキャパシティになる\n    }\n\n    pub fn push(&mut self, element: T) {\n        if self.len == self.capacity() {  // 要素を追加するスペースがないなら\n            self.grow();  // もっと大きいelementsを確保して既存の要素を引っ越す\n        }\n        self.elements[self.len] = element; // 要素を格納する（所有権がムーブする）\n        self.len += 1;\n    }\n\n    // elementsを拡張する（より大きなサイズで作り直す）\n    fn grow(&mut self) {\n        if self.capacity() == 0 {  // 現在のelementsが空なら\n            // 1要素分の領域を確保する\n            self.elements = Self::allocate_in_heap(1);\n        } else {\n            // 現在の2倍の領域を確保する\n            let new_elements = Self::allocate_in_heap(self.capacity() * 2);\n            // self.elementsを置き換える\n            let old_elements = std::mem::replace(&mut self.elements, new_elements);\n            // 既存の全要素を新しい領域へムーブする\n            // Vec<T>のinto_iter(self)なら要素の所有権が得られる\n            for (i, elem) in old_elements.into_vec().into_iter().enumerate() {\n                self.elements[i] = elem;\n            }\n        }\n    }\n\n    pub fn get(&self, index: usize) -> Option<&T> {\n        if index < self.len {            // インデックスが範囲内なら\n            Some(&self.elements[index])  // Some(不変の参照)を返す\n        } else {\n            None                         // 範囲外ならNoneを返す\n        }\n    }\n\n    // インデックスが範囲内なら要素への参照を返し、さもなければdefaultで与えた別の値への参照を返す\n    pub fn get_or<'a>(&'a self, index: usize, default: &'a T) -> &'a T {\n        self.get(index).unwrap_or(default)\n    }\n\n    pub fn pop(&mut self) -> Option<T> {\n        if self.len == 0 {\n            None\n        } else {\n            self.len -= 1;\n\n            // 最後の要素の所有権を得たいが、借用（&mut self）経由では所有権を奪えない\n            // let elem = self.elements[self.len];\n            //   → error[E0507]: cannot move out of borrowed content\n\n            // 代わりの値と交換するならできる（ここではデフォルト値を使用）\n            let elem = std::mem::replace(&mut self.elements[self.len], Default::default());\n            Some(elem)\n        }\n    }\n\n    // 要素へのイミュータブルな参照（Option<&T>）を返すイテレータを作る\n    // 説明のためにライフタイムを明示しているが、実際には省略できる\n    pub fn iter<'vec>(&'vec self) -> Iter<'vec, T> {\n        Iter {\n            elements: &self.elements,  // Iter構造体の定義より、ライフタイムは'vecになる\n            len: self.len,\n            pos: 0,\n        }\n    }\n\n    // 要素へのイミュータブルな参照（Option<&mut T>）を返すイテレータを作る\n    pub fn iter_mut<'vec>(&'vec mut self) -> IterMut<'vec, T> {\n        IterMut {\n            elements: &mut self.elements,\n            len: self.len,\n            pos: 0,\n        }\n    }\n\n    // 要素の所有権をとる（Option<T>）イテレータを作る\n    pub fn into_iter<'vec>(self) -> IntoIter<T> {\n        IntoIter {\n            elements: self.elements,\n            len: self.len,\n            pos: 0,\n        }\n    }\n\n}\n\nimpl<T: Default> Default for ToyVec<T> {\n    fn default() -> Self {\n        // newはキャパシティ（容量）が0のToyVecを作る\n        Self::new()\n    }\n}\n\nimpl<T: Clone + Default> Clone for ToyVec<T> {\n    fn clone(&self) -> Self {\n        let mut cloned = Self::with_capacity(self.len());\n        // 各要素のcloneを呼ぶことでdeepコピーを実現する\n        for elem in self.iter() {\n            cloned.push(elem.clone());\n        }\n        cloned\n    }\n}\n\nimpl<T: PartialEq> PartialEq for ToyVec<T> {\n    fn eq(&self, other: &Self) -> bool {\n        // スライス[T]同士を比較。各要素（T）がPartialEqを実装しているので可能になる\n        self.elements[..self.len] == other.elements[..other.len]\n    }\n}\n\nimpl<T: fmt::Debug> fmt::Debug for ToyVec<T> {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        self.elements[..self.len].fmt(f)\n    }\n}\n\n// IntoIteratorトレイトを実装するとfor式での繰り返しができるようになる\nimpl<'vec, T: Default> IntoIterator for &'vec ToyVec<T> {\n    type Item = &'vec T;            // イテレータがイテレートする値の型\n    type IntoIter = Iter<'vec, T>;  // into_iterメソッドの戻り値の型\n\n    // &ToyVec<T>に対するトレイト実装なので、selfの型はToyVec<T>ではなく&ToyVec<T>\n    fn into_iter(self) -> Self::IntoIter {\n        self.iter()\n    }\n}\n\nimpl<'vec, T: Default> IntoIterator for &'vec mut ToyVec<T> {\n    type Item = &'vec mut T;\n    type IntoIter = IterMut<'vec, T>;\n\n    // selfの型はToyVec<T>ではなく&mut ToyVec<T>\n    fn into_iter(self) -> Self::IntoIter {\n        self.iter_mut()\n    }\n}\n\nimpl<T: Default> IntoIterator for ToyVec<T> {\n    type Item = T;\n    type IntoIter = IntoIter<T>;\n\n    // selfの型はToyVec<T>\n    fn into_iter(self) -> Self::IntoIter {\n        self.into_iter()\n    }\n}\n\n//\n// 要素へのイミュータブルな参照（Option<&T>）を返すイテレータ\n//\n\n// ライフタイムの指定により、このイテレータ自身またはnext()で得た&'vec T型の値が\n// 生存してる間は、ToyVec<T>は変更できない\npub struct Iter<'vec, T> {\n    elements: &'vec Box<[T]>,\n    len: usize,\n    pos: usize,\n}\n\nimpl<'vec, T> Iterator for Iter<'vec, T> {\n    // 関連型（トレイトに関連付いた型）で、このイテレータがイテレートする要素の型を指定する\n    // 関連型は8章で説明\n    type Item = &'vec T;\n\n    // nextメソッドは次の要素を返す\n    // 要素があるなら不変の参照（&T）をSomeで包んで返し、ないときはNoneを返す\n    fn next(&mut self) -> Option<Self::Item> {\n        if self.pos >= self.len {\n            None\n        } else {\n            let res = Some(&self.elements[self.pos]);\n            self.pos += 1;\n            res\n        }\n    }\n\n    fn size_hint(&self) -> (usize, Option<usize>) {\n        (self.len, Some(self.len))\n    }\n}\n\n//\n// 要素へのミュータブルな参照（Option<&mut T>）を返すイテレータ\n//\n\npub struct IterMut<'vec, T> {\n    elements: &'vec mut Box<[T]>,  // ミュータブルな参照\n    len: usize,\n    pos: usize,\n}\n\nimpl<'vec, T> Iterator for IterMut<'vec, T> {\n    type Item = &'vec mut T;\n\n    fn next(&mut self) -> Option<Self::Item> {\n        if self.pos >= self.len {\n            None\n        } else {\n            // 要素を&'vec mut Tとして返したいが、&'a mut selfから要素を取り出すと\n            // 要素が&'a mut Tになってしまい、ライフタイム要件が満たせない\n            // そこで以下のように対応した\n            //   1. &'a mut Tを生ポインタ*mut Tに変換してライフタイムをなくす\n            //   2. *mut Tの参照外しをして要素Tにアクセス\n            //   3. 要素Tから&'vec mut Tを得る\n            let elem = unsafe { &mut *(&mut self.elements[self.pos] as *mut T) };\n            self.pos += 1;\n            Some(elem)\n        }\n    }\n\n    fn size_hint(&self) -> (usize, Option<usize>) {\n        (self.len, Some(self.len))\n    }\n}\n\n//\n// 要素の所有権をとるイテレータ。Option<T>を返す\n//\n\npub struct IntoIter<T> {\n    elements: Box<[T]>,  // ミュータブルな参照\n    len: usize,\n    pos: usize,\n}\n\nimpl<T: Default> Iterator for IntoIter<T> {\n    type Item = T;\n\n    fn next(&mut self) -> Option<Self::Item> {\n        if self.pos >= self.len {\n            None\n        } else {\n            // &mut selfから要素Tをムーブアウトできないのでreplaceでデフォルト値と交換している\n            let elem = std::mem::replace(&mut self.elements[self.pos], Default::default());\n            self.pos += 1;\n            Some(elem)\n        }\n    }\n\n    fn size_hint(&self) -> (usize, Option<usize>) {\n        (self.len, Some(self.len))\n    }\n}\n\n#[cfg(test)]\nmod tests {\n\n    use super::ToyVec;\n\n    #[test]\n    fn test_char_vec() {\n        let mut v = ToyVec::new();\n        assert_eq!(v.len(), 0);\n        assert_eq!(v.capacity(), 0);\n\n        v.push('a');\n        assert_eq!(v.capacity(), 1);\n        v.push('b');\n        assert_eq!(v.capacity(), 2);\n        v.push('c');\n        assert_eq!(v.capacity(), 4);\n        assert_eq!(v.len(), 3);\n\n        assert_eq!(v.get(2), Some(&'c'));\n        assert_eq!(v.get(3), None);\n\n        let mut iter = v.iter();\n        assert_eq!(iter.size_hint(), (3, Some(3)));\n        assert_eq!(iter.next(), Some(&'a'));\n        assert_eq!(iter.next(), Some(&'b'));\n        assert_eq!(iter.next(), Some(&'c'));\n        assert_eq!(iter.next(), None);\n\n        assert_eq!(v.pop(), Some('c'));\n        assert_eq!(v.pop(), Some('b'));\n        assert_eq!(v.pop(), Some('a'));\n        assert_eq!(v.pop(), None);\n\n        assert_eq!(v.len(), 0);\n        assert_eq!(v.capacity(), 4);\n    }\n\n    #[test]\n    fn test_string_vec() {\n        let mut v = ToyVec::new();\n        assert_eq!(v.len(), 0);\n        assert_eq!(v.capacity(), 0);\n\n        v.push(\"alfalfa\");\n        v.push(\"broccoli\");\n        v.push(\"carrot\");\n        assert_eq!(v.capacity(), 4);\n        assert_eq!(v.len(), 3);\n\n        assert_eq!(v.get(2), Some(&\"carrot\"));\n        assert_eq!(v.get(3), None);\n\n        let mut iter = v.iter();\n        assert_eq!(iter.size_hint(), (3, Some(3)));\n        assert_eq!(iter.next(), Some(&\"alfalfa\"));\n        assert_eq!(iter.next(), Some(&\"broccoli\"));\n        assert_eq!(iter.next(), Some(&\"carrot\"));\n        assert_eq!(iter.next(), None);\n\n        assert_eq!(v.pop(), Some(\"carrot\"));\n        assert_eq!(v.pop(), Some(\"broccoli\"));\n        assert_eq!(v.pop(), Some(\"alfalfa\"));\n        assert_eq!(v.pop(), None);\n\n        assert_eq!(v.len(), 0);\n        assert_eq!(v.capacity(), 4);\n    }\n\n    #[test]\n    fn test_nested_vec() {\n        let mut v = ToyVec::new();\n        assert_eq!(v.len(), 0);\n        assert_eq!(v.capacity(), 0);\n\n        let mut v1 = ToyVec::new();\n        v1.push(\"alfalfa\");\n        let mut v2 = ToyVec::new();\n        v2.push(\"broccoli\");\n        let mut v3 = ToyVec::new();\n        v3.push(\"carrot\");\n\n        v.push(v1);\n        v.push(v2);\n        v.push(v3);\n\n        assert_eq!(v.capacity(), 4);\n        assert_eq!(v.len(), 3);\n\n        assert!(v.get(2).is_some());\n        assert!(v.get(3).is_none());\n\n        let mut iter = v.iter();\n        assert_eq!(iter.size_hint(), (3, Some(3)));\n        assert!(iter.next().is_some());\n        assert!(iter.next().is_some());\n        assert!(iter.next().is_some());\n        assert!(iter.next().is_none());\n\n        let mut v1 = ToyVec::new();\n        v1.push(\"alfalfa\");\n        let mut v2 = ToyVec::new();\n        v2.push(\"broccoli\");\n        let mut v3 = ToyVec::new();\n        v3.push(\"carrot\");\n\n        assert_eq!(v.pop(), Some(v3));\n        assert_eq!(v.pop(), Some(v2));\n        assert_eq!(v.pop(), Some(v1));\n        assert_eq!(v.pop(), None);\n\n        assert_eq!(v.len(), 0);\n        assert_eq!(v.capacity(), 4);\n    }\n\n    #[test]\n    fn test_iter() {\n        let mut v = ToyVec::new();\n        v.push(1);\n        v.push(1);\n        v.push(2);\n        v.push(3);\n        v.push(5);\n\n        // このイテレータはイミュータブルな要素（Option<&i32>）を返す\n        let mut iter = v.iter();\n\n        // イテレータが有効な間でもvからの直接のget（読み出し）はできる\n        assert_eq!(v.get(4), Some(&5));\n\n        // イテレータが有効な間はvへの直接のpush（変更）はできない\n        // v.push(8);\n        // → error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable\n\n        let mut sum = 0;\n\n        // &ToyVec<T>にIntoIteratorを実装し、Iter<T>を返すようにしたので以下のように使える\n        for i in &v {\n            sum += *i;\n        }\n\n        assert_eq!(sum, [1, 1, 2, 3, 5].iter().sum());\n        assert_eq!(iter.next(), Some(&1));\n\n        assert_eq!(v.len(), 5);\n    }\n\n    #[test]\n    fn test_iter_mut() {\n        let mut v = ToyVec::new();  // ToyVec<i32>\n        v.push(1);\n        v.push(1);\n        v.push(2);\n        v.push(3);\n        v.push(5);\n\n        // このイテレータはミュータブルな要素（Option<&mut i32>）を返す\n        let mut iter = v.iter_mut();\n\n        // イテレータが有効な間はvからの直接のget（読み出し）やpush（変更）はできない\n        // v.get(0);\n        // → error[E0502]: cannot borrow `v` as immutable because it is also borrowed as mutable\n\n        iter.next().map(|i| *i *= 8);  // 最初の要素を8倍する\n\n        // &mut ToyVec<T>にIntoIteratorを実装し、IterMut<T>を返すようにしたので以下のように使える\n        for i in &mut v {\n            *i += 10;\n        }\n\n        assert_eq!(v.get(0), Some(&18));\n        assert_eq!(v.get(1), Some(&11));\n        assert_eq!(v.get(2), Some(&12));\n        assert_eq!(v.get(3), Some(&13));\n        assert_eq!(v.get(4), Some(&15));\n        assert_eq!(v.len(), 5);\n    }\n\n    #[test]\n    fn test_into_iter() {\n        let mut v = ToyVec::new();\n        v.push(1);\n        v.push(1);\n        v.push(2);\n        v.push(3);\n        v.push(5);\n\n        let mut sum = 0;\n\n        // ToyVec<T>にIntoIteratorを実装し、IntoIter<T>を返すようにしたので以下のように使える\n        for i in v {\n            sum += i;\n\n            // IntoIter<T>はToyVec<T>消費するので、作成後はvにアクセスできなくなる\n            // v.get(0);\n            // → error[E0382]: borrow of moved value: `v`\n        }\n\n        assert_eq!(sum, [1, 1, 2, 3, 5].iter().sum());\n    }\n\n}\n"
  },
  {
    "path": "ch07/toy-vec/tests/integration_tests.rs",
    "content": "use cli_test_dir::*;\n\n// バイナリを実行して入出力を確認するテスト\n// `cargo test` で実行できる\n\n#[test]\nfn run_toy_vec_01() {\n    let testdir = TestDir::new(\"./examples/toy_vec_01\", \"Run ToyVec example 01\");\n    let output = testdir.cmd().expect_success();\n    assert!(output.stdout_str().is_empty());\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_toy_vec_02() {\n    let testdir = TestDir::new(\"./examples/toy_vec_02\", \"Run ToyVec example 02\");\n    let output = testdir.cmd().expect_success();\n    assert!(output.stdout_str().is_empty());\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_toy_vec_03() {\n    let testdir = TestDir::new(\"./examples/toy_vec_03\", \"Run ToyVec example 03\");\n    let output = testdir.cmd().expect_success();\n    assert!(output.stdout_str().is_empty());\n    assert!(output.stderr_str().is_empty());\n}\n"
  },
  {
    "path": "ch08/ex08/.gitignore",
    "content": "# Cargoが選択した依存ライブラリのバージョン郡\nCargo.lock\n\n# コンパイラが生成する成果物や中間ファイルが置かれる\ntarget/\n\n# Javaのコンパイラが生成する成果物\n*.class\n"
  },
  {
    "path": "ch08/ex08/Cargo.toml",
    "content": "[package]\nname = \"ex08\"\nversion = \"0.1.0\"\nauthors = [\"Rust Bicycle Book <bicycle-book@example.com>\"]\nedition = \"2018\"\n\n[dependencies]\n\n[dev-dependencies]\ncli_test_dir = \"0.1\"\n"
  },
  {
    "path": "ch08/ex08/examples/ch08_01_trait_basics.rs",
    "content": "// デカルト座標\n#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Default)]\npub struct CartesianCoord {\n    pub x: f64,\n    pub y: f64,\n}\n\n// 極座標\n//         y\n//         ^\n//         |\n// r sin θ +   +\n//         |  / r\n//         | /\n//         |/)θ\n//         +---+--------> x\n//        O    r cos θ\npub struct PolarCoord {\n    pub r: f64,\n    pub theta: f64,\n}\n\n// 座標\npub trait Coordinates {\n    // 関数の本体は書かない\n    fn to_cartesian(self) -> CartesianCoord;\n    fn from_cartesian(cart: CartesianCoord) -> Self;\n}\n\n// デカルト座標系はそのまま\nimpl Coordinates for CartesianCoord {\n    fn to_cartesian(self) -> CartesianCoord {\n        self\n    }\n    fn from_cartesian(cart: CartesianCoord) -> Self {\n        cart\n    }\n}\n\n// 極座標系は変換が必要\nimpl Coordinates for PolarCoord {\n    fn to_cartesian(self) -> CartesianCoord {\n        CartesianCoord {\n            x: self.r * self.theta.cos(),\n            y: self.r * self.theta.sin(),\n        }\n    }\n    fn from_cartesian(cart: CartesianCoord) -> Self {\n        PolarCoord {\n            r: (cart.x * cart.x + cart.y * cart.y).sqrt(),\n            theta: (cart.y / cart.x).atan(),\n        }\n    }\n}\n\n// タプルにもトレイトを実装できる\nimpl Coordinates for (f64, f64) {\n    fn to_cartesian(self) -> CartesianCoord {\n        CartesianCoord {\n            x: self.0,\n            y: self.1,\n        }\n    }\n    fn from_cartesian(cart: CartesianCoord) -> Self {\n        (cart.x, cart.y)\n    }\n}\n\nfn main() {\n    // 値を用意する\n    let point = (1.0, 1.0);\n\n    // トレイトのメソッドを呼ぶ\n    let c = point.to_cartesian();\n    println!(\"x = {}, y = {}\", c.x, c.y);\n\n    // 同じくトレイトの関連関数を呼ぶ(後述\n    let p: PolarCoord = Coordinates::from_cartesian(c);\n    println!(\"r = {}, θ = {}\", p.r, p.theta);\n}\n"
  },
  {
    "path": "ch08/ex08/examples/ch08_02_trait_basics.rs",
    "content": "// デカルト座標\n#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Default)]\npub struct CartesianCoord {\n    pub x: f64,\n    pub y: f64,\n}\n\n// 極座標\npub struct PolarCoord {\n    r: f64,\n    theta: f64,\n}\n\n// 座標\npub trait Coordinates {\n    // 関数の本体は書かない\n    fn to_cartesian(self) -> CartesianCoord;\n    fn from_cartesian(cart: CartesianCoord) -> Self;\n}\n\n// デカルト座標系はそのまま\nimpl Coordinates for CartesianCoord {\n    fn to_cartesian(self) -> CartesianCoord {\n        self\n    }\n    fn from_cartesian(cart: CartesianCoord) -> Self {\n        cart\n    }\n}\n\n// 極座標系は変換が必要\nimpl Coordinates for PolarCoord {\n    fn to_cartesian(self) -> CartesianCoord {\n        CartesianCoord {\n            x: self.r * self.theta.cos(),\n            y: self.r * self.theta.sin(),\n        }\n    }\n    fn from_cartesian(cart: CartesianCoord) -> Self {\n        PolarCoord {\n            r: (cart.x * cart.x + cart.y * cart.y).sqrt(),\n            theta: (cart.y / cart.x).atan(),\n        }\n    }\n}\n\n// タプルにもトレイトを実装できる\nimpl Coordinates for (f64, f64) {\n    fn to_cartesian(self) -> CartesianCoord {\n        CartesianCoord {\n            x: self.0,\n            y: self.1,\n        }\n    }\n    fn from_cartesian(cart: CartesianCoord) -> Self {\n        (cart.x, cart.y)\n    }\n}\n\n// fn print_point<P: Coordinates>(point: P) {\n//     let p = point.to_cartesian();\n//     println!(\"({}, {})\", p.x, p.y)\n// }\n\n// fn print_point<P>(point: P)\n// where\n//     P: Coordinates,\n// {\n//     let p = point.to_cartesian();\n//     println!(\"({}, {})\", p.x, p.y)\n// }\n\nfn print_point(point: impl Coordinates) {\n    let p = point.to_cartesian();\n    println!(\"({}, {})\", p.x, p.y)\n}\n\n// #[allow(dead_code)]\n// fn as_cartesian<P: Coordinates + Clone>(point: &P) -> CartesianCoord {\n//     point.clone().to_cartesian()\n// }\n\n#[allow(dead_code)]\nfn as_cartesian(point: &(impl Coordinates + Clone)) -> CartesianCoord {\n    point.clone().to_cartesian()\n}\n\n// `P` を2回書くにはジェネリクスが必要\n#[allow(dead_code)]\nfn double_point<P: Coordinates>(point: P) -> P {\n    let mut cart = point.to_cartesian();\n    cart.x *= 2.0;\n    cart.y *= 2.0;\n    P::from_cartesian(cart)\n}\n\n// `(T, T)` のように `T` そのものでない型への制約はジェネリクスが必要\n#[allow(dead_code)]\nfn make_point<T>(x: T, y: T) -> CartesianCoord\nwhere\n    (T, T): Coordinates,\n{\n    (x, y).to_cartesian()\n}\n\n// ジェネリックトレイトを用意しておく\n// 後に説明するがトレイトもジェネリクスにできる\ntrait ConvertTo<Output> {\n    fn convert(&self) -> Output;\n}\n\n#[allow(dead_code)]\nfn to<T>(i: i32) -> T\nwhere\n    // `ConvertTo<T>` と型パラメータがトレイト側にある\n    // where 記法だと`i32`など具体的な型に制約がかける\n    i32: ConvertTo<T>,\n{\n    i.convert()\n}\n\nfn main() {\n    // `Coordinates`を実装している型の値に対して呼べる\n    print_point((0.0, 1.0)); // (0, 1)\n    print_point(PolarCoord {\n        r: 1.0,\n        theta: std::f64::consts::PI / 2.0,\n    }); // (0.00000000000000006123233995736766, 1)\n\n    // しかし  `Coordinates` を実装していない型の値を引数に渡そうとするとコンパイルエラーになる\n    // print_point(\"string\"); // error[E0277]: the trait bound `&str: Coordinates` is not satisfied\n}\n"
  },
  {
    "path": "ch08/ex08/examples/ch08_03_trait_basics.rs",
    "content": "// デカルト座標\n#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Default)]\npub struct CartesianCoord {\n    pub x: f64,\n    pub y: f64,\n}\n\n// 極座標\npub struct PolarCoord {\n    r: f64,\n    theta: f64,\n}\n\n// 座標\npub trait Coordinates {\n    // 関数の本体は書かない\n    fn to_cartesian(self) -> CartesianCoord;\n    fn from_cartesian(cart: CartesianCoord) -> Self;\n}\n\n// デカルト座標系はそのまま\nimpl Coordinates for CartesianCoord {\n    fn to_cartesian(self) -> CartesianCoord {\n        self\n    }\n    fn from_cartesian(cart: CartesianCoord) -> Self {\n        cart\n    }\n}\n\n// 極座標系は変換が必要\nimpl Coordinates for PolarCoord {\n    fn to_cartesian(self) -> CartesianCoord {\n        CartesianCoord {\n            x: self.r * self.theta.cos(),\n            y: self.r * self.theta.sin(),\n        }\n    }\n    fn from_cartesian(cart: CartesianCoord) -> Self {\n        PolarCoord {\n            r: (cart.x * cart.x + cart.y * cart.y).sqrt(),\n            theta: (cart.y / cart.x).atan(),\n        }\n    }\n}\n\n// タプルにもトレイトを実装できる\nimpl Coordinates for (f64, f64) {\n    fn to_cartesian(self) -> CartesianCoord {\n        CartesianCoord {\n            x: self.0,\n            y: self.1,\n        }\n    }\n    fn from_cartesian(cart: CartesianCoord) -> Self {\n        (cart.x, cart.y)\n    }\n}\n\nfn print_point(point: impl Coordinates) {\n    let p = point.to_cartesian();\n    println!(\"({}, {})\", p.x, p.y)\n}\n\nstruct Matrix([[f64; 2]; 2]);\n\ntrait LinearTransform: Coordinates {\n    fn transform(self, matrix: &Matrix) -> Self\n    where\n        Self: Sized,\n    {\n        let mut cart = self.to_cartesian();\n        let x = cart.x;\n        let y = cart.y;\n        let m = matrix.0;\n\n        cart.x = m[0][0] * x + m[0][1] * y;\n        cart.y = m[1][0] * x + m[1][1] * y;\n        Self::from_cartesian(cart)\n    }\n\n    fn rotate(self, theta: f64) -> Self\n    where\n        Self: Sized,\n    {\n        self.transform(&Matrix([\n            [theta.cos(), -theta.sin()],\n            [theta.sin(), theta.cos()],\n        ]))\n    }\n}\n\n// 継承するトレイトを全て実装しているので `LinearTransform` を `CartesianCoord` に実装できる\nimpl LinearTransform for CartesianCoord {}\n\nimpl LinearTransform for PolarCoord {\n    fn rotate(mut self, theta: f64) -> Self {\n        self.theta += theta;\n        self\n    }\n}\n\nfn main() {\n    let p = (1.0, 0.0).to_cartesian();\n    print_point(p.rotate(std::f64::consts::PI)); // (-1, 0.00000000000000012246467991473532)\n}\n"
  },
  {
    "path": "ch08/ex08/examples/ch08_04_trait_generics.rs",
    "content": "trait Init<T> {\n    fn init(t: T) -> Self;\n}\n\nimpl<T> Init<T> for Box<T> {\n    // 内部では`T`でパラメータの型を参照する\n    fn init(t: T) -> Self {\n        Box::new(t)\n    }\n}\n\nfn main() {\n    // ジェネリクスが推論可能なら省略できる\n    let _data = Box::init(\"foo\");\n    // トレイトのジェネリク型を明示するには`型名::<型>`と書く\n    let _data = Box::<f32>::init(0.1);\n    let _data: Box<f32> = Init::init(0.1);\n    let _data: Box<_> = Init::<f32>::init(0.1);\n}\n"
  },
  {
    "path": "ch08/ex08/examples/ch08_05_trait_generics.rs",
    "content": "trait As<T> {\n    fn cast(self) -> T;\n}\n\n// 実装をジェネリックにせずに個別の型に対して実装する\nimpl As<u64> for u8 {\n    fn cast(self) -> u64 {\n        self as u64\n    }\n}\n\n// 同じ`As`を`u8`に実装しているが、パラメータが異なるので問題ない\nimpl As<u32> for u8 {\n    fn cast(self) -> u32 {\n        self as u32\n    }\n}\n\nfn main() {\n    // トレイト実装で指定した型はcastに指定できる\n    let _one_u32: u32 = 1.cast();\n    let _one_u32: u64 = 1.cast();\n    // `i8` は指定していないのでこれはエラー\n    // error[E0277]: the trait bound `{integer}: As<i8>` is not satisfied\n    // let _one_u32: i8 = 1.cast();\n}\n"
  },
  {
    "path": "ch08/ex08/examples/ch08_06_overload.rs",
    "content": "// trait Overload {\n//     fn call(&self) -> &'static str;\n// }\n\n// impl Overload for i32 {\n//     fn call(&self) -> &'static str {\n//         \"i32\"\n//     }\n// }\n\n// impl Overload for str {\n//     fn call(&self) -> &'static str {\n//         \"str\"\n//     }\n// }\n\n// fn main() {\n//     assert_eq!(Overload::name(&1i32), \"i32\");\n//     assert_eq!(Overload::name(\"str\"), \"str\");\n// }\n\n// fn main() {\n//     assert_eq!(1i32.name(), \"i32\");\n//     assert_eq!(\"str\".name(), \"str\");\n// }\n\ntrait Overload1<T> {\n    fn call(&self, t: T) -> &'static str;\n}\n\nimpl Overload1<i32> for i32 {\n    fn call(&self, _: i32) -> &'static str {\n        \"(i32, i32)\"\n    }\n}\n\nimpl Overload1<char> for i32 {\n    fn call(&self, _: char) -> &'static str {\n        \"(i32, char)\"\n    }\n}\n\nfn main() {\n    assert_eq!(1i32.call(2i32), \"(i32, i32)\");\n    assert_eq!(1i32.call('c'), \"(i32, char)\");\n}\n"
  },
  {
    "path": "ch08/ex08/examples/ch08_07_trait_object.rs",
    "content": "use std::fmt::Display;\n\nfn main() {\n    let mut v: Vec<&dyn Display> = vec![];\n    v.push(&true);\n    v.push(&1i32);\n}\n\nuse std::string::ToString;\n\n// #[allow(dead_code)]\n// fn stringify(t: Box<dyn ToString>) -> String {\n//     t.to_string()\n// }\n\n// #[allow(dead_code)]\n// fn stringify<T: ToString>(t: T) -> String {\n//     t.to_string()\n// }\n\n#[allow(dead_code)]\nfn stringify(t: impl ToString) -> String {\n    t.to_string()\n}\n\n// 上記コードは以下のようなコードに展開される\n// ※ コードはイメージです。実際のものと異なることがありま\n// fn stringify(t: Box<dyn ToString>) -> String {\n//     let data = t.data;\n//     let to_string = t.to_string;\n//     to_string(&data)\n// }\n"
  },
  {
    "path": "ch08/ex08/examples/ch08_08_existential_impl_trait.rs",
    "content": "#[allow(dead_code)]\nfn to_n(n: i32) -> impl Iterator {\n    0..n\n}\n\n// use std::ops::Range;\n// #[allow(dead_code)]\n// fn to_n(n: i32) -> Range<i32> {\n//     0..n\n// }\n\n#[allow(dead_code)]\nfn to_n_even(n: i32) -> impl Iterator {\n    (0..n).filter(|i| i % 2 == 0)\n}\n\nuse std::fmt;\n\nfn one() -> impl fmt::Display {\n    1i32\n}\n\n// fn one(is_float: bool) -> impl fmt::Display {\n//     // error[E0308]: if and else have incompatible types\n//     if is_float {\n//         1.0f32\n//     } else {\n//         1i32\n//     }\n// }\n\nfn main() {\n    let mut _n = one();\n    _n = one();\n}\n\n#[allow(dead_code)]\nfn gen_counter(init: i32) -> impl FnMut() -> i32 {\n    let mut n = init;\n    move || {\n        let ret = n;\n        n += 1;\n        ret\n    }\n}\n"
  },
  {
    "path": "ch08/ex08/examples/ch08_09_associated_const.rs",
    "content": "// デカルト座標\n#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Default)]\npub struct CartesianCoord {\n    pub x: f64,\n    pub y: f64,\n}\n\n// `Dimension` を `CartesianCoord` に実装する\ntrait Dimension {\n    const DIMENSION: u32;\n}\n\nfn main() {\n    // 実装された型から定数を取り出す\n    #[allow(unused_variables)]\n    let dim = CartesianCoord::DIMENSION;\n\n    #[allow(dead_code)]\n    const DIM: u32 = CartesianCoord::DIMENSION;\n}\n\n// 09\nimpl Dimension for CartesianCoord {\n    const DIMENSION: u32 = 2;\n}\n"
  },
  {
    "path": "ch08/ex08/examples/ch08_10_associated_type.rs",
    "content": "use std::str::FromStr;\n\ntrait Server {\n    // `type 型名`で関連型を宣言できる\n    type Response;\n    // あるいは`type 型名: トレイト境界` で境界を設定することもできる\n    type Request: FromStr;\n\n    // 関連型を参照するには`Self::型名`でアクセスする\n    fn handle(&self, req: Self::Request) -> Self::Response;\n}\n\nstruct EchoServer;\n// `Server` トレイトを実装する\nimpl Server for EchoServer {\n    // トップレベルと同じように`type 型名 = 型名`で定義できる\n    type Response = String;\n    // トレイト境界のついた型も同じように定義できる\n    // トレイト境界を満たさない型を書くとコンパイルエラーになる\n    type Request = String;\n\n    // 関連型を参照するには`Self::型名`でアクセスする\n    fn handle(&self, req: Self::Request) -> Self::Response {\n        req\n    }\n}\n\n// // `S::Response`のようにServerの関連型を参照できる\n// // 関連型については特別指定しなければ任意の関連型を受け付ける\n// fn handle<S: Server>(server: S, req: &str) -> S::Response {\n//     // 関連型にトレイト境界がついているのでトレイトの関数を呼び出すこともできる\n//     let req = S::Request::from_str(&req).unwrap();\n//     server.handle(req)\n// }\n\n// あるいは、関連型が特定の型を持っていることを指定したければ、`トレイト名<関連型名 = 型>`のように指定できる\n// この場合RequestにStringを持つServerの実装しか受け付けない\nfn handle<S: Server<Request = String>>(server: S, req: &str) -> S::Response {\n    server.handle(req.to_string())\n}\n\nfn main() {\n    let server = EchoServer;\n    assert_eq!(handle(server, \"Hello\"), \"Hello\");\n}\n\n// どこかに定義されたToJsonトレイトを実装して欲しいとする\ntrait ToJson {}\n\ntrait Server2 {\n    type Request: FromStr;\n    // 返り値にトレイトを書くことはできない\n    fn handle(&self, req: Self::Request) -> ToJson;\n}\n\ntrait Foo<T> {}\ntrait Bar {\n    type T;\n}\n\n#[allow(dead_code)]\nstruct Baz;\n\nimpl Foo<i32> for Baz {}\nimpl Foo<char> for Baz {}\n// impl Bar for Baz {\n//     type T = i32;\n// }\n// impl Bar for Baz {\n//     type T = char;\n// }\n"
  },
  {
    "path": "ch08/ex08/examples/ch08_11_sized.rs",
    "content": "fn main() {\n    use std::mem::size_of;\n\n    println!(\"{}\", size_of::<&i32>()); // -> 8\n    println!(\"{}\", size_of::<&str>()); // -> 16\n}\n"
  },
  {
    "path": "ch08/ex08/examples/ch08_12_trait_techniques.rs",
    "content": "#[derive(Debug)]\nenum Either<A, B> {\n    A(A),\n    B(B),\n}\n\nuse std::fmt;\n\nimpl<A, B> fmt::Display for Either<A, B>\nwhere\n    A: fmt::Display,\n    B: fmt::Display,\n{\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        match self {\n            Either::A(a) => a.fmt(f),\n            Either::B(b) => b.fmt(f),\n        }\n    }\n}\n\nfn main() {\n    // `Vec<Either<bool, i32>>` として宣言しておく\n    let mut v: Vec<Either<bool, i32>> = vec![];\n    // Eitherの値を入れる\n    v.push(Either::A(true));\n    v.push(Either::B(1i32));\n\n    // すると `{}` で表示できる\n    for e in v {\n        println!(\"{}\", e);\n    }\n}\n"
  },
  {
    "path": "ch08/ex08/examples-java/Overload.java",
    "content": "import java.util.List;\nimport java.util.ArrayList;\n\npublic class Overload {\n    public static void main(String[] args) {\n        List<String> list = new ArrayList<String>();\n        // オーバーロードだとListとして扱われる\n        assert \"List\".equals(Overload.call(list));\n    }\n\n    // Listに対して定義する\n    static String call(List<String> list) {\n        return \"List\";\n    }\n\n    // ArrayListに対して定義する\n    static String call(ArrayList<String> list) {\n        return \"ArrayList\";\n    }\n}\n"
  },
  {
    "path": "ch08/ex08/tests/integration_tests.rs",
    "content": "use cli_test_dir::{ExpectStatus, OutputExt, TestDir};\n\n// examplesディレクトリ配下にあるバイナリを実行して入出力を確認するテスト\n// `cargo test` で実行できる\n\n#[test]\nfn run_ch08_01() {\n    // use cli_test_dir::TeeOutputExt;\n    let testdir = TestDir::new(\"./examples/ch08_01_trait_basics\", \"Run ch08_01\");\n    let output = testdir\n        .cmd()\n        // .tee_output()    // stdoutとstderrorを順に表示する。デバッグに便利\n        .expect_success();\n    assert_eq!(\n        output.stdout_str(),\n        r#\"x = 1, y = 1\nr = 1.4142135623730951, θ = 0.7853981633974483\n\"#,\n    );\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch08_02() {\n    let testdir = TestDir::new(\"./examples/ch08_02_trait_basics\", \"Run ch08_02\");\n    let output = testdir.cmd().expect_success();\n    assert_eq!(\n        output.stdout_str(),\n        r#\"(0, 1)\n(0.00000000000000006123233995736766, 1)\n\"#,\n    );\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch08_03() {\n    let testdir = TestDir::new(\"./examples/ch08_03_trait_basics\", \"Run ch08_03\");\n    let output = testdir.cmd().expect_success();\n    assert_eq!(output.stdout_str(), \"(-1, 0.00000000000000012246467991473532)\\n\");\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch08_04() {\n    let testdir = TestDir::new(\"./examples/ch08_04_trait_generics\", \"Run ch08_04\");\n    let output = testdir.cmd().expect_success();\n    assert!(output.stdout_str().is_empty());\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch08_05() {\n    let testdir = TestDir::new(\"./examples/ch08_05_trait_generics\", \"Run ch08_05\");\n    let output = testdir.cmd().expect_success();\n    assert!(output.stdout_str().is_empty());\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch08_06() {\n    let testdir = TestDir::new(\"./examples/ch08_06_overload\", \"Run ch08_06\");\n    let output = testdir.cmd().expect_success();\n    assert!(output.stdout_str().is_empty());\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch08_07() {\n    let testdir = TestDir::new(\"./examples/ch08_07_trait_object\", \"Run ch08_07\");\n    let output = testdir.cmd().expect_success();\n    assert!(output.stdout_str().is_empty());\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch08_08() {\n    let testdir = TestDir::new(\"./examples/ch08_08_existential_impl_trait\", \"Run ch08_08\");\n    let output = testdir.cmd().expect_success();\n    assert!(output.stdout_str().is_empty());\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch08_09() {\n    let testdir = TestDir::new(\"./examples/ch08_09_associated_const\", \"Run ch08_09\");\n    let output = testdir.cmd().expect_success();\n    assert!(output.stdout_str().is_empty());\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch08_10() {\n    let testdir = TestDir::new(\"./examples/ch08_10_associated_type\", \"Run ch08_10\");\n    let output = testdir.cmd().expect_success();\n    assert!(output.stdout_str().is_empty());\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch08_11() {\n    let testdir = TestDir::new(\"./examples/ch08_11_sized\", \"Run ch08_11\");\n    let output = testdir.cmd().expect_success();\n    assert_eq!(\n        output.stdout_str(), \n        r#\"8\n16\n\"#,\n    );\n    assert!(output.stderr_str().is_empty());\n}\n\n#[test]\nfn run_ch08_12() {\n    let testdir = TestDir::new(\"./examples/ch08_12_trait_techniques\", \"Run ch08_12\");\n    let output = testdir.cmd().expect_success();\n    assert_eq!(\n        output.stdout_str(), \n        r#\"true\n1\n\"#,\n    );\n    assert!(output.stderr_str().is_empty());\n}\n"
  },
  {
    "path": "ch09/parser/.gitignore",
    "content": "# コンパイラが生成する成果物や中間ファイルが置かれる\ntarget/\n"
  },
  {
    "path": "ch09/parser/Cargo.toml",
    "content": "[package]\nname = \"parser\"\nversion = \"0.1.0\"\nauthors = [\"Rust Bicycle Book <bicycle-book@example.com>\"]\nedition = \"2018\"\n\n[dependencies]\n"
  },
  {
    "path": "ch09/parser/src/main.rs",
    "content": "use std::error::Error as StdError;\nuse std::fmt;\nuse std::str::FromStr;\n\n/// 位置情報。.0から.1までの区間を表す。\n#[derive(Debug, Clone, PartialEq, Eq, Hash)]\nstruct Loc(usize, usize);\n\n// loc に便利メソッドを実装しておく。\nimpl Loc {\n    fn merge(&self, other: &Loc) -> Loc {\n        use std::cmp::{max, min};\n        Loc(min(self.0, other.0), max(self.1, other.1))\n    }\n}\n\n/// アノテーション。値に様々なデータをもたせたもの。ここでは`Loc`をもたせている。\n#[derive(Debug, Clone, PartialEq, Eq, Hash)]\nstruct Annot<T> {\n    value: T,\n    loc: Loc,\n}\n\nimpl<T> Annot<T> {\n    fn new(value: T, loc: Loc) -> Self {\n        Self { value, loc }\n    }\n}\n\n#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]\nenum TokenKind {\n    /// [0-9][0-9]*\n    Number(u64),\n    /// +\n    Plus,\n    /// -\n    Minus,\n    /// *\n    Asterisk,\n    /// /\n    Slash,\n    /// (\n    LParen,\n    /// )\n    RParen,\n}\n\n// `TokenKind` にアノテーションをつけたものを `Token` として定義しておく\ntype Token = Annot<TokenKind>;\n\n// ヘルパーメソッドを定義しておく\nimpl Token {\n    fn number(n: u64, loc: Loc) -> Self {\n        Self::new(TokenKind::Number(n), loc)\n    }\n    fn plus(loc: Loc) -> Self {\n        Self::new(TokenKind::Plus, loc)\n    }\n\n    fn minus(loc: Loc) -> Self {\n        Self::new(TokenKind::Minus, loc)\n    }\n\n    fn asterisk(loc: Loc) -> Self {\n        Self::new(TokenKind::Asterisk, loc)\n    }\n\n    fn slash(loc: Loc) -> Self {\n        Self::new(TokenKind::Slash, loc)\n    }\n\n    fn lparen(loc: Loc) -> Self {\n        Self::new(TokenKind::LParen, loc)\n    }\n\n    fn rparen(loc: Loc) -> Self {\n        Self::new(TokenKind::RParen, loc)\n    }\n}\n\n// `TokenKind` と同様の実装をする\n#[derive(Debug, Clone, PartialEq, Eq, Hash)]\nenum LexErrorKind {\n    InvalidChar(char),\n    Eof,\n}\n\ntype LexError = Annot<LexErrorKind>;\n\nimpl LexError {\n    fn invalid_char(c: char, loc: Loc) -> Self {\n        LexError::new(LexErrorKind::InvalidChar(c), loc)\n    }\n    fn eof(loc: Loc) -> Self {\n        LexError::new(LexErrorKind::Eof, loc)\n    }\n}\n\n/// `pos` のバイトが期待するものであれば1バイト消費して `pos`を1進める\nfn consume_byte(input: &[u8], pos: usize, b: u8) -> Result<(u8, usize), LexError> {\n    // posが入力サイズ以上なら入力が終わっている。\n    // 1バイト期待しているのに終わっているのでエラー\n    if input.len() <= pos {\n        return Err(LexError::eof(Loc(pos, pos)));\n    }\n    // 入力が期待するものでなければエラー\n    if input[pos] != b {\n        return Err(LexError::invalid_char(\n            input[pos] as char,\n            Loc(pos, pos + 1),\n        ));\n    }\n\n    Ok((b, pos + 1))\n}\n\nfn recognize_many(input: &[u8], mut pos: usize, mut f: impl FnMut(u8) -> bool) -> usize {\n    while pos < input.len() && f(input[pos]) {\n        pos += 1;\n    }\n    pos\n}\n\nfn lex_number(input: &[u8], pos: usize) -> Result<(Token, usize), LexError> {\n    use std::str::from_utf8;\n\n    let start = pos;\n    let end = recognize_many(input, start, |b| b\"1234567890\".contains(&b));\n    let n = from_utf8(&input[start..end])\n        // start..posの構成から `from_utf8` は常に成功するため`unwrap`しても安全\n        .unwrap()\n        .parse()\n        // 同じく構成から `parse` は常に成功する\n        .unwrap();\n    Ok((Token::number(n, Loc(start, end)), end))\n}\n\nfn lex_plus(input: &[u8], start: usize) -> Result<(Token, usize), LexError> {\n    // `Result::map` を使うことで結果が正常だった場合の処理を簡潔に書ける。\n    // これはこのコードと等価\n    // ```\n    // match consume_byte(input, start, b'+') {\n    //     Ok((_, end)) => (Token::plus(Loc(start, end)), end),\n    //     Err(err) => Err(err),\n    // }\n    consume_byte(input, start, b'+').map(|(_, end)| (Token::plus(Loc(start, end)), end))\n}\nfn lex_minus(input: &[u8], start: usize) -> Result<(Token, usize), LexError> {\n    consume_byte(input, start, b'-').map(|(_, end)| (Token::minus(Loc(start, end)), end))\n}\nfn lex_asterisk(input: &[u8], start: usize) -> Result<(Token, usize), LexError> {\n    consume_byte(input, start, b'*').map(|(_, end)| (Token::asterisk(Loc(start, end)), end))\n}\nfn lex_slash(input: &[u8], start: usize) -> Result<(Token, usize), LexError> {\n    consume_byte(input, start, b'/').map(|(_, end)| (Token::slash(Loc(start, end)), end))\n}\nfn lex_lparen(input: &[u8], start: usize) -> Result<(Token, usize), LexError> {\n    consume_byte(input, start, b'(').map(|(_, end)| (Token::lparen(Loc(start, end)), end))\n}\nfn lex_rparen(input: &[u8], start: usize) -> Result<(Token, usize), LexError> {\n    consume_byte(input, start, b')').map(|(_, end)| (Token::rparen(Loc(start, end)), end))\n}\nfn skip_spaces(input: &[u8], pos: usize) -> Result<((), usize), LexError> {\n    let pos = recognize_many(input, pos, |b| b\" \\n\\t\".contains(&b));\n    Ok(((), pos))\n}\n\n/// 字句解析器\nfn lex(input: &str) -> Result<Vec<Token>, LexError> {\n    // 解析結果を保存するベクタ\n    let mut tokens = Vec::new();\n    // 入力\n    let input = input.as_bytes();\n    // 位置を管理する値\n    let mut pos = 0;\n    // サブレキサを呼んだ後`pos`を更新するマクロ\n    macro_rules! lex_a_token {\n        ($lexer:expr) => {{\n            let (tok, p) = $lexer?;\n            tokens.push(tok);\n            pos = p;\n        }};\n    }\n    while pos < input.len() {\n        // ここでそれぞれの関数に`input`と`pos`を渡す\n        match input[pos] {\n            // 遷移図通りの実装\n            b'0'...b'9' => lex_a_token!(lex_number(input, pos)),\n            b'+' => lex_a_token!(lex_plus(input, pos)),\n            b'-' => lex_a_token!(lex_minus(input, pos)),\n            b'*' => lex_a_token!(lex_asterisk(input, pos)),\n            b'/' => lex_a_token!(lex_slash(input, pos)),\n            b'(' => lex_a_token!(lex_lparen(input, pos)),\n            b')' => lex_a_token!(lex_rparen(input, pos)),\n            // 空白を扱う\n            b' ' | b'\\n' | b'\\t' => {\n                let ((), p) = skip_spaces(input, pos)?;\n                pos = p;\n            }\n            // それ以外がくるとエラー\n            b => return Err(LexError::invalid_char(b as char, Loc(pos, pos + 1))),\n        }\n    }\n    Ok(tokens)\n}\n\n#[test]\nfn test_lexer() {\n    assert_eq!(\n        lex(\"1 + 2 * 3 - -10\"),\n        Ok(vec![\n            Token::number(1, Loc(0, 1)),\n            Token::plus(Loc(2, 3)),\n            Token::number(2, Loc(4, 5)),\n            Token::asterisk(Loc(6, 7)),\n            Token::number(3, Loc(8, 9)),\n            Token::minus(Loc(10, 11)),\n            Token::minus(Loc(12, 13)),\n            Token::number(10, Loc(13, 15)),\n        ])\n    )\n}\n\n/// 単項演算子を表すデータ型\n#[derive(Debug, Clone, PartialEq, Eq, Hash)]\nenum UniOpKind {\n    /// 正号\n    Plus,\n    /// 負号\n    Minus,\n}\n\ntype UniOp = Annot<UniOpKind>;\n\nimpl UniOp {\n    fn plus(loc: Loc) -> Self {\n        Self::new(UniOpKind::Plus, loc)\n    }\n\n    fn minus(loc: Loc) -> Self {\n        Self::new(UniOpKind::Minus, loc)\n    }\n}\n\n/// 二項演算子を表すデータ型\n#[derive(Debug, Clone, PartialEq, Eq, Hash)]\nenum BinOpKind {\n    /// 加算\n    Add,\n    /// 減算\n    Sub,\n    /// 乗算\n    Mult,\n    /// 除算\n    Div,\n}\n\ntype BinOp = Annot<BinOpKind>;\n\nimpl BinOp {\n    fn add(loc: Loc) -> Self {\n        Self::new(BinOpKind::Add, loc)\n    }\n    fn sub(loc: Loc) -> Self {\n        Self::new(BinOpKind::Sub, loc)\n    }\n    fn mult(loc: Loc) -> Self {\n        Self::new(BinOpKind::Mult, loc)\n    }\n    fn div(loc: Loc) -> Self {\n        Self::new(BinOpKind::Div, loc)\n    }\n}\n\n/// ASTを表すデータ型\n#[derive(Debug, Clone, PartialEq, Eq, Hash)]\nenum AstKind {\n    /// 数値\n    Num(u64),\n    /// 単項演算\n    UniOp { op: UniOp, e: Box<Ast> },\n    /// 二項演算\n    BinOp { op: BinOp, l: Box<Ast>, r: Box<Ast> },\n}\n\ntype Ast = Annot<AstKind>;\n\n// ヘルパメソッドを定義しておく\nimpl Ast {\n    fn num(n: u64, loc: Loc) -> Self {\n        // impl<T> Annot<T>で実装したnewを呼ぶ\n        Self::new(AstKind::Num(n), loc)\n    }\n\n    fn uniop(op: UniOp, e: Ast, loc: Loc) -> Self {\n        Self::new(AstKind::UniOp { op, e: Box::new(e) }, loc)\n    }\n\n    fn binop(op: BinOp, l: Ast, r: Ast, loc: Loc) -> Self {\n        Self::new(\n            AstKind::BinOp {\n                op,\n                l: Box::new(l),\n                r: Box::new(r),\n            },\n            loc,\n        )\n    }\n}\n\n#[derive(Debug, Clone, PartialEq, Eq, Hash)]\nenum ParseError {\n    /// 予期しないトークンがきた\n    UnexpectedToken(Token),\n    /// 式を期待していたのに式でないものがきた\n    NotExpression(Token),\n    /// 演算子を期待していたのに演算子でないものがきた\n    NotOperator(Token),\n    /// 括弧が閉じられていない\n    UnclosedOpenParen(Token),\n    /// 式の解析が終わったのにまだトークンが残っている\n    RedundantExpression(Token),\n    /// パース途中で入力が終わった\n    Eof,\n}\n\nuse std::iter::Peekable;\n\nfn parse_left_binop<Tokens>(\n    tokens: &mut Peekable<Tokens>,\n    subexpr_parser: fn(&mut Peekable<Tokens>) -> Result<Ast, ParseError>,\n    op_parser: fn(&mut Peekable<Tokens>) -> Result<BinOp, ParseError>,\n) -> Result<Ast, ParseError>\nwhere\n    Tokens: Iterator<Item = Token>,\n{\n    let mut e = subexpr_parser(tokens)?;\n    loop {\n        match tokens.peek() {\n            Some(_) => {\n                let op = match op_parser(tokens) {\n                    Ok(op) => op,\n                    // ここでパースに失敗したのはこれ以上中置演算子がないという意味\n                    Err(_) => break,\n                };\n                let r = subexpr_parser(tokens)?;\n                let loc = e.loc.merge(&r.loc);\n                e = Ast::binop(op, e, r, loc)\n            }\n            _ => break,\n        }\n    }\n    Ok(e)\n}\n\n// atom\nfn parse_atom<Tokens>(tokens: &mut Peekable<Tokens>) -> Result<Ast, ParseError>\nwhere\n    Tokens: Iterator<Item = Token>,\n{\n    tokens\n        .next()\n        .ok_or(ParseError::Eof)\n        .and_then(|tok| match tok.value {\n            // UNUMBER\n            TokenKind::Number(n) => Ok(Ast::new(AstKind::Num(n), tok.loc)),\n            // | \"(\", EXPR3, \")\" ;\n            TokenKind::LParen => {\n                let e = parse_expr(tokens)?;\n                match tokens.next() {\n                    Some(Token {\n                        value: TokenKind::RParen,\n                        ..\n                    }) => Ok(e),\n                    Some(t) => Err(ParseError::RedundantExpression(t)),\n                    _ => Err(ParseError::UnclosedOpenParen(tok)),\n                }\n            }\n            _ => Err(ParseError::NotExpression(tok)),\n        })\n}\n\n// expr1\nfn parse_expr1<Tokens>(tokens: &mut Peekable<Tokens>) -> Result<Ast, ParseError>\nwhere\n    Tokens: Iterator<Item = Token>,\n{\n    match tokens.peek().map(|tok| tok.value) {\n        Some(TokenKind::Plus) | Some(TokenKind::Minus) => {\n            // (\"+\" | \"-\")\n            let op = match tokens.next() {\n                Some(Token {\n                    value: TokenKind::Plus,\n                    loc,\n                }) => UniOp::plus(loc),\n                Some(Token {\n                    value: TokenKind::Minus,\n                    loc,\n                }) => UniOp::minus(loc),\n                _ => unreachable!(),\n            };\n            // , ATOM\n            let e = parse_atom(tokens)?;\n            let loc = op.loc.merge(&e.loc);\n            Ok(Ast::uniop(op, e, loc))\n        }\n        //  | ATOM\n        _ => parse_atom(tokens),\n    }\n}\n\nfn parse_expr2<Tokens>(tokens: &mut Peekable<Tokens>) -> Result<Ast, ParseError>\nwhere\n    Tokens: Iterator<Item = Token>,\n{\n    // `parse_left_binop` に渡す関数を定義する\n    fn parse_expr2_op<Tokens>(tokens: &mut Peekable<Tokens>) -> Result<BinOp, ParseError>\n    where\n        Tokens: Iterator<Item = Token>,\n    {\n        let op = tokens\n            .peek()\n            .ok_or(ParseError::Eof)\n            .and_then(|tok| match tok.value {\n                TokenKind::Asterisk => Ok(BinOp::mult(tok.loc.clone())),\n                TokenKind::Slash => Ok(BinOp::div(tok.loc.clone())),\n                _ => Err(ParseError::NotOperator(tok.clone())),\n            })?;\n        tokens.next();\n        Ok(op)\n    }\n\n    parse_left_binop(tokens, parse_expr1, parse_expr2_op)\n}\n\nfn parse_expr3<Tokens>(tokens: &mut Peekable<Tokens>) -> Result<Ast, ParseError>\nwhere\n    Tokens: Iterator<Item = Token>,\n{\n    // `parse_left_binop` に渡す関数を定義する\n    fn parse_expr3_op<Tokens>(tokens: &mut Peekable<Tokens>) -> Result<BinOp, ParseError>\n    where\n        Tokens: Iterator<Item = Token>,\n    {\n        let op = tokens\n            .peek()\n            // イテレータの終わりは入力の終端なのでエラーを出す。\n            .ok_or(ParseError::Eof)\n            // エラーを返すかもしれない値を繋げる\n            .and_then(|tok| match tok.value {\n                TokenKind::Plus => Ok(BinOp::add(tok.loc.clone())),\n                TokenKind::Minus => Ok(BinOp::sub(tok.loc.clone())),\n                _ => Err(ParseError::NotOperator(tok.clone())),\n            })?;\n        tokens.next();\n        Ok(op)\n    }\n\n    parse_left_binop(tokens, parse_expr2, parse_expr3_op)\n}\n\nfn parse_expr<Tokens>(tokens: &mut Peekable<Tokens>) -> Result<Ast, ParseError>\nwhere\n    Tokens: Iterator<Item = Token>,\n{\n    // `parse_expr`は `parse_expr3` を呼ぶだけ\n    parse_expr3(tokens)\n}\n\nfn parse(tokens: Vec<Token>) -> Result<Ast, ParseError> {\n    // 入力をイテレータにし、 `Peekable` にする\n    let mut tokens = tokens.into_iter().peekable();\n    // その後 `parse_expr` を呼んでエラー処理をする\n    let ret = parse_expr(&mut tokens)?;\n    match tokens.next() {\n        Some(tok) => Err(ParseError::RedundantExpression(tok)),\n        None => Ok(ret),\n    }\n}\n\n#[test]\nfn test_parser() {\n    // 1 + 2 * 3 - -10\n    let ast = parse(vec![\n        Token::number(1, Loc(0, 1)),\n        Token::plus(Loc(2, 3)),\n        Token::number(2, Loc(4, 5)),\n        Token::asterisk(Loc(6, 7)),\n        Token::number(3, Loc(8, 9)),\n        Token::minus(Loc(10, 11)),\n        Token::minus(Loc(12, 13)),\n        Token::number(10, Loc(13, 15)),\n    ]);\n    assert_eq!(\n        ast,\n        Ok(Ast::binop(\n            BinOp::sub(Loc(10, 11)),\n            Ast::binop(\n                BinOp::add(Loc(2, 3)),\n                Ast::num(1, Loc(0, 1)),\n                Ast::binop(\n                    BinOp::new(BinOpKind::Mult, Loc(6, 7)),\n                    Ast::num(2, Loc(4, 5)),\n                    Ast::num(3, Loc(8, 9)),\n                    Loc(4, 9)\n                ),\n                Loc(0, 9),\n            ),\n            Ast::uniop(\n                UniOp::minus(Loc(12, 13)),\n                Ast::num(10, Loc(13, 15)),\n                Loc(12, 15)\n            ),\n            Loc(0, 15)\n        ))\n    )\n}\n\nimpl FromStr for Ast {\n    type Err = Error;\n    fn from_str(s: &str) -> Result<Self, Self::Err> {\n        // 内部では字句解析、構文解析の順に実行する\n        let tokens = lex(s)?;\n        let ast = parse(tokens)?;\n        Ok(ast)\n    }\n}\n\n/// 字句解析エラーと構文解析エラーを統合するエラー型\n#[derive(Debug, Clone, PartialEq, Eq, Hash)]\nenum Error {\n    Lexer(LexError),\n    Parser(ParseError),\n}\n\nimpl From<LexError> for Error {\n    fn from(e: LexError) -> Self {\n        Error::Lexer(e)\n    }\n}\n\nimpl From<ParseError> for Error {\n    fn from(e: ParseError) -> Self {\n        Error::Parser(e)\n    }\n}\n\nimpl fmt::Display for TokenKind {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        use self::TokenKind::*;\n        match self {\n            Number(n) => n.fmt(f),\n            Plus => write!(f, \"+\"),\n            Minus => write!(f, \"-\"),\n            Asterisk => write!(f, \"*\"),\n            Slash => write!(f, \"/\"),\n            LParen => write!(f, \"(\"),\n            RParen => write!(f, \")\"),\n        }\n    }\n}\n\nimpl fmt::Display for Loc {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        write!(f, \"{}-{}\", self.0, self.1)\n    }\n}\n\nimpl fmt::Display for LexError {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        use self::LexErrorKind::*;\n        let loc = &self.loc;\n        match self.value {\n            InvalidChar(c) => write!(f, \"{}: invalid char '{}'\", loc, c),\n            Eof => write!(f, \"End of file\"),\n        }\n    }\n}\n\nimpl fmt::Display for ParseError {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        use self::ParseError::*;\n        match self {\n            UnexpectedToken(tok) => write!(f, \"{}: {} is not expected\", tok.loc, tok.value),\n            NotExpression(tok) => write!(\n                f,\n                \"{}: '{}' is not a start of expression\",\n                tok.loc, tok.value\n            ),\n            NotOperator(tok) => write!(f, \"{}: '{}' is not an operator\", tok.loc, tok.value),\n            UnclosedOpenParen(tok) => write!(f, \"{}: '{}' is not closed\", tok.loc, tok.value),\n            RedundantExpression(tok) => write!(\n                f,\n                \"{}: expression after '{}' is redundant\",\n                tok.loc, tok.value\n            ),\n            Eof => write!(f, \"End of file\"),\n        }\n    }\n}\n\nimpl fmt::Display for Error {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        write!(f, \"parser error\")\n    }\n}\n\nimpl StdError for LexError {}\n\nimpl StdError for ParseError {}\n\nimpl StdError for Error {\n    fn source(&self) -> Option<&(dyn StdError + 'static)> {\n        use self::Error::*;\n        match self {\n            Lexer(lex) => Some(lex),\n            Parser(parse) => Some(parse),\n        }\n    }\n}\n\n/// `input` に対して `loc` の位置を強調表示する\nfn print_annot(input: &str, loc: Loc) {\n    // 入力に対して\n    eprintln!(\"{}\", input);\n    // 位置情報をわかりやすく示す\n    eprintln!(\"{}{}\", \" \".repeat(loc.0), \"^\".repeat(loc.1 - loc.0));\n}\n\nimpl Error {\n    /// 診断メッセージを表示する\n    fn show_diagnostic(&self, input: &str) {\n        use self::Error::*;\n        use self::ParseError as P;\n        // エラー情報とその位置情報を取り出す。エラーの種類によって位置情報を調整する。\n        let (e, loc): (&StdError, Loc) = match self {\n            Lexer(e) => (e, e.loc.clone()),\n            Parser(e) => {\n                let loc = match e {\n                    P::UnexpectedToken(Token { loc, .. })\n                    | P::NotExpression(Token { loc, .. })\n                    | P::NotOperator(Token { loc, .. })\n                    | P::UnclosedOpenParen(Token { loc, .. }) => loc.clone(),\n                    // redundant expressionはトークン以降行末までが余りなのでlocの終了位置を調整する\n                    P::RedundantExpression(Token { loc, .. }) => Loc(loc.0, input.len()),\n                    // EoFはloc情報を持っていないのでその場で作る\n                    P::Eof => Loc(input.len(), input.len() + 1),\n                };\n                (e, loc)\n            }\n        };\n        // エラー情報を簡単に表示し\n        eprintln!(\"{}\", e);\n        // エラー位置を指示する\n        print_annot(input, loc);\n    }\n}\n\nfn show_trace<E: StdError>(e: E) {\n    // エラーがあった場合そのエラーとcauseを全部出力する\n    eprintln!(\"{}\", e);\n    let mut source = e.source();\n    // cause を全て辿って表示する\n    while let Some(e) = source {\n        eprintln!(\"caused by {}\", e);\n        source = e.source()\n    }\n    // エラー表示のあとは次の入力を受け付ける\n}\n\n/// 評価器を表すデータ型\nstruct Interpreter;\n\n#[derive(Debug, Clone, PartialEq, Eq, Hash)]\nenum InterpreterErrorKind {\n    DivisionByZero,\n}\n\ntype InterpreterError = Annot<InterpreterErrorKind>;\n\nimpl Interpreter {\n    pub fn new() -> Self {\n        Interpreter\n    }\n\n    pub fn eval(&mut self, expr: &Ast) -> Result<i64, InterpreterError> {\n        use self::AstKind::*;\n        match expr.value {\n            Num(n) => Ok(n as i64),\n            UniOp { ref op, ref e } => {\n                let e = self.eval(e)?;\n                Ok(self.eval_uniop(op, e))\n            }\n            BinOp {\n                ref op,\n                ref l,\n                ref r,\n            } => {\n                let l = self.eval(l)?;\n                let r = self.eval(r)?;\n                self.eval_binop(op, l, r)\n                    .map_err(|e| InterpreterError::new(e, expr.loc.clone()))\n            }\n        }\n    }\n\n    fn eval_uniop(&mut self, op: &UniOp, n: i64) -> i64 {\n        use self::UniOpKind::*;\n        match op.value {\n            Plus => n,\n            Minus => -n,\n        }\n    }\n    fn eval_binop(&mut self, op: &BinOp, l: i64, r: i64) -> Result<i64, InterpreterErrorKind> {\n        use self::BinOpKind::*;\n        match op.value {\n            Add => Ok(l + r),\n            Sub => Ok(l - r),\n            Mult => Ok(l * r),\n            Div => {\n                if r == 0 {\n                    Err(InterpreterErrorKind::DivisionByZero)\n                } else {\n                    Ok(l / r)\n                }\n            }\n        }\n    }\n}\n\nimpl fmt::Display for InterpreterError {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        use self::InterpreterErrorKind::*;\n        match self.value {\n            DivisionByZero => write!(f, \"division by zero\"),\n        }\n    }\n}\n\nimpl StdError for InterpreterError {\n    fn description(&self) -> &str {\n        use self::InterpreterErrorKind::*;\n        match self.value {\n            DivisionByZero => \"the right hand expression of the division evaluates to zero\",\n        }\n    }\n}\n\nimpl InterpreterError {\n    fn show_diagnostic(&self, input: &str) {\n        // エラー情報を簡単に表示し\n        eprintln!(\"{}\", self);\n        // エラー位置を指示する\n        print_annot(input, self.loc.clone());\n    }\n}\n\n/// 逆ポーランド記法へのコンパイラを表すデータ型\nstruct RpnCompiler;\n\nimpl RpnCompiler {\n    pub fn new() -> Self {\n        RpnCompiler\n    }\n\n    pub fn compile(&mut self, expr: &Ast) -> String {\n        let mut buf = String::new();\n        self.compile_inner(expr, &mut buf);\n        buf\n    }\n\n    pub fn compile_inner(&mut self, expr: &Ast, buf: &mut String) {\n        use self::AstKind::*;\n        match expr.value {\n            Num(n) => buf.push_str(&n.to_string()),\n            UniOp { ref op, ref e } => {\n                self.compile_uniop(op, buf);\n                self.compile_inner(e, buf)\n            }\n            BinOp {\n                ref op,\n                ref l,\n                ref r,\n            } => {\n                self.compile_inner(l, buf);\n                buf.push_str(\" \");\n                self.compile_inner(r, buf);\n                buf.push_str(\" \");\n                self.compile_binop(op, buf)\n            }\n        }\n    }\n\n    fn compile_uniop(&mut self, op: &UniOp, buf: &mut String) {\n        use self::UniOpKind::*;\n        match op.value {\n            Plus => buf.push_str(\"+\"),\n            Minus => buf.push_str(\"-\"),\n        }\n    }\n    fn compile_binop(&mut self, op: &BinOp, buf: &mut String) {\n        use self::BinOpKind::*;\n        match op.value {\n            Add => buf.push_str(\"+\"),\n            Sub => buf.push_str(\"-\"),\n            Mult => buf.push_str(\"*\"),\n            Div => buf.push_str(\"/\"),\n        }\n    }\n}\n\nuse std::io;\n\n/// プロンプトを表示しユーザの入力を促す\nfn prompt(s: &str) -> io::Result<()> {\n    use std::io::{stdout, Write};\n    let stdout = stdout();\n    let mut stdout = stdout.lock();\n    stdout.write(s.as_bytes())?;\n    stdout.flush()\n}\n\nfn main() {\n    use std::io::{stdin, BufRead, BufReader};\n    let mut interp = Interpreter::new();\n    let mut compiler = RpnCompiler::new();\n\n    let stdin = stdin();\n    let stdin = stdin.lock();\n    let stdin = BufReader::new(stdin);\n    let mut lines = stdin.lines();\n\n    loop {\n        prompt(\"> \").unwrap();\n        // ユーザの入力を取得する\n        if let Some(Ok(line)) = lines.next() {\n            // `from_str` を実装したので`parse`が呼べる\n            let ast = match line.parse::<Ast>() {\n                Ok(ast) => ast,\n                Err(e) => {\n                    e.show_diagnostic(&line);\n                    show_trace(e);\n                    continue;\n                }\n            };\n            println!(\"{:?}\", ast);\n            let n = match interp.eval(&ast) {\n                Ok(n) => n,\n                Err(e) => {\n                    e.show_diagnostic(&line);\n                    show_trace(e);\n                    continue;\n                }\n            };\n            println!(\"{}\", n);\n            let rpn = compiler.compile(&ast);\n            println!(\"{}\", rpn);\n        } else {\n            break;\n        }\n    }\n}\n"
  },
  {
    "path": "ch10/wordcount/.gitignore",
    "content": "# コンパイラが生成する成果物や中間ファイルが置かれる\ntarget/\n"
  },
  {
    "path": "ch10/wordcount/Cargo.toml",
    "content": "[package]\nname = \"bicycle-book-wordcount\"\nversion = \"0.1.0\"\nauthors = [\"Rust Bicycle Book <bicycle-book@example.com>\"]\nedition = \"2018\"\n# ここから追記\nlicense = \"MIT OR Apache-2.0\"\ndescription = \"シンプルな文字、単語、行の出現頻度の計数機能を提供します。\"\nreadme = \"README.md\"\nrepository = \"https://github.com/your_account/wordcount\"\ncategories = [\"command-line-utilities\"]\nkeywords = [\"example\", \"frequency\", \"text\"]\nexclude = [\"text.txt\", \"tests/*\"]\n\n[badges]\nappveyor = { repository = \"your_account/wordcount\" }\ntravis-ci = { repository = \"your_account/wordcount\" }\n\n# 追記ここまで\n\n[dependencies]\nregex = \"1.0\"\n"
  },
  {
    "path": "ch10/wordcount/README.md",
    "content": "`bicycle_book_wordcount` はシンプルな文字、単語、行の出現頻度の計数機能を提供します。\nCLIからは単語数の出現頻度が使えます。\n\n```console\n$ cargo run text.txt\n{\"bb\": 1, \"aa\": 2, \"cc\": 1}\n```\n````\n\n"
  },
  {
    "path": "ch10/wordcount/src/lib.rs",
    "content": "//! `bicycle_book_wordcount` はシンプルな文字、単語、行の出現頻度の計数機能を提供します。\n//! 詳しくは[`count`](fn.count.html)関数のドキュメントを見て下さい。\n\nuse regex::Regex;\nuse std::collections::HashMap;\nuse std::io::BufRead;\n\n/// [`count`](fn.count.html)で使うオプション\n#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]\npub enum CountOption {\n    /// 文字毎に頻度を数える\n    Char,\n    /// 単語毎に頻度を数える\n    Word,\n    /// 行毎に頻度を数える\n    Line,\n}\n\n/// オプションのデフォルトは [`Word`](enum.CountOption.html#variant.Word)\nimpl Default for CountOption {\n    fn default() -> Self {\n        CountOption::Word\n    }\n}\n\n/// `input` から1行ずつUTF-8文字列を読み込み、頻度を数える。\n///\n/// 頻度を数える対象はオプションによって制御される。\n/// * [`CountOption::Char`](enum.CountOption.html#variant.Char): Unicodeの1文字毎に頻度を数える\n/// * [`CountOption::Word`](enum.CountOption.html#variant.Word): 正規表現 `\\w+` にマッチする単語毎に頻度を数える\n/// * [`CountOption::Line`](enum.CountOption.html#variant.Line): `\\n`または`\\r\\n` で区切られた1行毎に頻度を数える\n///\n/// # Examples\n/// 入力中の単語の出現頻度を数える例\n///\n/// ```\n/// use std::io::Cursor;\n/// use bicycle_book_wordcount::{count, CountOption};\n///\n/// let mut input = Cursor::new(\"aa bb cc bb\");\n/// let freq = count(input, CountOption::Word);\n///\n/// assert_eq!(freq[\"aa\"], 1);\n/// assert_eq!(freq[\"bb\"], 2);\n/// assert_eq!(freq[\"cc\"], 1);\n/// ```\n///\n/// # Panics\n///\n/// 入力がUTF-8でフォーマットされていない場合にパニックする。\npub fn count(input: impl BufRead, option: CountOption) -> HashMap<String, usize> {\n    let re = Regex::new(r\"\\w+\").unwrap();\n    let mut freqs = HashMap::new(); // HashMap<String, usize>型\n\n    for line in input.lines() {\n        let line = line.unwrap();\n        use crate::CountOption::*;\n        match option {\n            Char => {\n                for c in line.chars() {\n                    *freqs.entry(c.to_string()).or_insert(0) += 1;\n                }\n            }\n            Word =>\n            // 4. その行を単語で分割する\n            {\n                for m in re.find_iter(&line) {\n                    let word = m.as_str().to_string();\n                    // 5. 出現した単語の出現頻度を数える\n                    *freqs.entry(word).or_insert(0) += 1;\n                }\n            }\n            Line => *freqs.entry(line.to_string()).or_insert(0) += 1,\n        }\n    }\n    freqs\n}\n\n#[test]\nfn word_count_works() {\n    use std::io::Cursor;\n\n    let mut exp = HashMap::new();\n    exp.insert(\"aa\".to_string(), 1);\n    exp.insert(\"bb\".to_string(), 2);\n    exp.insert(\"cc\".to_string(), 1);\n\n    assert_eq!(count(Cursor::new(\"aa bb cc bb\"), CountOption::Word), exp);\n}\n\n#[test]\nfn word_count_works2() {\n    use std::io::Cursor;\n\n    let mut exp = HashMap::new();\n    exp.insert(\"aa\".to_string(), 1);\n    exp.insert(\"cc\".to_string(), 1);\n    exp.insert(\"dd\".to_string(), 1);\n\n    assert_eq!(count(Cursor::new(\"aa  cc dd\"), CountOption::Word), exp);\n}\n\n#[cfg(test)]\nmod test {\n    use super::*;\n    use std::io::Cursor;\n\n    macro_rules! assert_map {\n        ($expr: expr, {$($key: expr => $value:expr),*}) => {\n            $(assert_eq!($expr[$key], $value));*\n        };\n    }\n\n    #[test]\n    fn word_count_works3() {\n        let freqs = count(Cursor::new(\"aa  cc dd\"), CountOption::Word);\n\n        assert_eq!(freqs.len(), 3);\n        assert_map!(freqs, {\"aa\" => 1, \"cc\" => 1, \"dd\" => 1});\n    }\n\n}\n\n#[test]\n#[should_panic]\nfn word_count_do_not_contain_unknown_words() {\n    use std::io::Cursor;\n\n    count(\n        Cursor::new([\n            b'a', // a\n            0xf0, 0x90, 0x80, // でたらめなバイト列\n            0xe3, 0x81, 0x82, // あ\n        ]),\n        CountOption::Word,\n    );\n}\n"
  },
  {
    "path": "ch10/wordcount/src/main.rs",
    "content": "use std::env;\nuse std::fs::File;\nuse std::io::BufReader;\n\n// libクレートに分離したものを使う\nuse bicycle_book_wordcount::count;\n\nfn main() {\n    // 1. コマンドラインで指定された引数を読み込む\n    let filename = env::args().nth(1).expect(\"1 argument FILENAME required\");\n    // 2. 指定されたファイルを開く\n    let file = File::open(filename).unwrap();\n    let reader = BufReader::new(&file);\n\n    // 3. ファイルから1行ずつ読み込む\n    // 第2引数 `Default::default` を加える\n    let freqs = count(reader, Default::default());\n    println!(\"{:?}\", freqs);\n}\n"
  },
  {
    "path": "ch10/wordcount/tests/char.rs",
    "content": "// アイテムのインポートも、もちろん必要\nuse std::io::Cursor;\nuse bicycle_book_wordcount::{count, CountOption};\n\n#[macro_use]\nmod utils;\n\n// 以下にテストを書く\n\n#[test]\nfn char_count_works() {\n    let input = Cursor::new(b\"abadracadabra\");\n\n    let freq = count(input, CountOption::Char);\n    assert_map!(freq,\n                {\n                    \"a\" => 6,\n                    \"b\" => 2,\n                    \"c\" => 1,\n                    \"d\" => 2,\n                    \"r\" => 2\n                }\n    );\n}\n\n#[test]\nfn char_count_utf8() {\n    let input = Cursor::new(\n        r#\"\n天地玄黃\n宇宙洪荒\n日月盈昃\n辰宿列張\n\"#,\n    );\n\n    let freq = count(input, CountOption::Char);\n\n    assert_eq!(freq.len(), 16);\n    for (_, count) in freq {\n        assert_eq!(count, 1);\n    }\n}\n"
  },
  {
    "path": "ch10/wordcount/tests/line.rs",
    "content": "use std::io::Cursor;\nuse bicycle_book_wordcount::{count, CountOption};\n\n#[macro_use]\nmod utils;\n\n// 以下にテストを書く\n\n#[test]\nfn line_count_works() {\n    let input = Cursor::new(\n        r#\"Tokyo, Japan\nKyoto, Japan\nTokyo, Japan\nShanghai, China\n\"#,\n    );\n\n    let freq = count(input, CountOption::Line);\n\n    assert_map!(freq, {\n        \"Tokyo, Japan\" => 2,\n        \"Kyoto, Japan\" => 1,\n        \"Shanghai, China\" => 1\n    });\n}\n\n#[test]\nfn line_count_lfcr() {\n    let input = Cursor::new(\"aa\\r\\nbb\\r\\ncc\\r\\nbb\");\n\n    let freq = count(input, CountOption::Line);\n\n    assert_map!(freq, {\n        \"aa\" => 1,\n        \"bb\" => 2,\n        \"cc\" => 1\n    });\n}\n"
  },
  {
    "path": "ch10/wordcount/tests/utils/mod.rs",
    "content": "macro_rules! assert_map {\n    ($expr: expr, {$($key: expr => $value:expr),*}) => {\n        $(assert_eq!($expr[$key], $value));*\n    };\n}\n"
  },
  {
    "path": "ch10/wordcount/text.txt",
    "content": "aa bb cc aa\n\n"
  },
  {
    "path": "ch11/log-collector/.gitignore",
    "content": "# コンパイラが生成する成果物や中間ファイルが置かれる\ntarget/\n"
  },
  {
    "path": "ch11/log-collector/Cargo.toml",
    "content": "[workspace]\nmembers = [\"server\", \"api\", \"cli\"]\n"
  },
  {
    "path": "ch11/log-collector/api/Cargo.toml",
    "content": "[package]\nname = \"api\"\nversion = \"0.1.0\"\nauthors = [\"Rust Bicycle Book <bicycle-book@example.com>\"]\nedition = \"2018\"\n\n[dependencies]\nserde = \"1.0.8\"\nserde_derive = \"1.0.8\"\n\n[dependencies.chrono]\nfeatures = [\"serde\"]\nversion = \"0.4.0\"\n\n"
  },
  {
    "path": "ch11/log-collector/api/src/lib.rs",
    "content": "use chrono::{DateTime, Utc};\nuse serde_derive::*;\n// JSONの {\"user_agent\": \"xxx\", \"response_time\": 0, \"timestamp\": \"yyyy-MM-dd+HH:mm:ss\"}に対応\n// 返り値で使うログはtimestampが`Option`ではない\n#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize)]\npub struct Log {\n    pub user_agent: String,\n    pub response_time: i32,\n    pub timestamp: DateTime<Utc>,\n}\n\n// クエリパラメータの `?from=yyyy-MM-dd+HH:mm:ss&until=yyyy-MM-dd+HH:mm:ss` に対応\n#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize)]\npub struct DateTimeRange {\n    pub from: Option<DateTime<Utc>>,\n    pub until: Option<DateTime<Utc>>,\n}\n\npub mod csv {\n    pub mod get {\n        use crate::DateTimeRange;\n\n        pub type Query = DateTimeRange;\n        // getははファイルを返すのでResponse型の定義がない\n    }\n\n    pub mod post {\n        use serde_derive::*;\n\n        // CSVファイルを受け付けるのでリクエストデータはない\n        #[derive(Debug, Clone, Eq, PartialEq, Hash, Default, Deserialize, Serialize)]\n        // 受領したログの数を返す\n        pub struct Response(pub usize);\n    }\n}\n\npub mod logs {\n    pub mod get {\n        use crate::{DateTimeRange, Log};\n        use serde_derive::*;\n\n        pub type Query = DateTimeRange;\n\n        #[derive(Debug, Clone, Eq, PartialEq, Hash, Default, Deserialize, Serialize)]\n        // 保存しているログをすべて返す\n        pub struct Response(pub Vec<Log>);\n    }\n\n    pub mod post {\n        use chrono::{DateTime, Utc};\n        use serde_derive::*;\n\n        // 説明した通りのデータを受け付ける\n        #[derive(Debug, Clone, Eq, PartialEq, Hash, Default, Deserialize, Serialize)]\n        pub struct Request {\n            pub user_agent: String,\n            pub response_time: i32,\n            pub timestamp: Option<DateTime<Utc>>,\n        }\n        // Acceptedを返すのでResponseデータ型の定義はない\n    }\n\n}\n"
  },
  {
    "path": "ch11/log-collector/cli/Cargo.toml",
    "content": "[package]\nname = \"cli\"\nversion = \"0.1.0\"\nauthors = [\"Rust Bicycle Book <bicycle-book@example.com>\"]\nedition = \"2018\"\n\n[dependencies]\nclap = \"2\"\nreqwest = \"0.9\"\ncsv = \"1\"\nserde = \"1\"\nserde_json = \"1\"\napi = {path = \"../api\"}\n\n\n[dependencies.chrono]\nfeatures = [\"serde\"]\nversion = \"0.4\"\n"
  },
  {
    "path": "ch11/log-collector/cli/src/main.rs",
    "content": "use clap::{App, AppSettings, Arg, SubCommand};\nuse clap::{_clap_count_exprs, arg_enum};\nuse reqwest::Client;\nuse std::io;\n\narg_enum! {\n    #[derive(Debug)]\n    enum Format {\n        Csv,\n        Json,\n    }\n}\n\nstruct ApiClient {\n    server: String,\n    client: Client,\n}\n\nimpl ApiClient {\n    fn post_logs(&self, req: &api::logs::post::Request) -> reqwest::Result<()> {\n        self.client\n            .post(&format!(\"http://{}/logs\", &self.server))\n            .json(req)\n            .send()\n            .map(|_| ())\n    }\n\n    fn get_logs(&self) -> reqwest::Result<api::logs::get::Response> {\n        self.client\n            .get(&format!(\"http://{}/logs\", &self.server))\n            .send()?\n            .json()\n    }\n\n    fn get_csv<W: io::Write>(&self, w: &mut W) -> reqwest::Result<u64> {\n        self.client\n            .get(&format!(\"http://{}/csv\", &self.server))\n            .send()?\n            .copy_to(w)\n    }\n}\n\nfn do_post_csv(api_client: &ApiClient) {\n    let reader = csv::Reader::from_reader(io::stdin());\n    for log in reader.into_deserialize::<api::logs::post::Request>() {\n        let log = match log {\n            Ok(log) => log,\n            Err(e) => {\n                eprintln!(\"[WARN] failed to parse a line, skipping: {}\", e);\n                continue;\n            }\n        };\n        api_client.post_logs(&log).expect(\"api request failed\");\n    }\n}\n\nfn do_get_json(api_client: &ApiClient) {\n    let res = api_client.get_logs().expect(\"api request failed\");\n    let json_str = serde_json::to_string(&res).unwrap();\n    println!(\"{}\", json_str);\n}\n\nfn do_get_csv(api_client: &ApiClient) {\n    let out = io::stdout();\n    let mut out = out.lock();\n    api_client.get_csv(&mut out).expect(\"api request failed\");\n}\n\nfn main() {\n    let opts = App::new(env!(\"CARGO_PKG_NAME\"))\n        .about(env!(\"CARGO_PKG_DESCRIPTION\"))\n        .version(env!(\"CARGO_PKG_VERSION\"))\n        .author(env!(\"CARGO_PKG_AUTHORS\"))\n        // 以上がほぼテンプレート\n        .setting(AppSettings::SubcommandRequiredElseHelp)\n        // -s URL | --server URL のオプションを受け付ける\n        .arg(\n            Arg::with_name(\"SERVER\")\n                .short(\"s\")\n                .long(\"server\")\n                .value_name(\"URL\")\n                .help(\"server url\")\n                .takes_value(true),\n        )\n        // サブコマンドとして `post` を受け付ける\n        .subcommand(SubCommand::with_name(\"post\").about(\"post logs, taking input from stdin\"))\n        // サブコマンドとして `get` を受け付ける\n        .subcommand(\n            SubCommand::with_name(\"get\").about(\"get logs\").arg(\n                Arg::with_name(\"FORMAT\")\n                    .help(\"log format\")\n                    .short(\"f\")\n                    .long(\"format\")\n                    .takes_value(true)\n                    // \"csv\", \"json\" のみを受け付ける\n                    .possible_values(&Format::variants())\n                    .case_insensitive(true),\n            ),\n        );\n    let matches = opts.get_matches();\n\n    let server = matches\n        .value_of(\"SERVER\")\n        .unwrap_or(\"localhost:3000\")\n        // .into()が増えた\n        .into();\n    let client = Client::new();\n    let api_client = ApiClient { server, client };\n\n    match matches.subcommand() {\n        (\"get\", sub_match) => {\n            let format = sub_match\n                .and_then(|m| m.value_of(\"FORMAT\"))\n                .map(|m| m.parse().unwrap())\n                .unwrap();\n            match format {\n                Format::Csv => do_get_csv(&api_client),\n                Format::Json => do_get_json(&api_client),\n            }\n        }\n        (\"post\", _) => do_post_csv(&api_client),\n        _ => unreachable!(),\n    }\n}\n"
  },
  {
    "path": "ch11/log-collector/docker-compose.yml",
    "content": "# いろいろ書かれていますが、ローカルホストの5432番ポートにユーザ名postgres、パスワードpasswordのデータベースサーバを立てる設定です\npostgres-data:\n  image: busybox\n  volumes:\n    - /var/lib/postgresql/log-collector-data\n  container_name: log-collector-postgres-datastore\n\npostgresql:\n  image: postgres\n  environment:\n    POSTGRES_USER: postgres\n    POSTGRES_PASSWORD: password\n  ports:\n    - \"5432:5432\"\n  volumes_from:\n    - postgres-data\n"
  },
  {
    "path": "ch11/log-collector/server/Cargo.toml",
    "content": "[package]\nname = \"server\"\nversion = \"0.1.0\"\nauthors = [\"Rust Bicycle Book <bicycle-book@example.com>\"]\nedition = \"2018\"\n\n[dependencies]\nenv_logger = \"0.6\"\nlog = \"0.4\"\nactix-web = \"0.7\"\nfailure = \"0.1\"\napi = {path = \"../api\"}\ndotenv = \"0.13\"\nchrono = \"0.4\"\ncsv = \"1\"\nactix-web-multipart-file = \"0.1\"\nfutures = \"0.1\"\nitertools = \"0.8\"\n\n[dependencies.diesel]\nfeatures = [\"postgres\", \"chrono\", \"r2d2\"]\nversion = \"1.4\"\n"
  },
  {
    "path": "ch11/log-collector/server/diesel.toml",
    "content": "# For documentation on how to configure this file,\n# see diesel.rs/guides/configuring-diesel-cli\n\n[print_schema]\nfile = \"src/schema.rs\"\n"
  },
  {
    "path": "ch11/log-collector/server/migrations/.gitkeep",
    "content": ""
  },
  {
    "path": "ch11/log-collector/server/migrations/00000000000000_diesel_initial_setup/down.sql",
    "content": "-- This file was automatically created by Diesel to setup helper functions\n-- and other internal bookkeeping. This file is safe to edit, any future\n-- changes will be added to existing projects as new migrations.\n\nDROP FUNCTION IF EXISTS diesel_manage_updated_at(_tbl regclass);\nDROP FUNCTION IF EXISTS diesel_set_updated_at();\n"
  },
  {
    "path": "ch11/log-collector/server/migrations/00000000000000_diesel_initial_setup/up.sql",
    "content": "-- This file was automatically created by Diesel to setup helper functions\n-- and other internal bookkeeping. This file is safe to edit, any future\n-- changes will be added to existing projects as new migrations.\n\n\n\n\n-- Sets up a trigger for the given table to automatically set a column called\n-- `updated_at` whenever the row is modified (unless `updated_at` was included\n-- in the modified columns)\n--\n-- # Example\n--\n-- ```sql\n-- CREATE TABLE users (id SERIAL PRIMARY KEY, updated_at TIMESTAMP NOT NULL DEFAULT NOW());\n--\n-- SELECT diesel_manage_updated_at('users');\n-- ```\nCREATE OR REPLACE FUNCTION diesel_manage_updated_at(_tbl regclass) RETURNS VOID AS $$\nBEGIN\n    EXECUTE format('CREATE TRIGGER set_updated_at BEFORE UPDATE ON %s\n                    FOR EACH ROW EXECUTE PROCEDURE diesel_set_updated_at()', _tbl);\nEND;\n$$ LANGUAGE plpgsql;\n\nCREATE OR REPLACE FUNCTION diesel_set_updated_at() RETURNS trigger AS $$\nBEGIN\n    IF (\n        NEW IS DISTINCT FROM OLD AND\n        NEW.updated_at IS NOT DISTINCT FROM OLD.updated_at\n    ) THEN\n        NEW.updated_at := current_timestamp;\n    END IF;\n    RETURN NEW;\nEND;\n$$ LANGUAGE plpgsql;\n"
  },
  {
    "path": "ch11/log-collector/server/migrations/2018-12-28-161332_create_logs/down.sql",
    "content": "-- This file should undo anything in `up.sql`\nDROP TABLE IF EXISTS logs;\n"
  },
  {
    "path": "ch11/log-collector/server/migrations/2018-12-28-161332_create_logs/up.sql",
    "content": "-- Your SQL goes here\nCREATE TABLE logs (\n  id BIGSERIAL NOT NULL,\n  user_agent VARCHAR NOT NULL,\n  response_time INT NOT NULL,\n  timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,\n  PRIMARY KEY (id)\n);\n\n"
  },
  {
    "path": "ch11/log-collector/server/src/db.rs",
    "content": "use crate::model::*;\nuse chrono::{DateTime, Utc};\nuse diesel::insert_into;\nuse diesel::prelude::*;\nuse diesel::result::QueryResult;\n\npub fn insert_log(cn: &PgConnection, log: &NewLog) -> QueryResult<i64> {\n    use crate::schema::logs::dsl;\n    insert_into(dsl::logs)\n        .values(log)\n        .returning(dsl::id)\n        .get_result(cn)\n}\n\npub fn insert_logs(cn: &PgConnection, logs: &[NewLog]) -> QueryResult<Vec<i64>> {\n    use crate::schema::logs::dsl;\n    insert_into(dsl::logs)\n        .values(logs)\n        .returning(dsl::id)\n        .load(cn)\n}\n\npub fn logs(\n    cn: &PgConnection,\n    from: Option<DateTime<Utc>>,\n    until: Option<DateTime<Utc>>,\n) -> QueryResult<Vec<Log>> {\n    use crate::schema::logs::dsl;\n\n    // 型エラーを防ぐためにinto_boxedを呼んでおく\n    let mut query = dsl::logs.into_boxed();\n    if let Some(from) = from {\n        query = query.filter(dsl::timestamp.ge(from.naive_utc()))\n    }\n    if let Some(until) = until {\n        query = query.filter(dsl::timestamp.lt(until.naive_utc()))\n    }\n    query.order(dsl::timestamp.asc()).load(cn)\n}\n"
  },
  {
    "path": "ch11/log-collector/server/src/handlers.rs",
    "content": "use crate::db;\nuse crate::Server;\nuse actix_web::{FutureResponse, HttpResponse, State};\nuse actix_web::{Json, Query};\nuse actix_web_multipart_file::{FormData, Multiparts};\nuse diesel::pg::PgConnection;\nuse failure::Error;\nuse futures::prelude::*;\nuse itertools::Itertools;\nuse log::debug;\nuse std::io::{BufReader, Read};\n\nfn load_file(conn: &PgConnection, file: impl Read) -> Result<usize, Error> {\n    use crate::model::NewLog;\n\n    let mut ret = 0;\n\n    // CSVファイルが渡される`csv::Reader`を用いてapi::Logにデコードしていく\n    let in_csv = BufReader::new(file);\n    let in_log = csv::Reader::from_reader(in_csv).into_deserialize::<::api::Log>();\n    // Itertoolsのchunksを用いて1000件ずつ処理する\n    for logs in &in_log.chunks(1000) {\n        let logs = logs\n            // Logとしてパースできた行だけ集める\n            .filter_map(Result::ok)\n            .map(|log| NewLog {\n                user_agent: log.user_agent,\n                response_time: log.response_time,\n                timestamp: log.timestamp.naive_utc(),\n            })\n            .collect_vec();\n\n        let inserted = db::insert_logs(conn, &logs)?;\n        ret += inserted.len();\n    }\n\n    Ok(ret)\n}\n\n/// `POST /csv`のハンドラ\npub fn handle_post_csv(\n    server: State<Server>,\n    // actix_web_multipart_fileを使ってマルチパートのリクエストをファイルに保存する\n    multiparts: Multiparts,\n) -> FutureResponse<HttpResponse> {\n    // multipartsは`Stream`になっているのでそのままメソッドを繋げる\n    // `Stream` は非同期版イテレータのような存在\n    let fut = multiparts\n        .from_err()\n        // text/csvでなければスキップ\n        .filter(|field| field.content_type == \"text/csv\")\n        // ファイルでなければスキップ\n        .filter_map(|field| match field.form_data {\n            FormData::File { file, .. } => Some(file),\n            FormData::Data { .. } => None,\n        })\n        // 1ファイルずつ処理する\n        .and_then(move |file| load_file(&*server.pool.get()?, file))\n        // usize の Stream(イテレータのようなもの) -> それらの和\n        .fold(0, |acc, x| Ok::<_, Error>(acc + x))\n        .map(|sum| HttpResponse::Ok().json(api::csv::post::Response(sum)))\n        .from_err();\n\n    Box::new(fut)\n}\n\n/// `POST /logs`のハンドラ\npub fn handle_post_logs(\n    server: State<Server>,\n    log: Json<api::logs::post::Request>,\n) -> Result<HttpResponse, Error> {\n    use crate::model::NewLog;\n    use chrono::Utc;\n\n    let log = NewLog {\n        user_agent: log.user_agent.clone(),\n        response_time: log.response_time,\n        timestamp: log.timestamp.unwrap_or_else(|| Utc::now()).naive_utc(),\n    };\n    let conn = server.pool.get()?;\n    db::insert_log(&conn, &log)?;\n\n    debug!(\"received log: {:?}\", log);\n\n    Ok(HttpResponse::Accepted().finish())\n}\n\n/// `GET /logs`のハンドラ\npub fn handle_get_logs(\n    server: State<Server>,\n    range: Query<api::logs::get::Query>,\n) -> Result<HttpResponse, Error> {\n    use chrono::{DateTime, Utc};\n\n    let conn = server.pool.get()?;\n    let logs = db::logs(&conn, range.from, range.until)?;\n    let logs = logs\n        .into_iter()\n        .map(|log| api::Log {\n            user_agent: log.user_agent,\n            response_time: log.response_time,\n            timestamp: DateTime::from_utc(log.timestamp, Utc),\n        })\n        .collect();\n\n    Ok(HttpResponse::Ok().json(api::logs::get::Response(logs)))\n}\n\n/// `GET /csv`のハンドラ\npub fn handle_get_csv(\n    server: State<Server>,\n    range: Query<api::csv::get::Query>,\n) -> Result<HttpResponse, Error> {\n    use chrono::{DateTime, Utc};\n\n    let conn = server.pool.get()?;\n    let logs = db::logs(&conn, range.from, range.until)?;\n    let v = Vec::new();\n    let mut w = csv::Writer::from_writer(v);\n\n    for log in logs.into_iter().map(|log| ::api::Log {\n        user_agent: log.user_agent,\n        response_time: log.response_time,\n        timestamp: DateTime::from_utc(log.timestamp, Utc),\n    }) {\n        w.serialize(log)?;\n    }\n\n    let csv = w.into_inner()?;\n    Ok(HttpResponse::Ok()\n        .header(\"Content-Type\", \"text/csv\")\n        .body(csv))\n}\n"
  },
  {
    "path": "ch11/log-collector/server/src/main.rs",
    "content": "#[macro_use]\nextern crate diesel;\nuse actix_web::http::Method;\nuse actix_web::App;\nuse diesel::pg::PgConnection;\nuse diesel::r2d2::{ConnectionManager, Pool};\nuse dotenv::dotenv;\nuse std::env;\n\nmod db;\nmod handlers;\nmod model;\nmod schema;\n\n// アプリケーションで持ち回る状態\n#[derive(Clone)]\npub struct Server {\n    pool: Pool<ConnectionManager<PgConnection>>,\n}\n\nimpl Server {\n    pub fn new() -> Self {\n        dotenv().ok();\n        let database_url = env::var(\"DATABASE_URL\").expect(\"DATABASE_URL is not set\");\n        let manager = ConnectionManager::<PgConnection>::new(database_url);\n        let pool = Pool::builder()\n            .build(manager)\n            .expect(\"Failed to create pool.\");\n        Server { pool }\n    }\n}\n\n// ルーティングなどを書く\npub fn app(server: Server) -> App<Server> {\n    use crate::handlers::*;\n\n    let app: App<Server> = App::with_state(server)\n        .route(\"/logs\", Method::POST, handle_post_logs)\n        .route(\"/csv\", Method::POST, handle_post_csv)\n        .route(\"/csv\", Method::GET, handle_get_csv)\n        .route(\"/logs\", Method::GET, handle_get_logs);\n\n    app\n}\n\nfn main() {\n    // 環境変数でログレベルを設定する\n    env_logger::init();\n\n    let server = Server::new();\n    ::actix_web::server::new(move || app(server.clone()))\n        .bind(\"localhost:3000\")\n        .expect(\"Can not bind to port 3000\")\n        .run();\n}\n"
  },
  {
    "path": "ch11/log-collector/server/src/model.rs",
    "content": "use crate::schema::*;\nuse chrono::NaiveDateTime;\n\n#[derive(Debug, Clone, Eq, PartialEq, Hash, Insertable)]\n#[table_name = \"logs\"]\npub struct NewLog {\n    pub user_agent: String,\n    pub response_time: i32,\n    pub timestamp: NaiveDateTime,\n}\n\n#[derive(Debug, Clone, Eq, PartialEq, Hash, Queryable)]\npub struct Log {\n    pub id: i64,\n    pub user_agent: String,\n    pub response_time: i32,\n    pub timestamp: NaiveDateTime,\n}\n"
  },
  {
    "path": "ch11/log-collector/server/src/schema.rs",
    "content": "table! {\n    logs (id) {\n        id -> Int8,\n        user_agent -> Varchar,\n        response_time -> Int4,\n        timestamp -> Timestamp,\n    }\n}\n"
  },
  {
    "path": "ch11/log-collector/test.csv",
    "content": "user_agent,response_time,timestamp\nhogehoge,10,\"2017-08-26T13:13:29.931320Z\"\n"
  },
  {
    "path": "ch11/start-aw/.gitignore",
    "content": "# コンパイラが生成する成果物や中間ファイルが置かれる\ntarget/\n"
  },
  {
    "path": "ch11/start-aw/Cargo.toml",
    "content": "[package]\nname = \"start-aw\"\nversion = \"0.1.0\"\nauthors = [\"Rust Bicycle Book <bicycle-book@example.com>\"]\nedition = \"2018\"\n\n[dependencies]\nactix-web = \"0.7\"\nserde = \"1\"\nserde_derive = \"1\""
  },
  {
    "path": "ch11/start-aw/src/main.rs",
    "content": "use actix_web::{server, App, HttpRequest, Responder};\n\nuse serde_derive::*;\n\n#[derive(Deserialize)]\nstruct HelloPath {\n    // `{name}` に対応するフィールドを定義する\n    name: String,\n}\n\nfn hello(req: &HttpRequest) -> impl Responder {\n    let to = req.match_info().get(\"name\").unwrap_or(\"World\");\n    format!(\"Hello {}!\", to)\n}\n\nfn main() {\n    server::new(|| {\n        App::new()\n            .resource(\"/\", |r| r.f(hello))\n            .resource(\"/{name}\", |r| r.f(hello))\n    })\n    .bind(\"localhost:3000\")\n    .expect(\"Can not bind to port 3000\")\n    .run();\n}\n"
  },
  {
    "path": "ch11/start-aw/static/test.txt",
    "content": "testtest\n"
  },
  {
    "path": "ch11/static-files/.gitignore",
    "content": "# コンパイラが生成する成果物や中間ファイルが置かれる\ntarget/\n"
  },
  {
    "path": "ch11/static-files/Cargo.toml",
    "content": "[package]\nname = \"static-files\"\nversion = \"0.1.0\"\nauthors = [\"Rust Bicycle Book <bicycle-book@example.com>\"]\nedition = \"2018\"\n\n[dependencies]\nactix-web = \"0.7.16\"\n"
  },
  {
    "path": "ch11/static-files/src/main.rs",
    "content": "// fsをインポート\nuse actix_web::{fs, server, App};\n\nfn main() {\n    server::new(|| {\n        App::new().handler(\n            \"/\",\n            // `StaticFiles`を用いて現在のディレクトリ下のファイルを提供する\n            fs::StaticFiles::new(\".\").unwrap(),\n        )\n    })\n    .bind(\"localhost:3000\")\n    .expect(\"Can not bind to port 3000\")\n    .run();\n}\n\n"
  },
  {
    "path": "ch11/templates/.gitignore",
    "content": "# コンパイラが生成する成果物や中間ファイルが置かれる\ntarget/\n"
  },
  {
    "path": "ch11/templates/Cargo.toml",
    "content": "[package]\nname = \"templates\"\nversion = \"0.1.0\"\nauthors = [\"Rust Bicycle Book <bicycle-book@example.com>\"]\nedition = \"2018\"\n\n[dependencies]\nactix-web = \"0.7.16\"\ntera = \"0.11.20\"\nserde_derive = \"1\"\nserde = \"1\"\n"
  },
  {
    "path": "ch11/templates/src/main.rs",
    "content": "use actix_web::{error, http, server, App, HttpResponse, Path, State};\nuse serde_derive::*;\nuse tera::{compile_templates, Context, Tera};\n\nstruct AppState {\n    template: Tera,\n}\n\n#[derive(Deserialize)]\nstruct HelloPath {\n    name: String,\n}\n\nfn hello_template(\n    app: State<AppState>,\n    path: Path<HelloPath>,\n) -> Result<HttpResponse, error::Error> {\n    // テンプレートに渡す値を作る\n    let mut context = Context::new();\n    context.insert(\"name\", &path.name);\n    // app.templateでテンプレートが取得出来る\n    let body = app\n        .template\n        // `Tera::render` で指定したテンプレートをレンダリングできる\n        .render(\"index.html.tera\", &context)\n        // レンダリングに失敗したらサーバ内部のエラーとして扱う\n        .map_err(|e| error::ErrorInternalServerError(format!(\"{}\", e)))?;\n    // レンダリング結果をレスポンスとしてステータス200 OKで返す\n    Ok(HttpResponse::Ok().body(body))\n}\n\nfn main() {\n    server::new(|| {\n        // AppStateを準備する\n        let app = AppState {\n            // compile_templates! でテンプレートを一括でコンパイルできる\n            template: compile_templates!(\"templates/**/*\"),\n        };\n        // with_stateでアプリケーションデータとして保持\n        App::with_state(app).route(\"/{name}\", http::Method::GET, hello_template)\n    })\n    .bind(\"localhost:3000\")\n    .expect(\"Can not bind to port 3000\")\n    .run();\n}\n"
  },
  {
    "path": "ch11/templates/templates/index.html.tera",
    "content": "<!doctype html>\n<html lang=\"ja\">\n    <head>\n        <meta charset=\"UTF-8\"/>\n        <title>Document</title>\n    </head>\n    <body>Hello {{name}}</body>\n</html>\n"
  },
  {
    "path": "ch12/c-api/.gitignore",
    "content": "# コンパイラが生成する成果物や中間ファイルが置かれる\ntarget/\n\n# Cコンパイラが生成する成果物\na.out\n"
  },
  {
    "path": "ch12/c-api/Cargo.toml",
    "content": "[package]\nname = \"c-api\"\nversion = \"0.1.0\"\nauthors = [\"Rust Bicycle Book <bicycle-book@example.com>\"]\nedition = \"2018\"\n\n[lib]\ncrate-type = [\"cdylib\"]\n\n[dependencies]\n"
  },
  {
    "path": "ch12/c-api/main.c",
    "content": "#include <stdio.h>\n#include <stdint.h>\n\n// Rustと同じ定義を書く\nstruct point {\n  int x;\n  int y;\n};\n\n// Rustの関数のプロトタイプ宣言\n// 上の`struct point`とこれは丁寧にやるならヘッダを作るべき\ndouble\ndist(struct point *, struct point *);\n\n\nint\nmain()\n{\n  struct point p1 = {1, 0}, p2 = {0, 1};\n  double ret;\n\n  ret = dist(&p1, &p2);\n\n  printf(\"%f\\n\", ret);\n\n}\n\n"
  },
  {
    "path": "ch12/c-api/src/lib.rs",
    "content": "use std::os::raw::{c_double, c_int};\n\n// Cのデータの扱いで説明したときと同様 `#[repr(C)]` で互換性を取れる\n/// 2次元平面上の点を表す型\n#[repr(C)]\npub struct point {\n    x: c_int,\n    y: c_int,\n}\n\nfn pow(x: c_int) -> c_int {\n    x * x\n}\n\n// `#[no_mangle]`をつけることでCから\"dist\"という名前で見つかるようになる。\n// `extern \"C\"`をつけることでCから呼べるようになる。\n/// 2点間の距離を計算する\n#[no_mangle]\npub extern \"C\" fn dist(p1: &point, p2: &point) -> c_double {\n    let d = pow(p1.x - p2.x) + pow(p1.y - p2.y);\n    (d as f64).sqrt() as c_double\n}\n\n"
  },
  {
    "path": "ch12/cffi-ownership/.gitignore",
    "content": "# コンパイラが生成する成果物や中間ファイルが置かれる\ntarget/\n"
  },
  {
    "path": "ch12/cffi-ownership/Cargo.toml",
    "content": "[package]\nname = \"cffi-ownership\"\nversion = \"0.1.0\"\nauthors = [\"Rust Bicycle Book <bicycle-book@example.com>\"]\nedition = \"2018\"\n\n[dependencies]\nlibc = \"0.2.0\"\n\n[build-dependencies]\ncc = \"1.0\"\n"
  },
  {
    "path": "ch12/cffi-ownership/build.rs",
    "content": "fn main() {\n    cc::Build::new()\n        .file(\"c_src/ownership.c\")\n        .compile(\"ownership\");\n}\n\n"
  },
  {
    "path": "ch12/cffi-ownership/c_src/ownership.c",
    "content": "#include <stdlib.h>\n#include <stdio.h>\n\nvoid\ntake_ownership(int *i, void(*dtor)(int *))\n{\n  printf(\"got %d\\n\", *i);\n  // Cのコードでメモリを解放する。\n  // Rustで用意した値はRustから貰ったデストラクタで解放する\n  dtor(i);\n}\n\nint *\nmake_memory() {\n  int *i;\n\n  i = malloc(sizeof(int));\n  *i = 2;\n\n  return i;\n}\n\n"
  },
  {
    "path": "ch12/cffi-ownership/src/main.rs",
    "content": "use std::os::raw::c_int;\n\n#[link(name = \"ownership\", kind = \"static\")]\nextern \"C\" {\n    fn make_memory() -> *mut c_int;\n}\n\nfn main() {\n    unsafe {\n        let i = make_memory();\n\n        println!(\"got {}\", *i);\n\n        // Cから渡されたメモリは手で解放する必要がある\n        libc::free(i as *mut _);\n    }\n}\n\n"
  },
  {
    "path": "ch12/cffi_readline.rs",
    "content": "// `String`のCのNULL終端文字列に対応する型。\nuse std::ffi::CString;\n// `str`のCのnull終端文字列に対応する型。\nuse std::ffi::CStr;\nuse std::os::raw::c_schar;\n\n// `readline`ライブラリとリンクする。\n#[link(name = \"readline\")]\nextern \"C\" {\n    // Cの符号付き `char` 型を`c_schar`で表現している。\n    fn readline(prompt: *const c_schar) -> *mut c_schar;\n}\n\nfn main() {\n    unsafe {\n        // Rustの文字列をCの文字列に変換する。\n        // NULL終端するために`CString`を使う。\n        let prompt = CString::new(\"> \").unwrap();\n        loop {\n            // `readline`を呼び、結果を`CStr`でラップする。\n            let input = CStr::from_ptr(readline(prompt.as_ptr()));\n            // `&CStr`を`&str`に変換する。\n            let input = input.to_str().expect(\"input contains invalid unicode\");\n            // 以後はRustの文字列なので自由に操作できる。\n            if input == \"exit\" {\n                break;\n            }\n\n            println!(\"your input is {}\", input);\n        }\n    }\n}\n"
  },
  {
    "path": "ch12/ffi-global/.gitignore",
    "content": "# コンパイラが生成する成果物や中間ファイルが置かれる\ntarget/\n"
  },
  {
    "path": "ch12/ffi-global/Cargo.toml",
    "content": "[package]\nname = \"ffi-global\"\nversion = \"0.1.0\"\nauthors = [\"Rust Bicycle Book <bicycle-book@example.com>\"]\nedition = \"2018\"\n\n[dependencies]\n"
  },
  {
    "path": "ch12/ffi-global/src/main.rs",
    "content": "use std::os::raw::c_int;\n\n#[link(name = \"readline\")]\nextern \"C\" {\n    // rustの`static`と同じく`static 名前: 型;`で宣言します。\n    static rl_readline_version: c_int;\n}\n\nfn main() {\n    unsafe {\n        // readlineのバージョンは16進数なので `:x` で16進表示する。\n        println!(\"using readline version {:x}\", rl_readline_version);\n    }\n}\n"
  },
  {
    "path": "ch12/onigmo-rs/.gitignore",
    "content": "# Cargoが選択した依存ライブラリのバージョン郡\nCargo.lock\n\n# コンパイラが生成する成果物や中間ファイルが置かれる\ntarget/\n"
  },
  {
    "path": "ch12/onigmo-rs/Cargo.toml",
    "content": "[workspace]\nmembers = [\"onigmo-sys\", \"onigmo\"]\n"
  },
  {
    "path": "ch12/onigmo-rs/onigmo/Cargo.toml",
    "content": "[package]\nname = \"onigmo\"\nversion = \"0.1.0\"\nauthors = [\"Rust Bicycle Book <bicycle-book@example.com>\"]\nedition = \"2018\"\n\n[dependencies]\n\n[dependencies.onigmo-sys]\npath = \"../onigmo-sys\"\n"
  },
  {
    "path": "ch12/onigmo-rs/onigmo/examples/simple.rs",
    "content": "fn main() {\n    let mut reg = {\n        let s = \"a(.*)b|[e-f]+\".to_string();\n        onigmo::Regex::new(&s).unwrap()\n    };\n    let s = \"zzzzaffffffffb\";\n    match reg.search(s) {\n        Some(ret) => {\n            use std::str::from_utf8;\n            for (beg, end) in ret.positions() {\n                println!(\"{}\", from_utf8(&s.as_bytes()[beg..end]).unwrap());\n            }\n        }\n        None => println!(\"not match\"),\n    }\n}\n"
  },
  {
    "path": "ch12/onigmo-rs/onigmo/src/lib.rs",
    "content": "use onigmo_sys::*;\nuse std::error;\nuse std::fmt;\n\n// 本来は`OnigPosition`のままでなくenumを定義して変換した方がいいが長くなるのでここでは省略。\n#[derive(Debug, Clone)]\npub struct Error(OnigPosition, Option<OnigErrorInfo>, String);\ntype Result<T> = ::std::result::Result<T, Error>;\n\nimpl Error {\n    // 中身はほぼonigmo-sysでの記述のままだが、最後に`String`を作っているのでRustから扱いやすくなっている。\n    // また、ここで`unsafe`を1つ閉じ込めている。\n    fn new(pos: OnigPosition, error_info: Option<OnigErrorInfo>) -> Self {\n        use std::str::from_utf8;\n        let s: &mut [OnigUChar] = &mut [0; ONIG_MAX_ERROR_MESSAGE_LEN as usize];\n        unsafe {\n            let size = match error_info {\n                Some(ei) => onig_error_code_to_str(s as *mut _ as *mut _, pos, ei),\n                None => onig_error_code_to_str(s as *mut _ as *mut _, pos),\n            };\n            let size = size as usize;\n            let s = from_utf8(&s[0..size]).unwrap().to_string();\n            Error(pos, error_info, s)\n        }\n    }\n}\n\nimpl fmt::Display for Error {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        write!(f, \"ERROR: {}\\n\", self.2)\n    }\n}\n\nimpl error::Error for Error {}\n\nuse std::mem;\nuse std::ops::Drop;\n\n// Regexは動作の主体となり、主に`&mut self`の形で使われるのでここではポインタは使わない\npub struct Regex(regex_t);\nimpl Regex {\n    pub fn new(pattern: &str) -> Result<Self> {\n        // 長く見えるが、実体は`onig_new_without_alloc`を呼んでいるだけ。\n        unsafe {\n            let mut reg: regex_t = mem::uninitialized();\n            let pattern = pattern.as_bytes();\n            let mut einfo: OnigErrorInfo = mem::uninitialized();\n            let r = onig_new_without_alloc(\n                &mut reg as *mut _,\n                pattern.as_ptr() as *const OnigUChar,\n                (pattern.as_ptr() as *const OnigUChar).offset(pattern.len() as isize),\n                ONIG_OPTION_NONE,\n                &OnigEncodingUTF_8,\n                OnigDefaultSyntax,\n                &mut einfo,\n            );\n            if (r as ::std::os::raw::c_uint) == ONIG_NORMAL {\n                Ok(Regex(reg))\n            } else {\n                // 先程定義したエラーもしっかり使う\n                Err(Error::new(r as OnigPosition, Some(einfo)))\n            }\n        }\n    }\n    // 検索対象はリードオンリーなので`&str`で受け取る\n    pub fn search(&mut self, s: &str) -> Option<Region> {\n        // これもほぼ中身は`onig_search`を呼んでいるだけ\n        unsafe {\n            let s = s.as_bytes();\n            let start = s.as_ptr();\n            let end = start.offset(s.len() as isize);\n            let range = end;\n            let mut region = Region::new()?;\n\n            let pos = onig_search(\n                &mut self.0,\n                start,\n                end,\n                start,\n                range,\n                region.as_ptr_mut(),\n                ONIG_OPTION_NONE,\n            );\n            if 0 <= pos {\n                Some(region)\n            } else {\n                // Onigmoのソースコードに倣い、デバッグビルドのときは返り値が`ONIG_MISMATCH`でなければ\n                // パニックするようにする\n                debug_assert!(pos as std::os::raw::c_int == ONIG_MISMATCH);\n                None\n            }\n        }\n    }\n}\n\nimpl Drop for Regex {\n    fn drop(&mut self) {\n        unsafe { onig_free_body(&mut self.0) }\n    }\n}\n\nuse std::ptr::NonNull;\n\n// `Region`はOnigmoのAPIがそうなっているのと、主に返り値でそのまま返されるので内部の値はポインタで指す。\n#[derive(Debug)]\npub struct Region(NonNull<OnigRegion>);\n\nimpl Region {\n    pub fn new() -> Option<Self> {\n        // コンストラクタは `onig_region_new` を呼ぶ\n        unsafe {\n            let region: *mut OnigRegion = onig_region_new();\n            Some(Region(NonNull::new(region)?))\n        }\n    }\n\n    fn as_ptr_mut(&mut self) -> *mut OnigRegion {\n        self.0.as_ptr()\n    }\n\n    fn as_ptr(&self) -> *const OnigRegion {\n        self.0.as_ptr()\n    }\n}\n\nimpl Clone for Region {\n    fn clone(&self) -> Self {\n        // `onig_region_copy` で Clone を実装\n        unsafe {\n            let to: *mut OnigRegion = mem::uninitialized();\n            onig_region_copy(to, self.0.as_ptr());\n            Region(NonNull::new_unchecked(to))\n        }\n    }\n}\n\nimpl Drop for Region {\n    fn drop(&mut self) {\n        unsafe { onig_region_free(self.0.as_ptr(), 1) }\n    }\n}\n\nuse std::ops::Range;\n// データを持っている `Region` とそのインデックスのイテレータ\n/// Regionから取り出すイテレータの型\n#[derive(Debug, Clone)]\npub struct PositionIter<'a>(&'a Region, Range<i32>);\n\nimpl Region {\n    // `Region`の`impl`にこの関数を追記する\n    /// 位置情報のイテレータを取り出す\n    pub fn positions(&self) -> PositionIter {\n        let num_regs;\n        // リージョン数の情報からインデックスのイテレータを作る\n        unsafe {\n            num_regs = (*self.as_ptr()).num_regs;\n        }\n        PositionIter(self, 0..num_regs)\n    }\n}\n\nimpl<'a> Iterator for PositionIter<'a> {\n    type Item = (usize, usize);\n    fn next(&mut self) -> Option<Self::Item> {\n        unsafe {\n            let region = *self.0.as_ptr();\n            // `self.1` がイテレータになっているのでそれを使ってイテレータを実装する\n            self.1.next().map(|i| {\n                (\n                    *region.beg.offset(i as isize) as usize,\n                    *region.end.offset(i as isize) as usize,\n                )\n            })\n        }\n    }\n}\n"
  },
  {
    "path": "ch12/onigmo-rs/onigmo-sys/Cargo.toml",
    "content": "[package]\nname = \"onigmo-sys\"\nversion = \"0.1.0\"\nauthors = [\"Rust Bicycle Book <bicycle-book@example.com>\"]\nedition = \"2018\"\n\n[dependencies]\n\n[build-dependencies]\nbindgen = \"0.49\"\n\n"
  },
  {
    "path": "ch12/onigmo-rs/onigmo-sys/build.rs",
    "content": "use std::env;\nuse std::path::PathBuf;\n\nfn main() {\n    // onigmoの共有ライブラリを使うことをcargoがrustcに伝えるように伝える\n    println!(\"cargo:rustc-link-lib=onigmo\");\n\n    // `binden::Builder`がbindgenを使うときのメインのエントリーポイント\n    // オプションを設定できます。\n    let bindings = bindgen::Builder::default()\n        // バインディングを作る基になるヘッダファイル\n        .header(\"wrapper.h\")\n        // `bindgen_test_layout_max_align_t` のテスト失敗を防ぐためにRust 1.28.0以上向けにコード生成する\n        .rust_target(bindgen::RustTarget::Stable_1_28)\n        // ビルダーを完了してバインディングを生成する\n        .generate()\n        .expect(\"Unable to generate bindings\");\n\n    // バインディングを`$OUT_DIR/bindings.rs`に書き出す。\n    let out_path = PathBuf::from(env::var(\"OUT_DIR\").unwrap());\n    bindings\n        .write_to_file(out_path.join(\"bindings.rs\"))\n        .expect(\"Couldn't write bindings!\");\n}\n"
  },
  {
    "path": "ch12/onigmo-rs/onigmo-sys/examples/simple.rs",
    "content": "use onigmo_sys::*;\nuse std::mem;\nuse std::str::from_utf8_unchecked;\n\nfn main() {\n    unsafe {\n        // 正規表現のパターン文字列\n        let pattern = b\"a(.*)b|[e-f]+\";\n        // マッチ対象です\n        let s = b\"zzzzaffffffffb\";\n        // `onig_new_without_alloc`で初期化するメモリをスタックに確保する。\n        let mut reg: regex_t = mem::uninitialized();\n        let mut einfo: OnigErrorInfo = mem::uninitialized();\n        // 正規表現文字列をコンパイルし、`reg`に格納する。\n        let r = onig_new_without_alloc(\n            &mut reg as *mut _,\n            // パターン文字列の先頭\n            pattern as *const OnigUChar,\n            // パターン文字列の末尾\n            (pattern as *const OnigUChar).offset(pattern.len() as isize),\n            // 今回、オプションは付けない\n            ONIG_OPTION_NONE,\n            // Rustの文字列はUTF-8エンコーディング\n            &OnigEncodingUTF_8,\n            // Onigmoのデフォルトの構文を使う\n            OnigDefaultSyntax,\n            &mut einfo,\n        );\n        // コンパイル結果の返り値が正常値でなければエラー\n        if (r as ::std::os::raw::c_uint) != ONIG_NORMAL {\n            // エラー情報を取得し出力 する\n            let s: &mut [OnigUChar] = &mut [0; ONIG_MAX_ERROR_MESSAGE_LEN as usize];\n            onig_error_code_to_str(s as *mut _ as *mut _, r as OnigPosition, &einfo);\n            println!(\"ERROR: {}\\n\", from_utf8_unchecked(s));\n            // 正規表現のエラーならそのまま終了\n            return;\n        }\n\n        // マッチ情報を表わすデータを準備する\n        let region = onig_region_new();\n\n        // マッチ対象文字列の終端\n        let end = (s as *const OnigUChar).offset(s.len() as isize);\n        // マッチ開始位置\n        let start = s as *const _;\n        // マッチ終了位置\n        let range = end;\n        // 正規表現でマッチする\n        let mut r = onig_search(\n            &mut reg,\n            s as *const _,\n            end,\n            start,\n            range,\n            region,\n            ONIG_OPTION_NONE,\n        );\n        if 0 <= r {\n            // 返り値が0以上ならマッチ成功\n            println!(\"match at {}\", r);\n            let region = region.as_ref().unwrap();\n            // グルーピングされた部分正規表現毎にマッチ位置を表示する\n            for i in 0..(region.num_regs) {\n                println!(\n                    \"{}: ({}-{})\",\n                    i,\n                    *region.beg.offset(i as isize),\n                    *region.end.offset(i as isize)\n                );\n            }\n            r = 0;\n        } else if (r as ::std::os::raw::c_int) == ONIG_MISMATCH {\n            // 返り値が`ONIG_MISMATCH`なら正規表現とマッチ失敗\n            println!(\"search fail\");\n            r = -1;\n        } else {\n            // それ以外ではOnigmoの内部エラー\n            let s: &mut [OnigUChar] = &mut [0; ONIG_MAX_ERROR_MESSAGE_LEN as usize];\n            onig_error_code_to_str(s as *mut _ as *mut _, r as OnigPosition, &einfo);\n            println!(\"ERROR: {}\\n\", from_utf8_unchecked(s));\n            std::process::exit(-1);\n        }\n        // 使ったリソースを手動で解放する\n        onig_region_free(region, 1);\n        onig_free_body(&mut reg);\n        onig_end();\n        std::process::exit(r as i32);\n    }\n}\n\n"
  },
  {
    "path": "ch12/onigmo-rs/onigmo-sys/src/lib.rs",
    "content": "// Cの名前のまま生成されてしまうので警告を切る\n#![allow(non_upper_case_globals)]\n#![allow(non_camel_case_types)]\n#![allow(non_snake_case)]\n\ninclude!(concat!(env!(\"OUT_DIR\"), \"/bindings.rs\"));\n"
  },
  {
    "path": "ch12/onigmo-rs/onigmo-sys/wrapper.h",
    "content": "#include <onigmo.h>\n"
  },
  {
    "path": "ch12/opaque/.gitignore",
    "content": "# コンパイラが生成する成果物や中間ファイルが置かれる\ntarget/\n"
  },
  {
    "path": "ch12/opaque/Cargo.toml",
    "content": "[package]\nname = \"opaque\"\nversion = \"0.1.0\"\nauthors = [\"Rust Bicycle Book <bicycle-book@example.com>\"]\nedition = \"2018\"\n\n[dependencies]\n"
  },
  {
    "path": "ch12/opaque/src/main.rs",
    "content": "use std::os::raw::{c_char, c_int};\n\n// オペーク型を表わす型を導入する。\n// バリアントのない列挙型は値が作れないのでユーザが勝手にインスタンスを作ることはできない。\n// この列挙型へのポインタでオペーク型へのポインタを表す。\nenum File {}\n\nextern \"C\" {\n    // Cの`FILE`型の実体が分からないのでRust側では実体に言及しない型でマッピングする。\n\n    // FILE *fopen(const char *path, const char *mode);\n    fn fopen(fname: *const c_char, mode: *const c_char) -> *mut File;\n\n    // int fgetc(FILE *stream);\n    fn fgetc(stream: *mut File) -> c_int;\n\n    // int fclose(FILE *stream);\n    fn fclose(stream: *mut File) -> c_int;\n}\n\nfn main() {\n    unsafe {\n        // Cの文字列を作る。ここではNULL終端したバイト列を作ってキャストしている。\n        let fname: *const c_char = b\"Cargo.toml\\0\".as_ptr() as *const _;\n        let mode: *const c_char = b\"r\\0\".as_ptr() as *const _;\n        // `FILE`はRustでは本来実体のない型なのでC関数を通してのみ初期化できる。\n        let file = fopen(fname, mode);\n        if file.is_null() {\n            println!(\"open file failed\");\n            return;\n        }\n        loop {\n            // Rustにとってはよく分からない値のままCの関数に渡す。\n            let c = fgetc(file);\n            if c == -1 {\n                break;\n            } else {\n                let c = c as u8 as char;\n                print!(\"{}\", c);\n            }\n        }\n        // 同じく実体のよく分からないままCの関数で終了処理をする。\n        if fclose(file) == -1 {\n            println!(\"close file failed\");\n        }\n    }\n}\n"
  },
  {
    "path": "ch12/ptr.rs",
    "content": "fn main() {\n    let x = 1;\n    // 参照からconstなポインタが作れる\n    let xptr: *const i32 = &x;\n    // 逆の変換はできない\n    // let xref: &i32 = xptr;\n    // ポインタヘの操作は基本的にアンセーフ\n    unsafe {\n        // ポインタの参照外しはアンセーフ\n        let x = *xptr;\n    }\n\n    let mut y = 2;\n    // ミュータブルな参照からミュータブルな参照が作れる\n    let yptr: *mut i32 = &mut y;\n    unsafe {\n        // 書き込みももちろんアンセーフ\n        *yptr = 3;\n    }\n\n    let z = Box::new(4);\n    // `Box`を参照してポインタも作れる\n    let zptr: *const i32 = &*z;\n\n    let s: &[u8] = b\"abc\";\n    // スライス(文字列)からポインタが作れる\n    let sptr: *const u8 = s.as_ptr();\n    unsafe {\n        // ポインタからスライス(文字列)も作れるが、こちらはアンセーフ。\n        let s = std::slice::from_raw_parts(sptr, s.len());\n    }\n}\n"
  },
  {
    "path": "ch12/ptr_ownership.rs",
    "content": "fn main() {\n    let boxed = Box::new(true);\n    // ここでboxedの所有権はムーブしてしまう\n    let ptr: *mut bool = Box::into_raw(boxed);\n    unsafe {\n        // ポイント先のメモリを解放するにはBox::from_rawでBoxに戻してあげる必要がある\n        // ここでポインタのデータ型の所有権をboxedが持つことになる\n        // 他に参照がないかはユーザが保証する必要がある。\n        let boxed = Box::from_raw(ptr);\n        // 気をつれないとたとえば下記のように2つ目のBoxも作れてしまう。\n        // これはRustの仮定を破ってしまう\n        // let boxed2 = Box::from_raw(ptr);\n    }\n}\n"
  },
  {
    "path": "ch12/repr-c/.gitignore",
    "content": "# コンパイラが生成する成果物や中間ファイルが置かれる\ntarget/\n"
  },
  {
    "path": "ch12/repr-c/Cargo.toml",
    "content": "[package]\nname = \"repr-c\"\nversion = \"0.1.0\"\nauthors = [\"Rust Bicycle Book <bicycle-book@example.com>\"]\nedition = \"2018\"\n\n[dependencies]\nlibc = \"0.2.0\"\n"
  },
  {
    "path": "ch12/repr-c/src/main.rs",
    "content": "use libc::{suseconds_t, time_t};\nuse std::mem;\nuse std::os::raw::c_int;\nuse std::ptr;\n\n// #[repr(C)]をつけることでCと相互運用できる型になる。\n// メモリ上の表現がC互換になるというだけで、それ以外は普通のRustの構造体として扱える。\n// struct timeval {\n//     time_t      tv_sec;     /* seconds */\n//     suseconds_t tv_usec;    /* microseconds */\n// };\n#[repr(C)]\n#[derive(Debug)]\nstruct Timeval {\n    tv_sec: time_t,\n    tv_usec: suseconds_t,\n}\n\n// struct timezone {\n//     int tz_minuteswest;     /* minutes west of Greenwich */\n//     int tz_dsttime;         /* type of DST correction */\n// };\n#[repr(C)]\n#[derive(Debug)]\nstruct Timezone {\n    tz_minuteswest: c_int,\n    tz_dsttime: c_int,\n}\n\nextern \"C\" {\n    // 上記で定義した型をFFIの型に使える。\n    // int gettimeofday(struct timeval *tv, struct timezone *tz);\n    fn gettimeofday(tv: *mut Timeval, tz: *mut Timezone) -> c_int;\n}\n\nfn main() {\n    unsafe {\n        // Cによって初期化するメモリは`mem::uninitialized`で確保できる。\n        // もちろん、Rustの構造体の初期化構文も使える。\n        let mut tv: Timeval = mem::uninitialized();\n        // あるいはNULLを渡したい場合は`ptr::null_mut`も使える。\n        let tz: *mut Timezone = ptr::null_mut();\n        let ret = gettimeofday(&mut tv as *mut _, tz);\n        if ret == -1 {\n            println!(\"failure\");\n            return;\n        }\n        println!(\"{:?}\", tv);\n    }\n}\n\n"
  },
  {
    "path": "ch12/small_cffi.rs",
    "content": "use std::os::raw::c_double;\n\n// インポートするCの関数群は`extern \"C\" { .. }`で囲む\nextern \"C\" {\n    fn cos(x: c_double) -> c_double;\n}\n\nfn main() {\n    // Cの関数はRustの管理下にないので全てアンセーフとして扱われる\n    unsafe {\n        // Rustの関数のように呼び出せる\n        println!(\"{}\", cos(1.5));\n    }\n}\n"
  },
  {
    "path": "ch12/static-link/.gitignore",
    "content": "# コンパイラが生成する成果物や中間ファイルが置かれる\ntarget/\n"
  },
  {
    "path": "ch12/static-link/Cargo.toml",
    "content": "[package]\nname = \"static-link\"\nversion = \"0.1.0\"\nauthors = [\"Rust Bicycle Book <bicycle-book@example.com>\"]\nedition = \"2018\"\n\n[dependencies]\n\n[build-dependencies]\ncc = \"1.0\"\n"
  },
  {
    "path": "ch12/static-link/build.rs",
    "content": "fn main() {\n    cc::Build::new().file(\"c_src/fib.c\").compile(\"fib\");\n}\n\n"
  },
  {
    "path": "ch12/static-link/c_src/fib.c",
    "content": "unsigned long long\nfib(unsigned int n)\n{\n  unsigned long long n0 = 1, n1 =1;\n\n  if (n == 0) {\n    return n0;\n  } else if (n == 1) {\n    return n1;\n  } else {\n    for(unsigned int i = 1; i < n; ++i) {\n      n0 ^= n1; n1 ^= n0; n0 ^= n1;\n      n1 += n0;\n    }\n    return n1;\n  }\n}\n\n"
  },
  {
    "path": "ch12/static-link/src/main.rs",
    "content": "use std::os::raw::{c_int, c_ulonglong};\n\n// kind=\"static\"とすることで静的リンクライブラリをリンクできる\n#[link(name = \"fib\", kind = \"static\")]\nextern \"C\" {\n    fn fib(n: c_int) -> c_ulonglong;\n}\n\nfn main() {\n    unsafe {\n        println!(\"fib(5) = {}\", fib(5));\n    }\n}\n\n"
  },
  {
    "path": "howto/running-msvc-compiler.md",
    "content": "# Windows MSVC：C/C++コンパイラを実行する方法\n\n本書の12章ではC言語で書いたプログラムをコンパイルするために、コマンドプロンプトやPowerShellのプロンプトからC/C++コンパイラを実行します。\nWindows MSVCのC/C++コンパイラ（`cl.exe`）を実行するために、MSVC環境へPathを通す方法を説明します。\n\n<!-- TODO: Visual Studio 2019の動作を確認する -->\n\n## コマンドプロンプトを使う場合\n\n本書執筆時点で最新版だったVisual Studio 2017を使って説明します。\n\nスタートメニューでキーワード「2017」で検索し、表示された「VC 2017 用 x64 Native Tools コマンドプロンプト」をクリックします。\n\n![VC 2017コマンドプロンプト](./images/msvc-command-prompt.png)\n\nコマンドプロンプトが起動し、Pathなどの環境変数が自動的に設定されます。\n試しにコンパイラを実行してみましょう。\n以下のようにバージョン情報と使い方（usage）が表示されるはずです。\n\n```\nC:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\BuildTools> cl\nMicrosoft (R) C/C++ Optimizing Compiler Version 19.16.27027.1 for x64\nCopyright (C) Microsoft Corporation.  All rights reserved.\n\nusage: cl [ option... ] filename... [ /link linkoption... ]\n```\n\n## PowerShellを使う場合\n\nPowerShellではPscxモジュールを使うのが簡単です。\n\n- https://www.powershellgallery.com/packages/Pscx\n\n### Pscxモジュールのインストール\n\nまず以下のコマンドを実行し、PowerShellでスクリプトを実行できるように設定します。\n\n```\nPS> Set-ExecutionPolicy RemoteSigned -Scope CurrentUser\n```\n\n続いてPscxと関連するモジュールをインストールします。\n\n```\nPS> Install-Module -Name VSSetup -Scope CurrentUser\nPS> Install-Module -Name Pscx -Scope CurrentUser -AllowClobber\n```\n\n### Pscxモジュールを使用してMSVC環境へPathを通す\n\nC++コンパイラを使う際は以下のコマンドを実行します。\nこれによりPathなどの環境変数が設定されます。\n`2017`のところは、お使いのVisual Studioバージョンに合わせて書き換えてください。\n\n```\nPS> Import-VisualStudioVars 2017 amd64\n```\n\nコンパイラを実行してバージョン情報などが表示されることを確認します。\n\n```\nC:\\Users\\user-name> cl\nMicrosoft (R) C/C++ Optimizing Compiler Version 19.16.27027.1 for x64\nCopyright (C) Microsoft Corporation.  All rights reserved.\n\nusage: cl [ option... ] filename... [ /link linkoption... ]\n```\n"
  },
  {
    "path": "install/docker.md",
    "content": "# DockerとDocker Composeのインストール\n\n**Docker**は軽量なコンテナ型のアプリケーション実行環境です。\n本書11章でリレーショナルデータベースのPostgreSQLを動かすために使用します。\nDockerには無償のCommunity Edition（CE）と有償のEnterprise Edition（EE）があります。\n本書の用途では無償のCEで十分でしょう。\n\n**Docker Compose**は1台のDockerホストマシン（みなさんのPCやMac）で使用できるオーケストレーションツールで、複数のコンテナで構成されるサービスを管理する時に役立ちます。\n無償で使用できます。\n\n## Linux\n\nLinuxではディストリビューションごとにDocker CEのインストール手順が異なります。\nここではUbuntu（x86_64）を例に説明します。\n他のディストリビューションについては、Dockerの公式ドキュメントにあるDocker CEのインストール手順を参照してください。\n\n- https://docs.docker.com/install/\n\n### Dockerのパッケージリポジトリの登録\n\n`apt`にDockerのパッケージリポジトリを登録しましょう。\n\nまず必要なツールをインストールします。\n\n```console\n$ sudo apt update\n$ sudo apt install \\\n    apt-transport-https \\\n    ca-certificates \\\n    curl \\\n    gnupg-agent \\\n    software-properties-common\n```\n\nDocker公式のGPGキーを登録します。\n\n```console\n$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \\\n  sudo apt-key add -\n\n$ sudo apt-key fingerprint 0EBFCD88\npub   rsa4096 2017-02-22 [SCEA]\n      9DC8 5822 9FC7 DD38 854A  E2D8 8D81 803C 0EBF CD88\nuid   [ unknown] Docker Release (CE deb) <docker@docker.com>\nsub   rsa4096 2017-02-22 [S]\n```\n\n[Get Docker CE for Ubuntu](https://docs.docker.com/install/linux/docker-ce/ubuntu/) にDocker公式のGPGキーのfingerprintが記載されているので、そのfingerprintと自分の登録したGPGキーのfingerprintが同じものであることを確認してください。\nなお上記のfingerprint（ `9DC8 5822 9FC7 DD38 854A  E2D8 8D81 803C 0EBF CD88` ）はこの文書を作成するときに筆者が確認したfingerprintであり、単なる例です。fingerprintを確認するときには必ず一次情報を参照しましょう。\n\nリポジトリを登録します。\n\n```console\n$ sudo add-apt-repository \\\n   \"deb [arch=amd64] https://download.docker.com/linux/ubuntu \\\n   $(lsb_release -cs) \\\n   stable\"\n```\n\n### Docker CEのインストール\n\nDocker CEをインストールします。\n\n```console\n$ sudo apt update\n$ sudo apt install docker-ce docker-ce-cli containerd.io\n```\n\n### ログインユーザを`docker`グループに追加する\n\n必須ではありませんが、`docker`コマンドが`sudo`なしで実行できるように、ユーザを`docker`グループに追加しましょう。\n\n```console\n$ sudo usermod -a -G docker $USER\n```\n\nグループの変更を反映するためにログアウトし、ログインしなおしてください。\n\n### Dockerのインストール結果の確認\n\n`docker run`コマンドで実際にコンテナが実行できることを確認します。\n\n```\n$ docker --version\nDocker version 18.09.5, build e8ff056\n\n$ docker run hello-world\n...\nHello from Docker!\nThis message shows that your installation appears to be working correctly.\n...\n```\n\n### Docker Composeのインストール\n\n続いてDocker Composeをインストールしましょう。\nWebブラウザで以下のページを開きます。\n\n- https://github.com/docker/compose/releases/latest\n\nDocker Composeの最新バージョンのリリースページが表示されますので、バージョン（例：1.24.0）が確認できたら以下のコマンドを実行します。\n\n```\n$ sudo -i\n# export VERSION='1.24.0'    # 最新リリースのバージョン\n# export BASE_URL='https://github.com/docker/compose/releases/download'\n# curl  -L ${BASE_URL}/${VERSION}/docker-compose-`uname -s`-`uname -m` \\\n        -o /usr/local/bin/docker-compose\n# chmod +x /usr/local/bin/docker-compose\n# exit\n```\n\nインストールできたらバージョンを確認します。\n\n```\n$ docker-compose --version\ndocker-compose version 1.24.0, build 0aa59064\n```\n\nこれでインストール完了です。\n\n## macOS\n\nmacOSではDockerプロジェクトが配布している「Docker Desktop for Mac」アプリケーションをインストールします。\nMac OS X El Capitan 10.11かそれ以降のmacOSで使用できます。\n\nDocker CEはLinuxカーネルの機能を使っており、コンテナ内で実行されるアプリケーション（例：PostgreSQL）も、macOSのものではなく、Linuxのものとなります。\nDocker Desktop for Macではそのために、xhyveという仮想化ハイパーバイザ上でごく軽量なLinux仮想マシンを実行し、その中でコンテナを実行します。\n\nではインストールしましょう。\nWebブラウザで以下のURLを開き「Download from Docker Hub」のボタンを押します。\n\n- https://docs.docker.com/docker-for-mac/install/\n\nDocker Hub内のDocker Desktop for Macのページに移動します。\nDocker Hubにログインしている場合には「Get Docker」というボタンが表示されるので、そのボタンを押して`Docker.img`というディスクイメージをダウンロードします。\nDocker Hubにログインしていない場合には「Please Login to Download」というボタンが表示されるので、そのボタンを押して指示に従います。\n\nダウンロードした`Docker.dmg`をダブルクリックしてマウントします。\nフォルダが開いたら、そこにある`Docker.app`をアプリケーションフォルダへドラッグします。\n`Docker.app`にはDocker CEだけでなくDocker Composeなども含まれていますので、これでインストールは完了です。\n\nインストール結果を確認しましょう。\nラウンチパッドからDockerアプリを起動します。\nメニューバーにDockerのクジラのアイコンが表示されますので、クリックしてステータスが「Docker is running」に変わるのを待ちます。\nターミナルを開いて以下のように入力してください。\n\n```\n$ docker --version\nDocker version 18.09.2, build 6247962\n\n$ docker-compose --version\ndocker-compose version 1.23.2, build 1110ad01\n\n$ docker run hello-world\n...\nHello from Docker!\nThis message shows that your installation appears to be working correctly.\n...\n```\n\nこれでインストール完了です。\n\n## Windows\n\nWindowsではDockerプロジェクトが配布している「Docker Desktop for Windows」アプリケーションをインストールします。\n仮想化ハイパーバイザのHyper-Vを使用しますので、Windows 10（64ビット版）のProfessional以上のエディションが必要です。\nもしWindows 10（64ビット版）のHomeエディションをお使いの場合は「Docker Toolbox for Windows」という、少し古いものの仮想化ソフトのVirtualBoxを使用するアプリケーションが使えます。\n\nDocker CEはLinuxカーネルの機能を使っており、コンテナ内で実行されるアプリケーション（例：PostgreSQL）も、Windowsのものではなく、Linuxのものとなります。\nWindows版でHyper-VやVirtualBoxを使用しているのはそのためです。ごく軽量なLinux仮想マシンを実行し、その中でコンテナが実行されます。\n\nではインストールしましょう。\nHyper-VベースのDocker Desktop for Windowsを使用するなら、Webブラウザで以下のURLを開き「Download from Docker Hub」のボタンを押します。\n\n- https://docs.docker.com/docker-for-windows/install/\n\nDocker Hub内のDocker Desktop for Windowsのページに移動します。\nDocker Hubにログインしている場合には「Get Docker」というボタンが表示されるので、そのボタンを押してインストーラをダウンロードします。\nDocker Hubにログインしていない場合には「Please Login to Download」というボタンが表示されるので、そのボタンを押して指示に従います。\n\nVirtualBoxベースのDocker Toolbox for Windowsを使用するなら、Webブラウザで以下のページを開き、「Get Docker Toolbox for Windows」のボタンを押します。\n\n- https://docs.docker.com/toolbox/overview/\n\nインストーラがダウンロードできたらダブルクリックし、画面の指示に従ってインストールします。\nDocker CEだけでなく、Docker Composeなども同時にインストールされます。\n\nインストール結果を確認しましょう。\nスタートメニューからDockerアプリを起動します。\nタスクトレイにDockerのクジラのアイコンが表示されますので、クリックしてステータスが「Docker is running」に変わるのを待ちます。\n起動したらコマンドプロンプトかPowerShellを開いて以下のように入力してください。\n\n```\n$ docker --version\nDocker version 18.09.2, build 6247962\n\n$ docker-compose --version\ndocker-compose version 1.23.2, build 1110ad01\n\nPS> docker run hello-world\n...\nHello from Docker!\nThis message shows that your installation appears to be working correctly.\n...\n```\n\nこれでインストール完了です。\n"
  },
  {
    "path": "install/windows10-vcpkg.md",
    "content": "# Windows MSVC：vcpkgパッケージマネージャのインストール\n\nvcpkgはC++ライブラリを管理するためのパッケージマネージャで、Microsoftがオープンソースで提供しています。Windows、Linux、macOSに対応しています。\n\n本書ではWindows MSVC環境をご使用の場合のみvcpkgが必要になります。具体的には11章でlibpqというPostgreSQLのクライアントライブラリをインストールするためにvcpkgを使います。ここではWindows MSVC環境にvcpkgをインストールする手順を説明します。\n\n## 準備\n\nWindowsでvcpkgをインストールするにはMSVCのC++コンパイラが必要です。\n本書の2-1-7項を参照して、Visual C++ Build Tools、または、Visual Studio Communityを事前にインストールしてください。\n\n## vcpkgのソースコードのダウンロード\n\nGitHubからvcpkgのソースコードを取得します。\nウェブブラウザで以下のURLを開いてください。\nvcpkgリポジトリの最新の内容がzipファイルとしてダウンロードされます。\n\n- https://github.com/Microsoft/vcpkg/archive/master.zip\n\nこのzipファイルをインストールしたい場所（例：`C:\\src\\vcpkg`）へ展開します。\n\n## vcpkgのビルド\n\nPowerShellかコマンドプロンプトでvcpkgを展開したディレクトリへ移動します。\n以下のように`bootstrap-vcpkg.bat`を実行し、vcpkgをビルドします。\n\n```powershell\n# vcpkgを展開したディレクトリへ移動する\nPS> cd c:\\src\\vcpkg\n\n# vcpkgをビルドする\nPS> .\\bootstrap-vcpkg.bat\n...\nBuilding vcpkg.exe... done.\n\n# ビルドできたのでバージョンを表示する\nPS> .\\vcpkg version\nVcpkg package management program version 2018.11.23-nohash\n\nSee LICENSE.txt for license information.\n```\n\n## 環境変数を設定する\n\n環境変数`VCPKG_ROOT`にvcpkgのインストールディレクトリを設定してください。\nPowerShellで一時的に設定するなら以下のようにします。\n\n```powershell\nPS> $Env:VCPKG_ROOT += \"c:\\src\\vcpkg\"\n```\n\nこの設定を忘れると11章の`diesel_cli`や`log_collector`のビルドに失敗しますので注意してください。\n\nこれでvcpkgのインストールは完了です。\n\n## vcpkgの詳しい情報\n\n本書11章のプログラムを実行するだけでしたら、vcpkg自体については特に知らなくても問題ありません。11章に書かれているとおりコマンドを実行すれば大丈夫です。\n\nもしvcpkgについて詳しく知りたくなったら、以下の日本語ドキュメントが役に立つでしょう。\n\n- https://docs.microsoft.com/ja-jp/cpp/build/vcpkg?view=vs-2019\n"
  }
]