Lesson 5.3 · 8 min
One of several: enum
Chatterbox decides what to do by comparing strings like "/help". A typo in one of them compiles fine and fails at run time. An enum lists every possible command once, and the compiler holds you to it.
Adds to ChatterboxA Command enum, matched exhaustively.
A value that is exactly one of these
A struct says "this and this and this". An enum says "this or that or the other". A line you type to Chatterbox is one of a few things: ask for help, quit, say something, or something it does not understand.
Each option is a variant, and a variant can carry its own data. Say carries the text to say; Unknown carries the line it could not read; Help and Quit carry nothing.
$ cargo run
hello
byeIn match (lesson 3.2) you matched text. Here each arm names a variant, and Say(text) also pulls the data out and gives it a name inside that arm. Because cmd is owned, text is moved out of it: the arm simply hands the string on.
Now delete an arm and see what the compiler thinks.
error[E0004]: non-exhaustive patterns: `Command::Unknown(_)` not covered --> src/main.rs:9:11 | 9 | match cmd { | ^^^ pattern `Command::Unknown(_)` not covered | note: `Command` defined here --> src/main.rs:1:6 | 1 | enum Command { | ^^^^^^^ ... 5 | Unknown(String), | ------- not covered = note: the matched value is of type `Command` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | 12 ~ Command::Say(text) => text, 13 ~ Command::Unknown(_) => todo!(), |
E0004: "non-exhaustive patterns: Command::Unknown(_) not covered". The compiler lists the case you forgot. A match must cover every variant, so adding a new command later turns every match that forgot it into a compile error. That is the whole value: a string comparison can only fail at run time, an enum fails at build time.
From a line to a Command
Something has to turn the typed line into a variant. That is parse. It borrows the line as a &str and returns a brand-new Command that owns whatever it carries.
What does this print?
say: [hi there]unknown: [/say hi there]other
Reveal the answer
The program prints: say: [hi there] trim() removes the outer spaces first, so the line becomes /say hi there. It does not match /help or /quit, falls to other, starts with /say , and &other[5..] is everything after those five characters.
$ cargo run
commands: /help /quit /say <text>
hello
unknown: /dance
byeNearly the whole file is new, because the old string comparisons moved into parse and handle. Look at main: it is now one line of real logic. Parsing is in one place, handling is in another, and the enum is the contract between them.
Return a short label for a command, borrowed: help, quit, say:<text> or ?<line> for unknown. Cover every variant.
Return a short label for a command, borrowed: help, quit, say:<text> or ?<line> for unknown. Cover every variant.
Hidden tests (3): plain_variants say_carries_text unknown_carries_line
This exercise runs real Rust in your browser through the official Rust Playground, so it needs JavaScript.
Say it out loud, then reveal
What can a variant like <code>Say(String)</code> do that a plain constant cannot?Reveal
What does E0004 protect you from?Reveal
Why does <code>parse</code> take <code>&str</code> but return an owned <code>Command</code>?Reveal
That is lesson 5.3. Tick it off so the course remembers where you are.