hyper - Rustのhttp clienet / reqwestとどちらを選ぶ?

hyperはrustのlow levelなhttpライブラリだ。他の有名なhttp clientはhyperをベースにしてるケースが多い。 hyperは設計から非同期であり、client side server side APIの両方を提供する。もし、より便利なHTTPクライアントが欲しいのであれば、reqwestをチェックすることをhyperは推奨している。 

たとえばreqwestを使えば、以下のように簡単にhttpリクエストを実行することができる。

https://docs.rs/reqwest/0.8.4/reqwest/struct.Client.html

let client = Client::new();

// Parse an `http::Uri`...
let uri = "https://www.google.com".parse()?;

// Await the response...
let resp = client.get(uri).await?;

println!(" status :  {}", resp.status());

regressionとは?

ソフトウェアにおけるregressionとは、ソフトウェアのバグの一種で、それまで動作していた機能が動作しなくなることです。これは、ソフトウェアのソースコードに新機能の追加やバグ修正などの変更が加えられた後に発生することがあります。

"We don't cause regressions"は、Linuxカーネル開発の第一のルールです。 Linux創始者であり開発責任者であるリーナス・トーバルズ氏が自ら制定しそれを遵守する。

Unsafe Rustとは?

Unsafe Rustとは?

通常Rustはコンパイル時にメモリ安全性が保証される。しかし、実はRustにはメモリ安全性を保証しない第二の言語が隠れている。それがUnsafe Rustだ。

Unsafe Rustがなぜ必要か?

Unsafe Rustが存在するのは、静的解析が本質的に保守的であるためです。こうしたコンパイラは、コードが保証を守っているかどうかを判断しようとするとき、無効なプログラムを受け入れるぐらいなら、有効なプログラムを拒否した方が良いと考えます。コードが正常であっても、Rustコンパイラが確信を持てるだけの情報を持っていなければ、そのコードは拒否されます。このような場合、安全でないコードを使用して、コンパイラに "私を信じてください、私は何をやっているか分かっています" と伝えることができます。デメリットは、自己責任で使用する必要があることです。安全でないコードを間違って使用すると、ヌルポインタの再参照など、メモリの非安全性による問題が発生する可能性があります。

 

不透明 (OPAQUE) 型とは

コンピュータサイエンスにおいて、不透明 (OPAQUE) 型とは、その具体的なデータ構造がインターフェースで定義されていないデータ型のことである。このデータ型の値は、その情報にアクセスできるサブルーチンを呼び出すことによってのみ操作できるため、情報の隠蔽が可能になる。

Genericで使われるstatic lifetimeとは

static lifetimeは、オブジェクトがどのような寿命よりも長持ちするかを定義する。

必ずしも、プログラムが終了したときにだけ削除されるとは限りません。ただ、このオブジェクトが他のどのオブジェクトよりも先にスコープ外に出ることを、Rust が強制する必要がないことを意味しているのです。

例えば、&'static strは'static lifetimeを持ちますが、i64やStringも同じです。そのため、次のような関数 。

fn take<T : Clone + 'static>(t : T);

は文字列と整数を引数として持つことができます。

静的リソースは他のリソースより先に破壊される必要がなく、必要なだけ生き続けることができるのです。一方、'a リソースには寿命があり、親がスコープ外に出る前に破棄されなければならない。

しかし、私たちは並行処理をしています。つまり、あるスレッドの何かが他のスレッドの何かより先に実行されることは保証できないので、あるスレッドのオブジェクトが他のスレッドのオブジェクトがスコープ外に出る前に破壊されることは約束できない。

したがって、オブジェクトを他のスレッドに送るには、そのオブジェクトがそれ自体で生きていけることを要求するのが最も安全な選択です。

Who コマンドを掘り下げよう

Who コマンドとは

基who コマンドでは、現在システムにログオンしているユーザーを一覧表示することができます。 

$ who
user1 tty2         2020-08-30 15:06 (tty2)
user1 pts/1        2020-08-30 15:06 (tmux(1555).%0)
user1 pts/2        2020-08-30 16:41 (tmux(1555).%6)
user1 pts/4        2020-08-30 15:57 (tmux(1555).%3)

物理的な端末 tty2 と 3 つの疑似端末でログインしていることを教えてくれている。この例だと現在のGnome Shellのセッションはtty2で実行されており、3つのtmuxウィンドウが開いている。

しかし、これらの情報はどこから取得しているのか?Linuxではすべてファイルとして扱われることを思い出すと、この情報はおそらくファイルからだと推測できるが、どのファイルにどのようにデータが保存されているのか確認してみたい。

ちょっとしたリバースエンジニアリング

whoコマンドが何をしているのかを見るために、ソースコードを見つけてそれを掘り下げてみることができる。また、代わりにstraceを使ってプロセスが何をしているかをチェックするのが面白い。

$ strace who 2>&1 | grep open
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/lib/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/var/run/utmp", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/etc/localtime", O_RDONLY|O_CLOEXEC) = 3

最初のファイル /etc/ld.so.cache, /usr/lib/libc.so.6 はプロセスが読み込んだ共有ライブラリである。

次に、/usr/lib/locale/local-archive, /var/run/utmp, /etc/localtime が開かれる。これらのファイルが何を保存しているのか見てみよう。

manで確認してみると、マニュアルの第5章は「ファイル形式と規約(“file formats and conventions” )」にページが割かれていることがわかる。ここをしらべよう。

locale-archive

$ man -wK 5 '/usr/lib/locale/locale-archive'
Sends us to locale(5) where we can read:

ロケール定義ファイルには、localedef(1) コマンドがそれをバイナリロケールのデータベースに変換するために必要なすべての情報が含まれている。 このページでは、これらの情報についてのより詳しい説明のために locale(7) にもかかれている。

ロケールとは、言語と文化のルールの集合です。ロケールとは、言語や文化のルールの集合です。 メッセージの言語、文字セット、語彙・図形の規則などが含まれます。プログラムは、異文化に移植できるようにロケールを決定し、それに応じて行動できるようにしなければなりません。 そこで、who コマンドはこのファイルを読み込んで、おそらく setlocale(3) 関数を使って、情報の書式や表示方法を調べていることがわかるだろう。

これは以下のように実際に確認することができる。

$ LC_ALL='fr_FR.utf8' who
gauthier tty2         Sep  2 11:38 (:1)
gauthier pts/1        Sep  2 12:11 (tmux(2445).%0)
gauthier pts/2        Sep  2 12:37 (tmux(2445).%1)
gauthier pts/3        Sep  2 13:04 (tmux(2445).%2)

確かに、日付は同じようにフォーマットされていません!

localtime
$ man -wK 5 '/etc/localtime'

localtime(5) は

・etc/localtime ファイルは、アプリケーションがユーザに表示するために使用するローカルシステムのシステム全体のタイムゾーンを設定。

となる。

おそらくwhoがこのファイルを使っているか(あるいはこのファイルを使っている関数を使っているか)は、ユーザによって設定された正しいタイムゾーンを使ってタイムスタンプ(誰の出力の4列目と5列目)をprintしてうr