As Sloth As Possible

可能な限りナマケモノでありたい

タグ:Rust

Rustで遊んでみよう第二弾、本当は並列処理を試してみたにする予定だったんだけど何故かHTTPパーサが出来てた。

経緯はこう。

「並列実行できるクローラ作ってください」「作るってどのレベルで?HTTPパーサから?」みたいなのがRust村みたいです。まぁ言うてまだアプリケーション層だ。TCP/IPからなんとかしましょうとか言われなくてよかった。一応C国からの輸入は許されてるけど、TLSとかならともかくHTTPくらいなら自力でなんとかできるでしょ、普段そんなの車輪の再発明だしやんないからいい機会だ、ってことでご用意しましたのがこちらになります

一応それらしいものにはなって、ステータスラインやリクエストラインの処理、ヘッダをフィールド名と値に分解、keep-aliveやupgradeの検出、chunkedなボディのデコード、くらいはできる。

ソース見ると一瞬うってなるけど、やってることはといえば、愚直に与えられたバイト列を1バイトずつチェックしてって適宜コールバックを呼ぶ、これだけ。TcpStreamには直接は触らないし、正規表現や文字列のパターンマッチはおろかcharへのキャストすらしてない。パースした結果を構造体に詰め直すとかはコールバック側で勝手にやってくださいのぶん投げ。

もっと綺麗に書けるのになんでこんなことになってるかというと、素直に書いてもつまらないので、crazyな速度と評判のCで書かれたhttp-parserを参考に速度最優先で作ったから。その甲斐あって400バイト強の普通のブラウザのGETリクエストをただパースするだけなら、手元の環境だと3~5μsくらいで 処理できるようになった(--opt-level=3でコンパイルしたとき)。

(試しに10万回ぶんまわすサンプルコード書いてみて、元のCのやつと比較してみたら、Cの方が550ms程度なのに対して俺が書いた方が330msで終わった。…なんで勝ってんだろ。多分なんかの間違いだろうなー。実装漏れしてるとか最適化でほぼ何もしなくなるコードになってるとかそんなとこだとは思う…。)

そんな感じで何もない荒野を耕しては雑草植えてますけどこれ結構楽しいです。んでよーやくHTTPクライアントに手を付け始めたけど、こっちの方は今任意のリクエスト投げて結果を表示するとこまではできた。keep-alive、リダイレクトも対応、Content-Typeにcharsetが付いてたらその文字コードでボディをデコードもできる。あとやりたいのは、POSTでフォームデータとかファイルとか送れるようにするのと、gzip/deflate対応と、TLSサポート(LibreSSLとSecure Transport選べるようにとかしたい)あたりか。まだ先長そうだなー。

なんでなのかと聞かれても「なんか暇だったから…」としか。

いや元々はこう周期的に来る「なんか仕事と全然関係ないコード書きたい」期だっただけなんだけど、Goとかで遊んでる最中にひょんなことからRustを見付けてしまってへー面白そうとか手を出してみることになり、「慣れない言語を使うときはとりあえずWhitespaceの処理系を作ってみるとなんか慣れたような気分になる」という癖でですね。なんか出来ちゃった。

記事書いてる時点の最新のnightly(v0.12.0-pre)ではコンパイル通るのを確認済み(というか多分0.12.0でしかビルドできない。流石いつβが出るとも分からないα言語、0.10.0と0.11.0と0.12.0で互換性無いし、ドキュメント見に行ったら標準ライブラリを含むほとんどのAPIがexperimentalだった)。rust-albinoの方をcloneしたら最新のrustcと対応するcargoをrustupかなんかで入れて、

cargo build
するとビルドできる。homebrewでも入れられるけどバイナリだと0.11.0、ソースからのビルドだとかなり時間かかるので大人しくnightlyのバイナリ使うがよろし。

Albinoがコマンドラインツールで、こいつがWhitespaceを実行したり逆アセンブルしたりしてくれる。最初は普通にインタプリタ作ってたんだけど、例のごとくWhitespace読めないし書けないからアセンブリ言語でもでっちあげよう、あとその昔書いたDTとかも動かしたいよねー、とかやってたらいつの間にかVMとパーサが分離して副産物として何故かライブラリになっちゃったのがWhitebase

厳密に言うと本体はWhitebaceの方でAlbinoはただのインターフェースだったりするけど細かいことは気にしない。先に名前が決まったのはWhitebaseの方で、Whitespaceの命令セットを持ったVMとパーサのライブラリなので「白地」というのが由来であって決して某19歳に見えない艦長率いる連邦の戦艦ではない。合わせてツールの方はWhitedevilにしようかなーとか一瞬考えたけどコマンド名としては長すぎるしrx78とかエイリアスするはめになるのでアルビノにした。VMとパーサが分離した結果どういうわけかBrainf*ck派生の言語をWhitespaceの命令セットに変換できるようになったので、「本来白くないものまで白くなっている」からアルビノなんです。

得られたもの。Rustがなかなか触っていて楽しいということが分かった。いまどきっぽいサブコマンド型のコマンドどうやって作ってるのかなーってのが分かった。WhitespaceもしくはBrainf*ckのトークンの内部表現を返すイテレータさえ実装できれば簡単にオレオレ言語が作れるライブラリが出来たので、今後さっと言語を作ってドヤリングしたいときは一瞬で出来るようになった。Brainf*ckの任意のプログラムからWhitespaceのコードが生成できるようになった。

失なったもの。時間。結構な無駄な時間。

↑このページのトップヘ