Open7
「作って学ぶブラウザの仕組み」読書メモ
手持ちの環境が古すぎてqemuが非対応とのことで、まずはqemuだったりnoli使わなくて良いところを実装しながら拾い読みしていく。良い加減Mac買い直さないとなあ...
レポジトリはこれ
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,
})
}
}
3章: HTTPを実装する
qemuが入れられなくnoliがビルドできないのでスキップ
4章: HTMLを解析する
HTMLの標準仕様なんてあるのか。まあ言われてみればブラウザ固有の表現とかされてもつらいもんな。https://html.spec.whatwg.org
いきなりStateを全部実装するのは煩雑なので最小限必要な以下4つだけでまずは実装してみる。
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum State {
Data,
TagOpen,
EndTagOpen,
TagName,
}
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
を消費していく感じで実装してみる。