Open7

「作って学ぶブラウザの仕組み」読書メモ

Yoshiki KudoYoshiki Kudo

手持ちの環境が古すぎてqemuが非対応とのことで、まずはqemuだったりnoli使わなくて良いところを実装しながら拾い読みしていく。良い加減Mac買い直さないとなあ...

Yoshiki KudoYoshiki Kudo

2章: URLを分解する

公式サンプルsababook上では全プロパティをStringで持たせてるけどなんか違和感あるので以下のようにしてみた。何か不具合あれば後で適当に直そう。

#[derive(Debug, Clone, PartialEq)]
pub struct Url {
    host: String,
    port: u16,
    path: Option<String>,
    searchpart: BTreeMap<String, String>,
}

あとは不適切な文字列の場合はそもそもインスタンス化できない方が自然かなと思うのでnewではなくtry_fromで以下のようにした。

impl TryFrom<&str> for Url {
    type Error = Error;

    fn try_from(url: &str) -> Result<Self, Self::Error> {
        if !url.starts_with("http://") {
            return Err(Error::InvalidScheme(url.to_string()));
        }

        let url = url.trim_start_matches("http://");

        let host = extract_host(url);
        let port = extract_port(url)?;
        let path = extract_path(url);
        let searchpart = extract_searchpart(url);

        Ok(Self {
            host,
            port,
            path,
            searchpart,
        })
    }
}
Yoshiki KudoYoshiki Kudo

3章: HTTPを実装する

qemuが入れられなくnoliがビルドできないのでスキップ

Yoshiki KudoYoshiki Kudo

いきなりStateを全部実装するのは煩雑なので最小限必要な以下4つだけでまずは実装してみる。

#[derive(Debug, Clone, Eq, PartialEq)]
pub enum State {
    Data,
    TagOpen,
    EndTagOpen,
    TagName,
}
Yoshiki KudoYoshiki Kudo

HtmlTokenizerはイテレータでトークンであるHtmlTokenを返す。ただ、内部実装は1文字ずつ消費しながらloop回す感じなので、現在更新中のトークンをlatest_tokenというプロパティを持つ。

#[derive(Debug, Clone, Eq, PartialEq)]
pub struct HtmlTokenizer {
    state: State,
    reconsume: bool,
    latest_token: Option<HtmlToken>,
    input: Vec<char>,
    buf: String,
}

公式サンプルsababook上では処理中の文字を参照するためにpos: usizeを持つが、これは一旦無くして毎回inputを消費していく感じで実装してみる。