アペフチ

EPUB Parser v0.3.6リリース

EPUB Parserv0.3.6をリリースした。

v0.3.4v0.3.5で汚いコードがあったのだが、その部分がいつの間にかメソッドとして存在していた(Item#find_item_by_relative_iri)のに気が付いたので、それを使うようにした。ついでにそのメソッドにバグが見付かったので修正した。このメソッド、少なくともこのライブライー内ではどこでも使われていなかったんだけど、なんで実装したんだろう……。

あと、このgemに付いてくるepubinfoコマンドのドキュメントが不親切だったというか、追加されたオプションについて何も書いていなかったので追記した。人間用だけじゃなくて、YAMLやJSONフォーマットでも出力できます。昔は「みんなコマンドは-hオプション付きで一回くらい実行するよね?」という感じだった気がするなあ。

テスト中PrettyBacktraceを常に有効にしていたのも、デフォルト無効にして、必要な時だけ環境変数で有効にするようにした。これが有効だと体感で結構遅くなっちゃう程度にテストケースが多くなってきてるのと、たまにPrettyBacktraceのせいでSEGVするので(バグレポートはしてない。済みません、再現手順見付ける気力が……)。

実装されているはずのメソッドが呼べなくてハマった

Rust勉強中です。

勉強中にありがちな、「分かってみればもう間違えないけど、最初は何が問題なのか全然分からない」というタイプのハマり方をしたので記録として書きます。

EPUBファイルの中身を調べようと思って、zipクレート(ライブラリー)を使った次のようなコードを書いていました(EPUBファイルは拡張子を変えたZIPアーカイブなのです)。

extern crate zip;

use std::fs;

fn main() {
    let path = std::env::args().nth(1).unwrap();
    let file = fs::File::open(&path).unwrap();

    let mut archive = zip::ZipArchive::new(file).unwrap();

    for i in 0..archive.len() {
        let mut f = archive.by_index(i).unwrap();
        let name = f.name().to_string();
        println!("{}", name);
    }

    let f = archive.by_name("META-INF/container.xml").unwrap();
    println!("{:?}", f.bytes().next().unwrap());
}

で、実行してみると、ファイル一覧は表示できる(println!("{}", name))のだけど、ファイルの中身を読み取る(f.bytes().next().unwrap())ところでエラー。

% cargo run api-design.epub
   Compiling handle-epub v0.1.0 (file:///Users/ikeda/src/gitlab.com/KitaitiMakoto/learning-rust/handle-epub)
error[E0599]: no method named `bytes` found for type `zip::read::ZipFile<'_>` in the current scope
  --> src/main.rs:18:24
   |
18 |     println!("{:?}", f.bytes().next().unwrap());
   |                        ^^^^^
   |
   = help: items from traits can only be used if the trait is in scope
help: the following trait is implemented but not in scope, perhaps add a `use` for it:
   |
3  | use std::io::Read;
   |

error: aborting due to previous error

error: Could not compile `handle-epub`.

zip::read::ZipFile<'_>bytesメソッドが無いと言われて、そんなばかなと思いつつzip::read::ZipFile構造体のAPIリファレンスを見ると

impl<'a> Read for ZipFile<'a>

fn bytes(self) -> Bytes<Self>
Transforms this Read instance to an [Iterator] over its bytes. Read more

やっぱりある。

ZipFileはちゃんとReadトレイトを実装しているのになーなんでだろうなー」と一日くらい悩んだのだけど、解決は一瞬でした。この悩み方に既にヒントが現れていて、悩んでいるうちに『プログラミング言語Rust』の次の文を思い出したのです。

第1に、あなたのスコープ内で定義されていないトレイトは適用されません。例えば、標準ライブラリは File にI/O機能を追加するための Write トレイトを提供しています。デフォルトでは、 FileWrite で定義されるメソッド群を持っていません。
(略)
始めに Write トレイトを use する必要があります。

(「トレイト」より)

というわけで答えは簡単、

use std::io::Read;

の一行を足すことで、あっさりとコンパイルが通ってコードも実行できたのでした。

% cargo run api-design.epub
   Compiling handle-epub v0.1.0 (file:///Users/ikeda/src/gitlab.com/KitaitiMakoto/learning-rust/handle-epub)
    Finished dev [unoptimized + debuginfo] target(s) in 0.90 secs
     Running `target/debug/handle-epub api-design.epub`
mimetype
META-INF/
META-INF/com.apple.ibooks.display-options.xml
META-INF/container.xml
OEBPS/
OEBPS/content.opf
OEBPS/images/
OEBPS/images/backslash.jpg
OEBPS/images/cover.jpg
OEBPS/images/p-001-000fig.jpg
OEBPS/images/p-001-001-1fig.jpg
OEBPS/images/p-001-001-2fig.jpg
...
OEBPS/text/p-005-003.xhtml
OEBPS/text/p-005-004.xhtml
OEBPS/text/p-005-005.xhtml
OEBPS/text/p-005-006.xhtml
OEBPS/text/p-006-001.xhtml
OEBPS/text/p-007-001.xhtml
OEBPS/text/p-008-001.xhtml
OEBPS/text/p-008-002.xhtml
Ok(60)

「ぐっとがんばる」話。

結城メルマガの『「ぐっとがんばる」話。』がよかった。

ある日、Evernoteのノート整理をしていました。 いいアイディアや書籍の案はいろいろあるんだけど、 断片ばかりではだめですね。 どこかで「ぐっとがんばる」ことをしないと、 断片をいくら集めてもまとまりません。

Scrapboxを使い始めて、ちょっとしたことをどんどんメモしていって、リンクが繋がる気持ちよさに悦に入ったりしているのだけど、やっぱりそれだけでは何にもならない。メモしたから安心、と、脳を解放して次のこと(やってた仕事に戻るとか、ツイッターアプリ開くとか、最近だとツイッターよりMastodon)に行ってしまうのではなく、そこでぐっとこらえて、メモを眺め直して、スマホから離れて、考えてみる。すると、ただの思い付きよりも先に進むことができる。

というのを実感した最近だったから、結城さんのこの話が刺さった。

この、「誰か他人(著名人)が自分が感じたのと同じことを言っている」ということの嬉しさは何だろうな。自分が肯定されたように感じる、というのもあるだろうけど、「考えを進めるための足場が出来た」という気持ちよさが大きい気がする。

余談だけど、Scrapboxに音声入力でメモを取った時が、考えが進みやすい気がする。体を使ったほうがいいということか。とは言え会話がいいのかというとそう簡単でもない。大体、会話しているようなスピードで僕は物を考えられないし、会話しながらだとそっちにエネルギーが奪われてしまう。一人がやっぱりいい。