UTF-8 validationとmruby/c

これは mrubyファミリー Advent Calendar 2023 の2日目の記事です。

こんにちは。ima1zumiです。

私はmruby/cでUTF-8を使えるように実装しています。そのなかでRubyString#valid_encoding みたいな機能を実装しているのでその背景とコードについて書きます。

mruby/c についての説明は昨日のはすみさんの記事がわかりやすかったので、そちらをご覧ください。

しまもん | はすみきん | mrubyファミリーの歩き方(を装ったビルドシステムの話)

現在のmruby/cの文字コード

現在のmruby/cの文字コードはCRubyでいうASCII-8BITのみ使える状態です。文字をバイナリとして格納しているので、どんな文字でも入れられます。ただし、文字数を取るようなメソッドではバイト単位で判定されます。例えば "あ" のようにUTF-8でマルチバイト文字を作ると "あ".size # => 3 となります。

これはUTF-8での \xE3\x81\x82 で3バイトあるため3文字と判定されています。その他にもString#indexなどが文字単位ではなくバイト単位で動いてしまいます。

UTF-8を使えるようにする

というわけでUTF-8を使えるように実装しているのですが、一つ問題がありました。mruby/cはなるべく軽量に作りたいので、Encodingクラスを作りたくありません。そのためビルドオプションでStringのEncodingをASCII-8BIT相当のものか、UTF-8かを切り替える方針にしようとしています。

しかしUTF-8にはinvalidなバイト列があります。たとえば以下のように、 \xE3\x80\x80 はvalidですが、 \xE3\x80\x7F はinvalidです。

String.new("\xE3\x80\x80", encoding: Encoding::UTF_8).valid_encoding?
# => true
String.new("\xE3\x80\x7F", encoding: Encoding::UTF_8).valid_encoding?
# => false

UTF-8にはこのバイトで始まった場合続くバイトはこれしか取れない、というルールがあります。 \xE3\x80\x7F はそれに違反しているためinvalidな文字列です。

仕様はこちらに書いてあります。

Table 3-7. Well-Formed UTF-8 Byte Sequences

https://www.unicode.org/versions/Unicode15.1.0/ch03.pdf

CRubyでは違反した場合文字列を作成できないか、invalidな文字列だというフラグが立つようになっています。しかしビルドオプションでEncodingを切り替えるmruby/cでは、その設定だとUTF-8を有効にしたときにバイト列をStringで作れなくなってしまい困ります。セキュリティ上invalidな文字列を扱うのはよくないのですが、mruby/cではワンチップマイコン向けの言語ということもあり、

ということで、Stringはどんな文字列でも作成できるが、valid_encoding?でvalidかどうか検査できるようにします。

実装

素朴にTable 3-7を実装しました。ビット演算でできるところはビット演算にして、命令を減らすようにしています。

ちなみにUTF-8 validationはいろいろ高速化の方法が研究されている*1ようで、これはあまり最適ではありません。

static void c_string_valid_encoding(struct VM *vm, mrbc_value v[], int argc)
{
#if MRBC_USE_STRING_UTF8
  unsigned char *str = (unsigned char *)mrbc_string_cstr(&v[0]);
  int len = mrbc_string_size(&v[0]);
  int i = 0;

  if (len == 0) {
    SET_TRUE_RETURN();
    return;
  }

  while (i < len) {
    // 1 byte
    if (str[i] <= 0x7F) {
      i++;
    // 2 bytes
    // First byte: C0..DF
    // Second byte: 80..BF
    } else if ((0xC2 <= str[i]) && (str[i] <= 0xDF) && (str[i+1] & 0xC0) == 0x80) {
      i += 2;
    // 3 bytes
    // First byte:  E0
    // Second byte: A0..BF
    // Third byte:  80..BF
    } else if ((str[i] == 0xE0) && (str[i+1] & 0xE0) == 0xA0 && (str[i+2] & 0xC0) == 0x80) {
      i += 3;
    // First byte:  E1..EC
    // Second byte: 80..BF
    // Third byte:  80..BF
    } else if (0xE1 <= str[i] && str[i] <= 0xEC && (str[i+1] & 0xC0) == 0x80 && (str[i+2] & 0xC0) == 0x80) {
      i += 3;
    // First byte: ED
    // Second byte: 80..9F
    // Third byte: 80..BF
    } else if ((str[i] == 0xED) && ((str[i+1] & 0xE0) == 0x80) && (str[i+2] & 0xC0) == 0x80) {
      i += 3;
    // First byte:  EE..EF
    // Second byte: 80..BF
    // Third byte:  80..BF
    } else if ((str[i] == 0xEE || str[i] == 0xEF) && (str[i+1] & 0xC0) == 0x80 && (str[i+2] & 0xC0) == 0x80) {
      i += 3;
    // 4 bytes
    // First byte:  F0
    // Second byte: 90..BF
    // Third byte:  80..BF
    // Fourth byte: 80..BF
    } else if ((str[i] == 0xF0) && (0x90 <= str[i+1]) && (str[i+1] <= 0xBF) && (str[i+2] & 0xC0) == 0x80 && (str[i+3] & 0xC0) == 0x80) {
      i += 4;
    // First byte:  F1..F3
    // Second byte: 80..BF
    // Third byte:  80..BF
    // Fourth byte: 80..BF
    } else if ((0xF1 <= str[i]) && (str[i] <= 0xF3) && (str[i+1] & 0xC0) == 0x80 && (str[i+2] & 0xC0) == 0x80 && (str[i+3] & 0xC0) == 0x80) {
      i += 4;
    // First byte:  F4
    // Second byte: 80..8F
    // Third byte:  80..BF
    // Fourth byte: 80..BF
    } else if ((str[i] == 0xF4) && (str[i+1] & 0xF0) == 0x80 && (str[i+2] & 0xC0) == 0x80 && (str[i+3] & 0xC0) == 0x80) {
      i += 4;
    } else {
      SET_FALSE_RETURN();
      return;
    }
  }
  SET_TRUE_RETURN();
#else
  SET_TRUE_RETURN();
#endif
}

3日目は執筆者募集中です!

IRBの型補完を有効にする方法

IRB 1.9.0から tompng さんの実装によりIRBでは型補完が使えるようになりました。katakata_irb の機能がIRB本体に入った形です。

今までは正規表現での補完だったため精度があまり良くなかったのですが、型のパワーを得てより速く精度の良い補完になりました。

今のところデフォルトでは正規表現補完を利用するため、型補完を利用するには設定が必要です。

github.com

依存関係

Ruby 3.0.0 以上、RBS、prism が必要です。

prism がない場合メッセージが出て、正規表現補完にフォールバックします。

型補完を有効にする方法

.irbrc で設定

IRB.conf[:COMPLETOR] = :type

環境変数で設定

IRB 1.9.1 以降で有効

IRB_COMPLETOR=type

Railsでは例えば development.rb でこんな感じで有効にできます。

Rails.application.configure do
  console do
    ENV["IRB_COMPLETOR"] ||= "type"
  end
end

irb bin/console などのオプションとして渡す

irb --type-completor

設定の確認方法

irb_info でどの補完を使っているか分かります。

irb(main):001> irb_info
Ruby version: 3.3.0
IRB version: irb 1.9.1 (2023-11-21)
InputMethod: RelineInputMethod with Reline 0.4.0
Completion: Autocomplete, TypeCompletion::Completor(Prism: 0.17.1, RBS: 3.3.0) # 型補完
.irbrc path: /Users/mi/.irbrc
RUBY_PLATFORM: x86_64-darwin21
East Asian Ambiguous Width: 1
=> nil

Kaigi on Rails 2023に参加した

浅草橋で行われたKaigi on Rails 2023に参加した。

印象に残ったセッション

やさしいActiveRecordのDB接続のしくみ

step by step でDBに接続するまでの過程を追いかけ、どのようなクラスがどんな働きをしているのかの解説だった。重要なポイントに絞ってありすごく理解しやすかった。接続までの過程でどんなクラスが登場するか分かったので今後何か困ったときにこの知識が活きそう。

数十億のレコードを持つ5年目サービスの設計と障害解決

レコード数が少ないときには簡単にできたことが、レコード数が多くなってくることで問題になったり解決が難しくなってくる。idinteger にしてしまう問題は以前私たちのプロジェクトでもレビューで指摘があり、改めて気をつけようと思った。

A Decade of Rails Bug Fixes

10年前のバグ修正と、10年後のバグ修正の話。byroot のような素晴らしいプログラマがコードの正しさよりもコミュニケーションを大事にしよう、と言うのはすごい説得力がある。私もNiceな態度を心がけようと思った。

:sorena:

後半は byroot 以外にこのバグを直せる人が世界に何人いるだろう?と思いながら聞いていた。「git log を見る時点で(バグの原因探しとしては)絶望的な状況」というのは確かにそうだと思った。再現手順を見つけるとか、先にやることがある。

初めてのパフォーマンス改善 〜君たちはどう計測するか〜

同僚のふーがさんのセッション。byroot のセッションを聞いてから改めて考え直すと、2人は違う切り口で同じことを言っていると思った。問題解決のためには仮説検証サイクルを回すこと、事実を集めて問題を分解するということが重要である、と言っていると思う。

一緒に働く中でふーがさんは問題解決能力が高いと感じており、その思考を言語化してもらって垣間見ることができたなと感じた。また、ふーがさんのセッションもbyrootのセッションも両方聞くことで問題解決とはこういうことだよね、という理解が3つの具体例から抽象化できたような気がした。問題を目の前にすると気が急いてしまいがちなのだけど、焦らずに一つずつ問題に取り組んでいきたいなあと思った。

イベント

STORES CAFE〜Kaigi on Rails 2023出張版〜

ノンアルコールで、お子さんと一緒に参加できるミートアップだった。何組かお子さん連れで参加されている方たちがいて、みんな楽しそうで盛り上がっていた。私もとても楽しんだ。会場の大きさに大して余裕がある人数でちょうど良かった。ノンアルコールでよくある一通りのドリンクと、STORESさんで扱っているクラフトコーラやスパイスが効いたシロップがあった。シロップを炭酸で割って飲むのがとても美味しかった。ノンアルのドリンクはどうしてもいつでも飲めるものが多くてスペシャル感が薄くなりがちなのを、こういったその場ならではのドリンクがあるといい体験したなぁと少し嬉しくなれてありがたい。

後半にogijunさんがネルドリップでコーヒーを淹れてくれる時間があり、猫廼舎ファンなので非常に嬉しかった。お昼にフリースペースで出張猫廼舎のペーパードリップコーヒーをいただいてはいたが、やはりネルドリップは柔らかさが違うなぁと思った。

After Party

立食で数百人規模で交流するのはRubyKaigi以来2回目だった。フルリモートワークであまり運動していない人間の体力のなさを感じた。後半疲れて隅っこのほうに座っていると、だんだん人が集まってきたのが面白かった。

話したことない人に話しかけるのは勇気がいるけど、話しかけないといつもの人たちとしか話さないんだよなぁと思った。しかしとっかかりがないと難しい。知り合いが知らない人と話していたらその輪に飛び込んでみるみたいなエイヤッと勇気が必要そう。

あとスピーカーTシャツは会期中毎日着ていいものだと思った。15分とか30分話を聞いただけでは顔を覚えられないので、話を聞いてみたいと思っても Attendee.all.select... では会場の中で探せない。スピーカーTシャツがあると Attendee.speaker から探せるのでできてとても助かる。

RubyMusicMixin on Rails 2023

DJに興味あるので全員のプレイに興味津々でほぼほぼ最前にいた。とはいえスペースがなくてステップ踏めるほどじゃなかったので揺れてるだけでそんなに疲れなかった。それぞれ30分だったけどあっという間だった。DJは集中力ずっと使って大変そうと思った

ラストのオブさんのプレイが印象的で、魅せ方がうまい〜。あとRubyMusicMixinのときも思ったけど緩急の付け方もうまいんだよなぁ、30分でテンションを上げたり落ち着かせたり、一瞬音を止めたりスクラッチで注目させたり観客側に振ってくれたりと様々な楽しませ方をしてくれる。あと不思議と全然疲れない。そういえば最初の曲で完全に止まっちゃうトラブルがあったけど、何事もなかったかのように再開してて凄かった。

今回のMixinは最前でもよく聞こえないくらい音が小さかったのはすこし残念だった。 盛り上がってくると人の声にDJの音量が負けてた気がした。

KaigiEffect

私にとっての Kaigi on Rails の KaigiEffect*1 は2つあった。

RDBMS が動く仕組みを知りたいと思った

Free Spaceでの雑談でRDBMSの性能で悩んでいることをいろいろな人に相談に乗ってもらい、あわせてRDBMSがどんな仕組みで動いているのか少し教えてもらった。ワクワクしたし、自分はRDBMSについて何も知らないなぁと思った。昔に知ったメインフレームで動くDBの知識が中途半端に残っているので、令和最新版にしたいというのもある。

RDBMSは賢く強く信頼できるソフトウェアだと思っていて、そんな子がどうやって動いているのか知りたいんだよなぁ。仲良くしていきたい。

私の知りたいことに合いそうなおすすめの本を3冊教えてもらったのでまずはこちらから読んでいこうと思う。

ogijunさんからカップ&ソーサーを購入した

大江戸Ruby会議10でogijunさんが「カップによってコーヒーの味は変わる」と言っていたのを聞いて、飲み口が薄かったり香りの立ち具合が良いコーヒーカップがほしいなと思っていた。うちにはマグカップはたくさんあるけどちゃんとしたコーヒーカップはなかった。

そうしたら、STORES CAFEでogijunさんがお店で使っていたカップの隠居先を探していると聞いて、購入することにした。なにせその場でogijunさんが淹れてくれたコーヒーでカップを試すことができる。手に持った具合や、佇まい、口当たり、何ccくらい入るか、とかとかすべて(しかもogijunさんが淹れたコーヒーで)実践で試して買うことができるのだ。こんなことができる機会が他にあるだろうか。いや、ない。

というわけでこのカップとソーサーにはうちで余生を過ごしてもらうことにした。早速使っているのだが、机の上に素敵なカップとソーサーがあるというのは思った以上に精神によい。特にソーサーがあることがこれほどいいとは思っていなかった。

これからも大事に使っていきたい。

有田焼のコーヒーカップとソーサー

IRBとRelineのHEADを使いつつ現在のブランチ名とcommit hashを表示する

IRBとRelineはHEADで使いたいので、特定ディレクトリのものを使用して実行している。

ASDF_RUBY_VERSION=3.3.0-dev ruby -I /Users/mi/ghq/github.com/ruby/reline/lib -I /Users/mi/ghq/github.com/ruby/irb/lib /Users/mi/ghq/github.com/ruby/irb/exe/irb`

これだけだとレビューするときに「今どのブランチで実行してるんだっけ?」と思うことがあるので、ブランチ名とcommit hashも表示するようにした。

ブランチ名は git rev-parse --abbrev-ref HEAD で、commit hashは git show --format='%h' --no-patch で表示できる。

function irbm() {
  echo "IRB    branch: $(cd /Users/mi/ghq/github.com/ruby/irb && git rev-parse --abbrev-ref HEAD), HEAD: $(cd /Users/mi/ghq/github.com/ruby/irb && git show --format='%h' --no-patch)"
  echo Reline branch: $(cd /Users/mi/ghq/github.com/ruby/reline && git rev-parse --abbrev-ref HEAD), HEAD: $(cd /Users/mi/ghq/github.com/ruby/reline && git show --format='%h' --no-patch)
  ASDF_RUBY_VERSION=3.3.0-dev ruby -I /Users/mi/ghq/github.com/ruby/reline/lib -I /Users/mi/ghq/github.com/ruby/irb/lib /Users/mi/ghq/github.com/ruby/irb/exe/irb
}

alias irbm='irbm'

実行するとこのように表示される。

❯ \irbm
IRB    branch: master, HEAD: c2e7002
Reline branch: master, HEAD: ffe81c8
irb(main):001:0>

RubyKaigi 2023で "UTF-8 is coming to mruby/c" というタイトルで話しました

スライドタイトルは「サンタが街にやってくる」つまり「Santa Claus Is Coming to Town」のもじりでした。

UTF-8がルンルンでmruby/cにやってくる様子を思い浮かべながら決めました。

スライド

きっかけ

発表内でも触れましたが、はすみさんにRubyWorldConference2022でmruby/cのUTF-8対応をしませんかと誘われたのがきっかけです。

文字コード好きなひとが来場する情報を事前にTwitterでキャッチしていたので、PicoRubyのUTF-8対応という釣り糸を垂らしたら、うまいこと引っかかりました。 質問タイムのときにちょうどその人が質問してくれて、「ちなみにUTF-8に興味ありません?」と聞いたら「めっちゃあります」とのことで、「じゃあ後ほど打ち合わせしましょう」と公衆の面前で言質をとった次第です。   mruby/cのUTF-8対応は進めてよい、とすでに開発者会議で決まっています(PicoRubyコンパイラ側は私の一存でなんでもできる)から、あとはやるだけです。

shimane.monstar-lab.com

言質をとられるシーンがYouTubeに残っています。

youtu.be

2022年にUTF-8を0から実装できる、しかも人々に使われる言語で…というのはとても魅力的で、ワクワクしました。

この時点ではmrubyとmruby/cの違いもわかっていませんでしたが、はすみさんに質問できるなら実装できないことはないだろうと思っていました。

プロポーザル

2022年末ごろに私はIRBとRelineのメンテナになりました。そうすると不思議なことにRubyKaigiへの焦がれるような執着がスッと消えました。RubyKaigiへのモチベーションがなくなったわけではないけれど、絶対にプロポーザルを出さなければ…という自分の中のプレッシャーからは解放されました。

また、前回のRubyKaigiからあまり日がなかったこともありプロポーザルを出すかどうかは直前まで悩んでいました。メンテナ活動も始めていて、プロポーザルとして出せるような大玉を持っていなかったというのもあります。mruby/cのUTF-8対応も未着手でした。今年は出さなくてもいいかな、と思っていました。Asakusa.rbの新年会までは。

1月24日にAsakusa.rbの新年会があり、そこでIRBの話をたくさんしておいしい羊をたくさん食べてとても楽しい時間を過ごせました。翌日、RubyKaigiのプロポーザルを出そうというやる気が湧いてきました。IRB, Relineで話せるようなネタはないのでmruby/cのUTF-8対応ができそうか下調べを開始していけそうだったのでプロポーザルにまとめてSubmitしました。その時点での実装は0で去年に引き続きまた見切り発車ですが、UTF-8のことは調べれば分かるのとmrubyが参考になりそうなことは知っていたのでまあ形にはなるだろうとの見込みで行きました。

その後しばらく実装を進めておらず、3月にプロポーザル通過の連絡が来て実装をはじめました。今思えば2月にもう少し作業しておけばよかったです。

実装

ただしく実装できた部分は発表の中で話したので、ここでは発表で話さなかった部分を書きます。

Stringの各メソッドでUTF-8に対応させるという方針は決めていたので粛々と実装とテストを書いていました。C言語とmruby/cについては素人なので、ChatGPTにいろいろ質問しながら進めました。ポインタ演算やポインタをprintfする方法など基本的なことを質問したり、関数をまるごと渡して要約してもらったりしました。ChatGPTにはとても助けられました。ChatGPT 4のサポートをしてくれた所属先の永和システムマネジメントに感謝しています。

ほかにはmemcpy, memmoveをすることでどうバイト列を操作するか分からなくて手書きで方眼紙にバイト列とアドレスを書いてどうやってバイト列が移動するのか理解したりしていました。ビット演算も不慣れで、16進数と2進数の変換を脳内で行う練習をしたりしました。こういうのは実際に手を動かすことで理解が深まると思います。

いろいろ困ったこともおきました。\0 を文字列終端の判定にしていたら、Ruby側から途中で \0 を含む文字列が渡されたときに途中までしか見なくなってしまうとか。こう書くと当たり前ですが、Cに不慣れでよくわかっていませんでした。

        s1 = "ABC\x00\x0d\x0e\x0f"
        assert_equal 7, s1.size # => 3

String#inspectの修正には少し悩まされました。mruby/cのテスティングフレームワーク自身がmruby/cのinspectを使っているため、expectedとactualで全く同じ結果が出力されていますがこれはテストに失敗しています。コード読んで直しました。

    1) StringTest#string_inspect_case (:assert_equal)
      description : String#inspect
      expected    : ""\xE3\x81\x82\xE3\x81\x84\xE3\x81\x86"" [String]
      actual      : ""\xE3\x81\x82\xE3\x81\x84\xE3\x81\x86"" [String]
      # /work/mrubyc/test/string_test.rb:951

あとはmruby/cのStringのテストがいろいろ不足していたため、テストを追加するPRをいくつか出しました。mrubyc contoributors 4位になりました (12 commits) https://github.com/mrubyc/mrubyc/graphs/contributors

実装過程は気づいたことや思ったことのメモを取っていました。中途半端なところで中断しても「次はここからやるんだな」ということがひと目で分かって便利でした。また、たまに見返すことで自分がやってきたことを振り返ることができました。この記事を書くのにもかなり役立っています。

RubyKaigiの準備が前日になっても全然終わっていない悪夢を3回くらい見ました。LTとKeebKaigiにはプロポーザルを出さないことを決めました。

発表

人がたくさんいてかなり緊張しました。OpenStudioはお立ち台と1列目が近く、1列目に見知った顔を何人か見かけました。同僚のふーがさんと目があって、声をかけてもらえて少し緊張がほぐれました。

発表は28分で時間的にはちょうど良かったと思います。話し終わった後に「楽しそうに話していてよかった」とフィードバックをもらえてよかったです。文字コードの面白さ、結局すべてはバイト列であるということが少しでも伝わったら幸いです。

ふりかえり

しかしスライド作成がギリギリになったこと、実装が完了できなかったことは残念でした。みなさんにお届けできる状態で発表したいです。また練習不足も感じました。去年よりは早めに手を付けられたものの、やはり実装完了している状態でプロポーザル出すのがスケジュール的にはよいなと感じました。またスライドの英語の説明、図表の少なさ、情報密度などに課題を感じています。特にRubyKaigiは「わからないことによるワクワク感」があっていいカンファレンスだと感じます。もっと情報密度を高めて、わからなくても楽しいと感じるような発表をしたいと感じました。

今後やりたいこと

  • UTF-8対応の残りの実装
  • Unicode Standardを読む
  • mruby/cを実機にデプロイ
  • mruby/cのテスティングフレームワークでassertionが落ちた行が分からないのを修正

IRBとRelineのバージョンを変更してIRBを起動するスクリプトを書いた

IRBのバージョンは簡単に変更できるけど、Relineのバージョン変えてIRB起動するのが面倒だったのでスクリプトを書いてみた。 手元でしか使わないのでARGVで文字列渡すだけの簡素な作り。

bundler/inline は便利だなぁ。

コードにもコメントしてあるけど、ARGV.clear しないとIRBの lib/irb/magic-file.rb で ARGV[0]File.open しようとして落ちるので ARGV.clear している。

使用例

ruby irb_reline_versions_changer.rb 1.4.1 0.3.0
#!/usr/bin/env ruby

require 'bundler/inline'

IRB_VERSION = ARGV[0]
RELINE_VERSION = ARGV[1]

# NOTE: IRBのMagicFileでARGVをファイルとしてOpenしようとして落ちるためARGVを削除する
ARGV.clear

gemfile do
  source 'https://rubygems.org'
  gem 'irb', IRB_VERSION
  gem 'reline', RELINE_VERSION
end

require 'irb'
require 'reline'

puts "irb: #{IRB::VERSION}"
puts "reline: #{Reline::VERSION}"

IRB.start(__FILE__)

福岡Rubyist会議03に参加した

福岡Rubyist会議03

regional.rubykaigi.org

キーノートスピーカーの2名が公開されたときに、これは絶対に行きたい!!と思って参加を決めた。参加してとても良かった。

sorahさんの発表はRubyKaigiがどんなものを使って、どんなスケジュール感で作られているのかが分かり面白かった。自宅ISPとは…? コンパネがRails consoleだったとか生々しい裏話が聞けて面白かった。あと話の節々からsorahさんのカバー範囲の広さが伺えて刺激を受けた。

YouTube眺めてるときにRubyistの話がもっと聞ければいいのにな〜と以前から思っておりこれを機に配信するRubyistが増えてくれないだろうかと思った。ピンマイク欲しくなった。普段の打ち合わせとか、オンラインの登壇で音質よくしたい気持ちが高まった。

iPadのカメラを使って配信できるとは思ってもいなかったので新しい視点だった。iPadだと気軽だし対応アプリも多そうだし良さそう。

Rubyのリリース大変そうというのが分かって良かった。デプロイボタンを押せばポンとリリースされるものではなく、何人かが数時間かけて対応していく大変な作業だった...いつもありがとうございます。

私がESP32にmruby/cを入れようとしてハマったところがなぜハマったのか分かって勉強になった。project.mkがないと言われていたがESP32側がmake非対応になっていたらしい。

発表後にyuuuさんに「私はマイコンに興味があるが、何から勉強したらいいか分からない。どんなレイヤに何があるのかがちんぷんかんぷんで、基礎知識を知りたい。組み込みの基礎知識を得るにはどうすればいいと思うか?」と聞いたところ「エンベデッドシステムスペシャリスト試験の教科書がよくまとまってる」と教えてもらい、とても参考になった。ネットで検索しても電子工作の基礎情報は出てくるもののマイコンの世界についてはなかなか見つけられなかったので聞けて良かった。

るびまはznzさんの発表をきっかけに本当にみんなが動き出している。すごいことだと思う。みんな実は内なる思いがあって、それがznzさんの話が起爆剤になって動き出したように見える。動き出したものはじゃんじゃん前に進んでいて、みんなすごいなーと思う。

るびまに必要だったのは「るびまがまた発行されてほしい」という気持ちを持っている人がたくさんいることをお互いが気づくことだったのかもしれない

Ruby M17N の設計と実装」はRubyの多言語対応がどのようになされたか、概念からAPIまで一気通貫できる最高のドキュメントなのでおすすめです。

tompngさんの発表はとにかく楽しいし理解が及ばないしで、とても楽しかった。トークの構成でも技術的な内容でも素晴らしいキーノートだったと思う。これを現地で聞けて良かった。

話の内容は高度で角谷さんがツイートしていたとおり「ふくろうの描き方」のように感じた。しかし描いたふくろうを手直しできるようにするための工夫を行っているとか、描く本人も完成するか分からないと思いながら気合で作り上げるとかそんな泥臭い話を聞けて、あまりに摩訶不思議で魔法のように見えていたTRICKコードが同じ人間の手によるものなのだと感じた。職人技だ〜

クロージング

恩送りをしよう、アウトプットを世界に届けよう。

登壇者のみなさん、スタッフのみなさん、最高の会を開いてくださりありがとうございました!

福岡観光とか

  • 鯖のさしみが美味しかった
  • 資さんうどん、めちゃめちゃ良かった。たっぷりのごぼ天に甘く味付けされた牛肉…甘い味付けよ…!!地元の味を思い出すかのような少し甘めの味がしんみり来たし美味しくて、地下鉄+歩きで行くにはちょっと遠かったけど食べられて良かった。また福岡に行ったらうどん食べたいなぁ。
  • 会場の八女茶がホットもアイスもとても美味しかった。茶葉買って帰れば良かった。
  • 翌日に行った大濠公園がとても心落ち着く場所だった。地下鉄からもアクセスがよかった。凪いだ池と飛び交う鳥たち、散歩する犬に心が和んだ。
  • 茶店にあまり行けなかったので、今度福岡に行くことがあればいろいろな喫茶店に行きたい。

IRB会議

緊急IRB会議がお昼の寿司の部・夜のうどんの部の2回開催された。今のIRB/Relineをとりまく状況とか、困っていること、今後の方針など話せてとても良かった。やはりリアルタイムで話すのは早くて帯域が広くていいな。自分じゃ権限がなくてできなかったことがその場でシュッと依頼できていろいろ前に進んだりもした。物理的な距離があり、なかなか集まれないメンバーなのでいい機会だった。

寿司の部ではチームとか方針の話を主にして、うどんの部ではコードに踏み込んだ話をがっつりできた。PRの解説を本人に図付きで解説してもらうのとても分かりやすくてありがたい。

その他 \1\2 の謎とか、メソッドチェーンの補完が重すぎるとか、Reline::Terminfoの話とか、JRuby分からないとか、readlineどうしようねみたいな話とかいろいろ。 Relineコードリーディング部やりたい。

あと、うどんの部でmrubyのコードの読み方がわからなかったところを聞けて詰まっていたところの解消ができてよかった。

分からなかったのはここ。

extern const char mrb_utf8len_table[];
const char mrb_utf8len_table[] = {
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 3, 3, 4, 0
};

mrb_int
mrb_utf8len(const char* p, const char* e)
{
  mrb_int len = mrb_utf8len_table[(unsigned char)p[0] >> 3];

github.com

UTF-8の1文字のバイト長を取得する部分で、mrb_utf8len_table がバイト長を返していそうなのは分かるがなんでこれでいいのか分からず詰まっていた。そのことを質問したところ、UTF-8の文字の1バイト目を3つ右シフトして5ビットにして、5ビットの値をindexにして mrb_utf8len_table に渡しているんじゃないかと教えてもらった。

AND演算すればいいのでは?とも聞いたところ、このほうが命令数が少なくなるからこうしているのではと教えてもらって自分にはない観点が得られた。CPUにやさしいコードだった。

コード見て話しながら、これは3つ右シフトしたら5ビットだから0~31でテーブルに32個あるんじゃないですかねえとかここでマッチングかけてるというのがシュッとでてくる人たち、ビット演算や2進数の扱いに慣れてて自分も精進せねばと思った。私は空中で計算ができないのでiPadに書いて認識があってるか他の人たちに確認した。