4. プロジェクトの形 — src/ の 20 のモジュールと、1 ファイル版の対応
完成版は のふつうのプロジェクトで、src/ の下に段ごとのフォルダがあります。 がモジュールを束ね、 がコマンドラインの入口です。モジュールは 20 個(フォルダごとの を除く)で、各モジュールの先頭には「この部品は何で、仕様のどこに対応し、何を省いたか」をコメントで書いてあります。
モジュールの分け方は変換の列そのままです。url と http は 1 ファイルずつ。html は (トークンの型)/ (字句解析)/ dom(木)/ (構文解析)の 4 つ。css も同じ 4 つ。 は style()/ layout()/ (描画)。js は lexer / ast / parser / runtime。browser.rs が 1 ページ分をつなぎます。
各レッスンの「1 ファイルで動く版」は、この src/ のモジュールを mod として 1 つのファイルに並べ、末尾にそのレッスン用の main を足したものです。中身は同じソースから機械的に作っているので、で読んだコードと cargo プロジェクトのファイルは一致します。cargo に移すときは、mod ブロックの中身をそのファイル名で src/ に置くだけです。
テストは各モジュールの末尾に mod tests として置いてあります。 で 78 本が走ります。1 ファイル版でも 2021 で同じテストが走ります。字句解析のように入出力が決まっている部品は、先にテストを書いてから実装を埋める書き方がよく合います。
開発のどこに活かすか: 「段 = モジュール = ファイル」で切る分け方は、パーサやパイプライン処理のある業務コードにそのまま使えます。入力の型と出力の型を境界にして分けると、1 段だけ差し替える(例: 字句解析を手書きからライブラリに替える)ことが他の段に波及しません。
点線の付いた語はタップすると説明が出ます。用語集を開く →
サンプルコード(フレームワーク環境が必要なため表示のみ)
// Cargo.toml
[package]
name = "tinybrowser"
version = "0.1.0"
edition = "2021"
[dependencies]
# 外部クレートなし
// ─── src/ の構成 ───
// src/
// lib.rs モジュールを束ねる(下のコード)
// main.rs コマンドラインの入口
// url.rs B 章
// http.rs C 章
// html/token.rs D 章
// html/tokenizer.rs D 章
// html/dom.rs E 章
// html/parser.rs E 章
// css/token.rs F 章
// css/tokenizer.rs F 章
// css/cssom.rs F 章
// css/parser.rs F 章
// renderer/style.rs F 章
// renderer/layout.rs G 章
// renderer/paint.rs G 章
// js/lexer.rs H 章
// js/ast.rs H 章
// js/parser.rs H 章
// js/runtime.rs H 章
// browser.rs I 章
// ─── src/lib.rs ───
//! tinybrowser: 学習用の小さなブラウザ。
//!
//! 処理の流れは本物のブラウザと同じ順番にしてある。
//!
//! 1. `url` 文字列の URL を部品(スキーム・ホスト・ポート・パス・クエリ)に分ける
//! 2. `http` TCP でつないで HTTP/1.1 の GET を送り、レスポンスを分解する
//! 3. `html` HTML をトークンに切り(字句解析)、DOM ツリーに組み立てる(構文解析)
//! 4. `css` CSS をトークンに切り、CSSOM(ルール・セレクタ・宣言)に組み立てる
//! 5. `renderer` 要素ごとの計算値を決め(カスケード・継承)、箱の位置と大きさを決め(レイアウト)、表示リストにする(描画)
//! 6. `js` JavaScript をトークン → 抽象構文木 → 評価し、document.getElementById / textContent で DOM を書き換える
//! 7. `browser` 上の部品を 1 ページ分つなぐ
//!
//! 外部クレートは使わない。std だけで書いてある。
pub mod browser;
pub mod css;
pub mod html;
pub mod http;
pub mod js;
pub mod renderer;
pub mod url;
手元で動かす(配布物)
- 完成版のプロジェクト(tinybrowser.zip)
- GitHub: kazumasamatsumoto/rust-tiny-browser ↗git clone https://github.com/kazumasamatsumoto/rust-tiny-browser.git && cd rust-tiny-browser && cargo test