Rust の練習帳のメモ
cargo new hello
すると以下が作成される。
tree .
.
├── Cargo.toml
└── src
└── main.rs
main.rs
の中身は以下の通り。
fn main() {
println!("Hello, world!");
}
cargo run
すると以下のようになる。
実行ファイルは /target/debug/hello
に置かれる。
tree .
.
├── Cargo.lock
├── Cargo.toml
├── src
│ └── main.rs
└── target
├── CACHEDIR.TAG
└── debug
├── build
├── deps
│ ├── hello-c9774b34a6e1eca3
│ ├── hello-c9774b34a6e1eca3.2r5t8a6x6ysod9l3.rcgu.o
│ ├── hello-c9774b34a6e1eca3.3bs9ikjyeoj6vqal.rcgu.o
│ ├── hello-c9774b34a6e1eca3.3gxre9yf6hbggtv2.rcgu.o
│ ├── hello-c9774b34a6e1eca3.4j5iatayyh4dpk5e.rcgu.o
│ ├── hello-c9774b34a6e1eca3.d
│ ├── hello-c9774b34a6e1eca3.dyjs2r1dyhl4sh9.rcgu.o
│ └── hello-c9774b34a6e1eca3.f2gl77r8focf7oj.rcgu.o
├── examples
├── hello
├── hello.d
└── incremental
└── hello-3k89lm8602rdv
├── s-gslj1pn8al-hx8uw1-6yezk5dj6mc3k2aoleinaxeir
│ ├── 2r5t8a6x6ysod9l3.o
│ ├── 3bs9ikjyeoj6vqal.o
│ ├── 3gxre9yf6hbggtv2.o
│ ├── 4j5iatayyh4dpk5e.o
│ ├── dep-graph.bin
│ ├── dyjs2r1dyhl4sh9.o
│ ├── f2gl77r8focf7oj.o
│ ├── query-cache.bin
│ └── work-products.bin
└── s-gslj1pn8al-hx8uw1.lock
ファイル名は main.rs
だけど、実行ファイルは hello
になる。
実行ファイル名は Cargo.toml
の package.name
で指定する。
- name = "hello"
+ name = "koyasaseki"
として cargo clean && cargo run
すると以下のようになる。
実行ファイル名が変わる。
tree .
.
├── Cargo.lock
├── Cargo.toml
├── src
│ └── main.rs
└── target
├── CACHEDIR.TAG
└── debug
├── build
├── deps
│ ├── koyasaeki-0d153506e3c40c03
│ ├── koyasaeki-0d153506e3c40c03.2ubaiqv6x72hbhdm.rcgu.o
│ ├── koyasaeki-0d153506e3c40c03.4jubn5l5cpoc9wuy.rcgu.o
│ ├── koyasaeki-0d153506e3c40c03.4k4tzs27wyglqtys.rcgu.o
│ ├── koyasaeki-0d153506e3c40c03.4rzewetuhiwgie41.rcgu.o
│ ├── koyasaeki-0d153506e3c40c03.4x89ou07wvwgdpx2.rcgu.o
│ ├── koyasaeki-0d153506e3c40c03.d
│ └── koyasaeki-0d153506e3c40c03.ut0tsegnln9z2ry.rcgu.o
├── examples
├── incremental
│ └── koyasaeki-2583y3hi30ttr
│ ├── s-gslj8kpacj-18lkeen-7u8mf2r39wbxpuo9zcjypxvmx
│ │ ├── 2ubaiqv6x72hbhdm.o
│ │ ├── 4jubn5l5cpoc9wuy.o
│ │ ├── 4k4tzs27wyglqtys.o
│ │ ├── 4rzewetuhiwgie41.o
│ │ ├── 4x89ou07wvwgdpx2.o
│ │ ├── dep-graph.bin
│ │ ├── query-cache.bin
│ │ ├── ut0tsegnln9z2ry.o
│ │ └── work-products.bin
│ └── s-gslj8kpacj-18lkeen.lock
├── koyasaeki
└── koyasaeki.d
ところで cargo clean
したときに
Removed 27 files, 917.3KiB total
と表示される。 tree
コマンドでも出力されるファイルが多い。
これらはなんだろう。
依存関係の解決が deps
、再コンパイルを効率的に行うためのものが incremental
みたい。
どちらもコンパイル速度改善のためにあるみたい。
容量が大きくなってきたら clean
しても問題ない。
もちろん git
の管理対象外にする類のもの。
std::process::Command
でコマンドを使える。
例えば以下のようにすると、 ls
コマンドを実行できる。
use std::process::Command;
fn main() {
let mut ls = Command::new("ls");
println!("{:#?}", ls.output().unwrap());
}
Output {
status: ExitStatus(
unix_wait_status(
0,
),
),
stdout: "Cargo.lock\nCargo.toml\nsrc\ntarget\ntests\n",
stderr: "",
}
stdout
を見ると ls
が実行できてることがわかる。
2 章のメモ
echo
コマンドを書くのが目標。
man echo
で echo
の使い方を確認する。
ECHO(1) General Commands Manual ECHO(1)
NAME
echo – write arguments to the standard output
SYNOPSIS
echo [-n] [string ...]
DESCRIPTION
The echo utility writes any specified operands, separated by single blank (‘ ’) characters and followed by a newline (‘\n’) character, to the standard output.
The following option is available:
-n Do not print the trailing newline character. This may also be achieved by appending ‘\c’ to the end of the string, as is done by iBCS2 compatible
systems. Note that this option as well as the effect of ‘\c’ are implementation-defined in IEEE Std 1003.1-2001 (“POSIX.1”) as amended by Cor. 1-2002.
Applications aiming for maximum portability are strongly encouraged to use printf(1) to suppress the newline character.
Some shells may provide a builtin echo command which is similar or identical to this utility. Most notably, the builtin echo in sh(1) does not accept the -n
option. Consult the builtin(1) manual page.
EXIT STATUS
The echo utility exits 0 on success, and >0 if an error occurs.
SEE ALSO
builtin(1), csh(1), printf(1), sh(1)
STANDARDS
The echo utility conforms to IEEE Std 1003.1-2001 (“POSIX.1”) as amended by Cor. 1-2002.
macOS 14.2 April 12, 2003 macOS 14.2
-
echo
は引数を標準出力に書き込む。 - オプションは
-n
だけ。-
-n
は最後に改行文字を印字しないためのオプション。
-
いろいろ書いてあるけどだいたいわかるからちゃんと読まなくてもよし。
cargo new echor
でプロジェクトを作る。
println!("{:?}", std::env::args());
でコマンドライン引数の受け取り方を見る。
fn main() {
println!("{:?}", std::env::args());
}
cargo run
...
Args { inner: ["target/debug/echor"] }
実行ファイルのパス target/debug/echor
が入っている。
引数に Hello
と Rust
を渡してみる。
Args { inner: ["target/debug/echor", "Hello", "Rust"] }
となるはず。
cargo run
...
Args { inner: ["target/debug/echor", "Hello", "Rust"] }
OK。あってそう。
つまり、 std::env::args()
の返す構造体 Args
は inner
に引数を持っている。
ただし、1つ目は実行ファイルのパスになる。
素のコマンドライン引数を扱うのは(おそらく)大変なのでクレート clap を使う。
本の clap
はバージョンが 2.33
で、
現在の最新バージョンが 4.4.18
なのでそれなりに読み替えは必要そう。
Cargo.toml
に clap
を追加する。
cargo add clap
これで Cargo.toml
が以下のようになる。
[package]
name = "echor"
version = "0.1.0"
edition = "2021"
[dependencies]
clap = "4.4.18"
VSCode (僕は VSCode を使っている)の LS が警告を出力する。
cargo build
すると clap
がダウンロードされて警告が消える。
clap
を使うことで --help
オプションが勝手に定義されるらしい。
以下のように書いて cargo run -- --help
してみる。
use clap::Command;
fn main() {
let _matches = Command::new("echor")
.version("0.1.0")
.author("Koya Saeki <koyasaeki@gmail.com>")
.about("Rust echo")
.get_matches();
}
本だと clap::App
だが、 その辺はバージョンがかなり違うから調べつつって感じかね。
動かすと以下の出力になる。
cargo run -- --help
Rust echo
Usage: echor
Options:
-h, --help Print help
-V, --version Print version
バージョン表記もしてくれるみたいなのでやってみる。
cargo run -- -V
...
echor 0.1.0
今度は
cargo run -- foo
としたときに foo
を適当な構造体で保持したい。
本に従いつつ、最新のバージョンに合わせるとこうなる。
-n
フラグの取得もやってるのでそれも真似する。
cargo run -- -n foo
...
ArgMatches {
valid_args: [
"text",
"omit_newline",
"help",
"version",
],
valid_subcommands: [],
args: FlatMap {
keys: [
"omit_newline",
"text",
],
values: [
MatchedArg {
source: Some(
CommandLine,
),
indices: [
1,
],
type_id: Some(
bool,
),
vals: [
[
AnyValue {
inner: bool,
},
],
],
raw_vals: [
[
"true",
],
],
ignore_case: false,
},
MatchedArg {
source: Some(
CommandLine,
),
indices: [
2,
],
type_id: Some(
alloc::string::String,
),
vals: [
[
AnyValue {
inner: alloc::string::String,
},
],
],
raw_vals: [
[
"foo",
],
],
ignore_case: false,
},
],
},
subcommand: None,
}
cargo run -- foo
...
ArgMatches {
valid_args: [
"text",
"omit_newline",
"help",
"version",
],
valid_subcommands: [],
args: FlatMap {
keys: [
"text",
"omit_newline",
],
values: [
MatchedArg {
source: Some(
CommandLine,
),
indices: [
1,
],
type_id: Some(
alloc::string::String,
),
vals: [
[
AnyValue {
inner: alloc::string::String,
},
],
],
raw_vals: [
[
"foo",
],
],
ignore_case: false,
},
MatchedArg {
source: Some(
DefaultValue,
),
indices: [
2,
],
type_id: Some(
bool,
),
vals: [
[
AnyValue {
inner: bool,
},
],
],
raw_vals: [
[
"false",
],
],
ignore_case: false,
},
],
},
subcommand: None,
}
-n
の有無で構造体に入る値が違うのがわかる。
うまくいっているよう。よかった。
バージョン違いについては ↓ の変更ログを見ながら変えた。
また、 引数に required
オプションをつけたので、 cargo run
だけで動かすとエラーになる。
cargo run
Finished dev [unoptimized + debuginfo] target(s) in 0.00s
Running `target/debug/echor`
error: the following required arguments were not provided:
<TEXT>...
Usage: echor <TEXT>...
For more information, try '--help'.
直前のコマンドの終了コードを見る。
echo $?
2
cargo run -- foo && echo $?
とすると最後は
優れたコマンドラインプログラムでは、通常の出力を標準出力に、エラーメッセージを標準エラーに出力します。
コマンドラインプログラム書かないのでこういう当たり前っぽいことを書いてくれるの助かる。
text
の値と omit_newline
の値を取得したい。
clap
の API がかなり変わっているのでドキュメントをみつつ進めて最終的にこうなった。
use clap::{value_parser, Arg, Command};
fn main() {
let matches = Command::new("echor")
.version("0.1.0")
.author("Koya Saeki <koyasaeki@gmail.com>")
.about("Rust echo")
.arg(
Arg::new("text")
.value_name("TEXT")
.help("Input text")
.required(true)
.num_args(1..)
.value_parser(value_parser!(String)),
)
.arg(
Arg::new("omit_newline")
.short('n')
.help("Do not output print newline")
.num_args(0),
)
.get_matches();
let text: Vec<&String> = matches.get_many::<String>("text").unwrap().collect();
let omit_newline = matches.get_flag("omit_newline");
println!("{:#?}", text);
println!("{:#?}", omit_newline);
}
cargo run -- -n foo bar
...
[
"foo",
"bar",
]
true
cargo run -- foo bar
...
[
"foo",
"bar",
]
false
フラグを見て改行入れるかをみる。
let text: Vec<String> = matches
.get_many::<String>("text")
.unwrap()
.map(|x| x.to_string())
.collect();
let omit_newline = matches.get_flag("omit_newline");
print!("{}{}", text.join(" "), if omit_newline { "" } else { "\n" });
こうすれば良い。
text
を Vec<String>
にしたのは、 Vec<&String>
だと join
が使えなかったため。
テストは本の通りに書けば通る。
- ハマった点
-
02_echor
のmk-outs.sh
を実行してテストファイルを作成する。 - このときに
sh mk-outs.sh
として実行したため、shell
で実行してしまい、echo
の結果が違うことに... -
./mk-outs.sh
とするか、シェバンみてbash mk-outs.sh
とする。
-
この時点での学習用リポジトリ
3 章のメモ
cat
コマンドを実装するのが目標
cat
は、複数のファイルを 1 つのファイルに連結(concatenate)するので、この名前が付けられました。
そうだったんだ。ファイルの中身を標準出力するのにしか使ってなかった。
cat a.txt
Hello
cat b.txt
World
cat a.txt b.txt > c.txt && cat c.txt
Hello
World
man cat
でマニュアルを見る。
長い英語は読みたくないので日本語マニュアルを読む。
オプションがいくつかある。行番号を表示したり、空行を表示しなかったり。
2 章と同じようにプロジェクトを作る。
cargo new catr
クレートも追加する。
cargo add --dev assert_cmd predicates rand
cargo add clap
catr
をテストするための以下の 03_catr/tests
から取得する。
この時点で cargo test
した結果を載せておく。
サマリ
failures:
all
all_b
all_n
bustle
bustle_b
bustle_n
bustle_stdin
bustle_stdin_b
bustle_stdin_n
empty
empty_b
empty_n
fox
fox_b
fox_n
skips_bad_file
spiders
spiders_b
spiders_n
usage
test result: FAILED. 0 passed; 20 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.19s
error: test failed, to rerun pass `--test cli`
当然すべて失敗している。
アウトプット
cargo test
Compiling memchr v2.7.1
Compiling regex-syntax v0.8.2
Compiling cfg-if v1.0.0
Compiling libc v0.2.152
Compiling predicates-core v1.0.6
Compiling ppv-lite86 v0.2.17
Compiling difflib v0.4.0
Compiling termtree v0.4.1
Compiling normalize-line-endings v0.3.0
Compiling doc-comment v0.3.3
Compiling num-traits v0.2.17
Compiling predicates-tree v1.0.9
Compiling getrandom v0.2.12
Compiling wait-timeout v0.2.0
Compiling rand_core v0.6.4
Compiling aho-corasick v1.1.2
Compiling rand_chacha v0.3.1
Compiling float-cmp v0.9.0
Compiling rand v0.8.5
Compiling regex-automata v0.4.5
Compiling regex v1.10.3
Compiling bstr v1.9.0
Compiling predicates v3.1.0
Compiling assert_cmd v2.0.13
Compiling catr v0.1.0 (/Users/koyasaeki/ghq/github.com/koyasaeki/rust-solutions/catr)
Finished test [unoptimized + debuginfo] target(s) in 2.21s
Running unittests src/main.rs (target/debug/deps/catr-0fb49176e21b3b8a)
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
Running tests/cli.rs (target/debug/deps/cli-40d76ff55a01c9fa)
running 20 tests
test empty_b ... FAILED
test bustle_b ... FAILED
test empty ... FAILED
test bustle_stdin_n ... FAILED
test bustle_n ... FAILED
test all ... FAILED
test bustle_stdin ... FAILED
test bustle ... FAILED
test all_n ... FAILED
test empty_n ... FAILED
test bustle_stdin_b ... FAILED
test all_b ... FAILED
test fox_b ... FAILED
test fox ... FAILED
test spiders ... FAILED
test spiders_n ... FAILED
test usage ... FAILED
test fox_n ... FAILED
test spiders_b ... FAILED
test skips_bad_file ... FAILED
failures:
---- empty_b stdout ----
thread 'empty_b' panicked at /rustc/82e1608dfa6e0b5569232559e3d385fea5a93112/library/core/src/ops/function.rs:250:5:
Unexpected stdout, failed diff original var
├── original:
├── diff:
│ --- orig
│ +++ var
│ @@ -0,0 +1 @@
│ +Hello, world!
└── var as str: Hello, world!
command=`"/Users/koyasaeki/ghq/github.com/koyasaeki/rust-solutions/catr/target/debug/catr" "-b" "tests/inputs/empty.txt"`
code=0
stdout="Hello, world!\n"
stderr=""
---- bustle_b stdout ----
thread 'bustle_b' panicked at /rustc/82e1608dfa6e0b5569232559e3d385fea5a93112/library/core/src/ops/function.rs:250:5:
Unexpected stdout, failed diff original var
├── original: 1 The bustle in a house
│ 2 The morning after death
│ 3 Is solemnest of industries
│ 4 Enacted upon earth,—
│
│ 5 The sweeping up the heart,
│ 6 And putting love away
│ 7 We shall not want to use again
│ 8 Until eternity.
├── diff:
│ --- orig
│ +++ var
│ @@ -1,9 +1 @@
│ - 1 The bustle in a house
│ - 2 The morning after death
│ - 3 Is solemnest of industries
│ - 4 Enacted upon earth,—
│ -
│ - 5 The sweeping up the heart,
│ - 6 And putting love away
│ - 7 We shall not want to use again
│ - 8 Until eternity.
│ +Hello, world!
└── var as str: Hello, world!
command=`"/Users/koyasaeki/ghq/github.com/koyasaeki/rust-solutions/catr/target/debug/catr" "-b" "tests/inputs/the-bustle.txt"`
code=0
stdout="Hello, world!\n"
stderr=""
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
---- empty stdout ----
thread 'empty' panicked at /rustc/82e1608dfa6e0b5569232559e3d385fea5a93112/library/core/src/ops/function.rs:250:5:
Unexpected stdout, failed diff original var
├── original:
├── diff:
│ --- orig
│ +++ var
│ @@ -0,0 +1 @@
│ +Hello, world!
└── var as str: Hello, world!
command=`"/Users/koyasaeki/ghq/github.com/koyasaeki/rust-solutions/catr/target/debug/catr" "tests/inputs/empty.txt"`
code=0
stdout="Hello, world!\n"
stderr=""
---- bustle_stdin_n stdout ----
thread 'bustle_stdin_n' panicked at /rustc/82e1608dfa6e0b5569232559e3d385fea5a93112/library/core/src/ops/function.rs:250:5:
Unexpected stdout, failed diff original var
├── original: 1 The bustle in a house
│ 2 The morning after death
│ 3 Is solemnest of industries
│ 4 Enacted upon earth,—
│ 5
│ 6 The sweeping up the heart,
│ 7 And putting love away
│ 8 We shall not want to use again
│ 9 Until eternity.
├── diff:
│ --- orig
│ +++ var
│ @@ -1,9 +1 @@
│ - 1 The bustle in a house
│ - 2 The morning after death
│ - 3 Is solemnest of industries
│ - 4 Enacted upon earth,—
│ - 5
│ - 6 The sweeping up the heart,
│ - 7 And putting love away
│ - 8 We shall not want to use again
│ - 9 Until eternity.
│ +Hello, world!
└── var as str: Hello, world!
command=`"/Users/koyasaeki/ghq/github.com/koyasaeki/rust-solutions/catr/target/debug/catr" "-n" "-"`
stdin=`
The bustle in a house
The morning after death
Is solemnest of industries
Enacted upon earth,—
The sweeping up the heart,
And putting love away
We shall not want to use again
Until eternity.
`
code=0
stdout="Hello, world!\n"
stderr=""
---- bustle_n stdout ----
thread 'bustle_n' panicked at /rustc/82e1608dfa6e0b5569232559e3d385fea5a93112/library/core/src/ops/function.rs:250:5:
Unexpected stdout, failed diff original var
├── original: 1 The bustle in a house
│ 2 The morning after death
│ 3 Is solemnest of industries
│ 4 Enacted upon earth,—
│ 5
│ 6 The sweeping up the heart,
│ 7 And putting love away
│ 8 We shall not want to use again
│ 9 Until eternity.
├── diff:
│ --- orig
│ +++ var
│ @@ -1,9 +1 @@
│ - 1 The bustle in a house
│ - 2 The morning after death
│ - 3 Is solemnest of industries
│ - 4 Enacted upon earth,—
│ - 5
│ - 6 The sweeping up the heart,
│ - 7 And putting love away
│ - 8 We shall not want to use again
│ - 9 Until eternity.
│ +Hello, world!
└── var as str: Hello, world!
command=`"/Users/koyasaeki/ghq/github.com/koyasaeki/rust-solutions/catr/target/debug/catr" "-n" "tests/inputs/the-bustle.txt"`
code=0
stdout="Hello, world!\n"
stderr=""
---- all stdout ----
thread 'all' panicked at /rustc/82e1608dfa6e0b5569232559e3d385fea5a93112/library/core/src/ops/function.rs:250:5:
Unexpected stdout, failed diff original var
├── original: The quick brown fox jumps over the lazy dog.
│ Don't worry, spiders,
│ I keep house
│ casually.
│ The bustle in a house
│ The morning after death
│ Is solemnest of industries
│ Enacted upon earth,—
│
│ The sweeping up the heart,
│ And putting love away
│ We shall not want to use again
│ Until eternity.
├── diff:
│ --- orig
│ +++ var
│ @@ -1,13 +1 @@
│ -The quick brown fox jumps over the lazy dog.
│ -Don't worry, spiders,
│ -I keep house
│ -casually.
│ -The bustle in a house
│ -The morning after death
│ -Is solemnest of industries
│ -Enacted upon earth,—
│ -
│ -The sweeping up the heart,
│ -And putting love away
│ -We shall not want to use again
│ -Until eternity.
│ +Hello, world!
└── var as str: Hello, world!
command=`"/Users/koyasaeki/ghq/github.com/koyasaeki/rust-solutions/catr/target/debug/catr" "tests/inputs/fox.txt" "tests/inputs/spiders.txt" "tests/inputs/the-bustle.txt"`
code=0
stdout="Hello, world!\n"
stderr=""
---- bustle_stdin stdout ----
thread 'bustle_stdin' panicked at /rustc/82e1608dfa6e0b5569232559e3d385fea5a93112/library/core/src/ops/function.rs:250:5:
Unexpected stdout, failed diff original var
├── original: The bustle in a house
│ The morning after death
│ Is solemnest of industries
│ Enacted upon earth,—
│
│ The sweeping up the heart,
│ And putting love away
│ We shall not want to use again
│ Until eternity.
├── diff:
│ --- orig
│ +++ var
│ @@ -1,9 +1 @@
│ -The bustle in a house
│ -The morning after death
│ -Is solemnest of industries
│ -Enacted upon earth,—
│ -
│ -The sweeping up the heart,
│ -And putting love away
│ -We shall not want to use again
│ -Until eternity.
│ +Hello, world!
└── var as str: Hello, world!
command=`"/Users/koyasaeki/ghq/github.com/koyasaeki/rust-solutions/catr/target/debug/catr" "-"`
stdin=
The bustle in a house
The morning after death
Is solemnest of industries
Enacted upon earth,—
The sweeping up the heart,
And putting love away
We shall not want to use again
Until eternity.
`
code=0
stdout="Hello, world!\n"
stderr=""
---- bustle stdout ----
thread 'bustle' panicked at /rustc/82e1608dfa6e0b5569232559e3d385fea5a93112/library/core/src/ops/function.rs:250:5:
Unexpected stdout, failed diff original var
├── original: The bustle in a house
│ The morning after death
│ Is solemnest of industries
│ Enacted upon earth,—
│
│ The sweeping up the heart,
│ And putting love away
│ We shall not want to use again
│ Until eternity.
├── diff:
│ --- orig
│ +++ var
│ @@ -1,9 +1 @@
│ -The bustle in a house
│ -The morning after death
│ -Is solemnest of industries
│ -Enacted upon earth,—
│ -
│ -The sweeping up the heart,
│ -And putting love away
│ -We shall not want to use again
│ -Until eternity.
│ +Hello, world!
└── var as str: Hello, world!
command=`"/Users/koyasaeki/ghq/github.com/koyasaeki/rust-solutions/catr/target/debug/catr" "tests/inputs/the-bustle.txt"`
code=0
stdout="Hello, world!\n"
stderr=""
---- all_n stdout ----
thread 'all_n' panicked at /rustc/82e1608dfa6e0b5569232559e3d385fea5a93112/library/core/src/ops/function.rs:250:5:
Unexpected stdout, failed diff original var
├── original: 1 The quick brown fox jumps over the lazy dog.
│ 1 Don't worry, spiders,
│ 2 I keep house
│ 3 casually.
│ 1 The bustle in a house
│ 2 The morning after death
│ 3 Is solemnest of industries
│ 4 Enacted upon earth,—
│ 5
│ 6 The sweeping up the heart,
│ 7 And putting love away
│ 8 We shall not want to use again
│ 9 Until eternity.
├── diff:
│ --- orig
│ +++ var
│ @@ -1,13 +1 @@
│ - 1 The quick brown fox jumps over the lazy dog.
│ - 1 Don't worry, spiders,
│ - 2 I keep house
│ - 3 casually.
│ - 1 The bustle in a house
│ - 2 The morning after death
│ - 3 Is solemnest of industries
│ - 4 Enacted upon earth,—
│ - 5
│ - 6 The sweeping up the heart,
│ - 7 And putting love away
│ - 8 We shall not want to use again
│ - 9 Until eternity.
│ +Hello, world!
└── var as str: Hello, world!
command=`"/Users/koyasaeki/ghq/github.com/koyasaeki/rust-solutions/catr/target/debug/catr" "tests/inputs/fox.txt" "tests/inputs/spiders.txt" "tests/inputs/the-bustle.txt" "-n"`
code=0
stdout="Hello, world!\n"
stderr=""
---- empty_n stdout ----
thread 'empty_n' panicked at /rustc/82e1608dfa6e0b5569232559e3d385fea5a93112/library/core/src/ops/function.rs:250:5:
Unexpected stdout, failed diff original var
├── original:
├── diff:
│ --- orig
│ +++ var
│ @@ -0,0 +1 @@
│ +Hello, world!
└── var as str: Hello, world!
command=`"/Users/koyasaeki/ghq/github.com/koyasaeki/rust-solutions/catr/target/debug/catr" "-n" "tests/inputs/empty.txt"`
code=0
stdout="Hello, world!\n"
stderr=""
---- bustle_stdin_b stdout ----
thread 'bustle_stdin_b' panicked at /rustc/82e1608dfa6e0b5569232559e3d385fea5a93112/library/core/src/ops/function.rs:250:5:
Unexpected stdout, failed diff original var
├── original: 1 The bustle in a house
│ 2 The morning after death
│ 3 Is solemnest of industries
│ 4 Enacted upon earth,—
│
│ 5 The sweeping up the heart,
│ 6 And putting love away
│ 7 We shall not want to use again
│ 8 Until eternity.
├── diff:
│ --- orig
│ +++ var
│ @@ -1,9 +1 @@
│ - 1 The bustle in a house
│ - 2 The morning after death
│ - 3 Is solemnest of industries
│ - 4 Enacted upon earth,—
│ -
│ - 5 The sweeping up the heart,
│ - 6 And putting love away
│ - 7 We shall not want to use again
│ - 8 Until eternity.
│ +Hello, world!
└── var as str: Hello, world!
command=`"/Users/koyasaeki/ghq/github.com/koyasaeki/rust-solutions/catr/target/debug/catr" "-b" "-"`
stdin=
The bustle in a house
The morning after death
Is solemnest of industries
Enacted upon earth,—
The sweeping up the heart,
And putting love away
We shall not want to use again
Until eternity.
`
code=0
stdout="Hello, world!\n"
stderr=""
---- all_b stdout ----
thread 'all_b' panicked at /rustc/82e1608dfa6e0b5569232559e3d385fea5a93112/library/core/src/ops/function.rs:250:5:
Unexpected stdout, failed diff original var
├── original: 1 The quick brown fox jumps over the lazy dog.
│ 1 Don't worry, spiders,
│ 2 I keep house
│ 3 casually.
│ 1 The bustle in a house
│ 2 The morning after death
│ 3 Is solemnest of industries
│ 4 Enacted upon earth,—
│
│ 5 The sweeping up the heart,
│ 6 And putting love away
│ 7 We shall not want to use again
│ 8 Until eternity.
├── diff:
│ --- orig
│ +++ var
│ @@ -1,13 +1 @@
│ - 1 The quick brown fox jumps over the lazy dog.
│ - 1 Don't worry, spiders,
│ - 2 I keep house
│ - 3 casually.
│ - 1 The bustle in a house
│ - 2 The morning after death
│ - 3 Is solemnest of industries
│ - 4 Enacted upon earth,—
│ -
│ - 5 The sweeping up the heart,
│ - 6 And putting love away
│ - 7 We shall not want to use again
│ - 8 Until eternity.
│ +Hello, world!
└── var as str: Hello, world!
command=`"/Users/koyasaeki/ghq/github.com/koyasaeki/rust-solutions/catr/target/debug/catr" "tests/inputs/fox.txt" "tests/inputs/spiders.txt" "tests/inputs/the-bustle.txt" "-b"`
code=0
stdout="Hello, world!\n"
stderr=""
---- fox_b stdout ----
thread 'fox_b' panicked at /rustc/82e1608dfa6e0b5569232559e3d385fea5a93112/library/core/src/ops/function.rs:250:5:
Unexpected stdout, failed diff original var
├── original: 1 The quick brown fox jumps over the lazy dog.
├── diff:
│ --- orig
│ +++ var
│ @@ -1 +1 @@
│ - 1 The quick brown fox jumps over the lazy dog.
│ +Hello, world!
└── var as str: Hello, world!
command=`"/Users/koyasaeki/ghq/github.com/koyasaeki/rust-solutions/catr/target/debug/catr" "-b" "tests/inputs/fox.txt"`
code=0
stdout="Hello, world!\n"
stderr=""
---- fox stdout ----
thread 'fox' panicked at /rustc/82e1608dfa6e0b5569232559e3d385fea5a93112/library/core/src/ops/function.rs:250:5:
Unexpected stdout, failed diff original var
├── original: The quick brown fox jumps over the lazy dog.
├── diff:
│ --- orig
│ +++ var
│ @@ -1 +1 @@
│ -The quick brown fox jumps over the lazy dog.
│ +Hello, world!
└── var as str: Hello, world!
command=`"/Users/koyasaeki/ghq/github.com/koyasaeki/rust-solutions/catr/target/debug/catr" "tests/inputs/fox.txt"`
code=0
stdout="Hello, world!\n"
stderr=""
---- spiders stdout ----
thread 'spiders' panicked at /rustc/82e1608dfa6e0b5569232559e3d385fea5a93112/library/core/src/ops/function.rs:250:5:
Unexpected stdout, failed diff original var
├── original: Don't worry, spiders,
│ I keep house
│ casually.
├── diff:
│ --- orig
│ +++ var
│ @@ -1,3 +1 @@
│ -Don't worry, spiders,
│ -I keep house
│ -casually.
│ +Hello, world!
└── var as str: Hello, world!
command=`"/Users/koyasaeki/ghq/github.com/koyasaeki/rust-solutions/catr/target/debug/catr" "tests/inputs/spiders.txt"`
code=0
stdout="Hello, world!\n"
stderr=""
---- spiders_n stdout ----
thread 'spiders_n' panicked at /rustc/82e1608dfa6e0b5569232559e3d385fea5a93112/library/core/src/ops/function.rs:250:5:
Unexpected stdout, failed diff original var
├── original: 1 Don't worry, spiders,
│ 2 I keep house
│ 3 casually.
├── diff:
│ --- orig
│ +++ var
│ @@ -1,3 +1 @@
│ - 1 Don't worry, spiders,
│ - 2 I keep house
│ - 3 casually.
│ +Hello, world!
└── var as str: Hello, world!
command=`"/Users/koyasaeki/ghq/github.com/koyasaeki/rust-solutions/catr/target/debug/catr" "--number" "tests/inputs/spiders.txt"`
code=0
stdout="Hello, world!\n"
stderr=""
---- usage stdout ----
thread 'usage' panicked at /rustc/82e1608dfa6e0b5569232559e3d385fea5a93112/library/core/src/ops/function.rs:250:5:
Unexpected stdout, failed var.contains(USAGE)
├── var: Hello, world!
└── var as str: Hello, world!
command=`"/Users/koyasaeki/ghq/github.com/koyasaeki/rust-solutions/catr/target/debug/catr" "-h"`
code=0
stdout="Hello, world!\n"
stderr=""
---- fox_n stdout ----
thread 'fox_n' panicked at /rustc/82e1608dfa6e0b5569232559e3d385fea5a93112/library/core/src/ops/function.rs:250:5:
Unexpected stdout, failed diff original var
├── original: 1 The quick brown fox jumps over the lazy dog.
├── diff:
│ --- orig
│ +++ var
│ @@ -1 +1 @@
│ - 1 The quick brown fox jumps over the lazy dog.
│ +Hello, world!
└── var as str: Hello, world!
command=`"/Users/koyasaeki/ghq/github.com/koyasaeki/rust-solutions/catr/target/debug/catr" "-n" "tests/inputs/fox.txt"`
code=0
stdout="Hello, world!\n"
stderr=""
---- spiders_b stdout ----
thread 'spiders_b' panicked at /rustc/82e1608dfa6e0b5569232559e3d385fea5a93112/library/core/src/ops/function.rs:250:5:
Unexpected stdout, failed diff original var
├── original: 1 Don't worry, spiders,
│ 2 I keep house
│ 3 casually.
├── diff:
│ --- orig
│ +++ var
│ @@ -1,3 +1 @@
│ - 1 Don't worry, spiders,
│ - 2 I keep house
│ - 3 casually.
│ +Hello, world!
└── var as str: Hello, world!
command=`"/Users/koyasaeki/ghq/github.com/koyasaeki/rust-solutions/catr/target/debug/catr" "--number-nonblank" "tests/inputs/spiders.txt"`
code=0
stdout="Hello, world!\n"
stderr=""
---- skips_bad_file stdout ----
thread 'skips_bad_file' panicked at /rustc/82e1608dfa6e0b5569232559e3d385fea5a93112/library/core/src/ops/function.rs:250:5:
Unexpected stderr, failed var.is_match(sAGY6pP: .* [(]os error 2[)])
├── var:
└── var as str:
command=`"/Users/koyasaeki/ghq/github.com/koyasaeki/rust-solutions/catr/target/debug/catr" "sAGY6pP"`
code=0
stdout="Hello, world!\n"
stderr=""
failures:
all
all_b
all_n
bustle
bustle_b
bustle_n
bustle_stdin
bustle_stdin_b
bustle_stdin_n
empty
empty_b
empty_n
fox
fox_b
fox_n
skips_bad_file
spiders
spiders_b
spiders_n
usage
test result: FAILED. 0 passed; 20 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.19s
error: test failed, to rerun pass `--test cli`
catr
からはコードを src/lib.rs
と src/main.rs
に分ける。
main.rs
は基本的に lib.rs
の run
を呼び出す形にする。
lib.rs
では以下のように成功 or 失敗を返す MyResult
を定義して、 run
の返り値とする。
type MyResult<T> = Result<T, Box<dyn Error>>;
pub fn run() -> MyResult<()> {
println!("Hello, world!");
Ok(())
}
この MyResult
は echor
のテストで書いた TestResult
のジェネリクス版になっている。
main.rs
は lib.rs
の run
を呼び出す形にする。
fn main() {
if let Err(e) = catr::run() {
eprintln!("Application error: {}", e);
std::process::exit(1);
}
}
if let
と eprintln!
を使ったことがないので調べる。
if let
はこれがわかりやすかったのでこれ以上調べない。
eprintln!
は単純に標準エラーにエラーを書き込むだけだった。 e
は error
の e
なのね。
今日まで