Checking against user input and returns a response based on that input How could I use enums in the following block of code to simplify it? The block is a program that has a command interpreter that returns different data based on user input. Is there a way I could easily apply enums and a match statement to the logic here?

use std::io;

fn main() {
    let version = String::from("0.0.1");
    let mut input = String::new();

    shell(&amp;mut input, &amp;version);
}

fn shell(input: &amp;mut String, version: &amp;String) {
    input.clear();
    match io::stdin().read_line(input) {
        Ok(b) =&gt; {
            if &amp;input.trim() == &amp;"ver" || &amp;input.trim() == &amp;"what are you" {
                println!("C ute R ust A mateur B eginner Shell ver: {}", version);
                shell(input, version);
            } else {
                println!("Command '{}' Not Recognized", input);
                shell(input, &amp;version);
            }
        }
        Err(err) =&gt; panic!("incorrect"),
    }
}
Use rustfmt. I know the code you've presented is formatted correctly now, but that's because I reformatted it for you over on Stack Overflow (I wouldn't have touched it here).
Read and address the compiler's warning messages!

warning: unused variable: `b`
  --&gt; src/main.rs:13:12
   |
13 |         Ok(b) =&gt; {
   |            ^ help: consider using `_b` instead
   |
   = note: #[warn(unused_variables)] on by default

warning: unused variable: `err`
  --&gt; src/main.rs:22:13
   |
22 |         Err(err) =&gt; panic!("incorrect"),
   |             ^^^ help: consider using `_err` instead

warning: function cannot return without recursing
  --&gt; src/main.rs:10:1
   |
10 | fn shell(input: &amp;mut String, version: &amp;String) {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
...
16 |                 shell(input, version);
   |                 --------------------- recursive call site
...
19 |                 shell(input, &amp;version);
   |                 ---------------------- recursive call site
   |
   = note: #[warn(unconditional_recursion)] on by default
   = help: a `loop` may express intention better if this is on purpose

    Finished dev [unoptimized + debuginfo] target(s) in 2.16s
     Running `target/debug/playground`

Don't have infinite recursion; that's almost always a bad idea and you will run out of stack space. Write an infinite loop instead.
There's no reason to put input outside of the function, as it's only ever used inside it.
Use clippy. It will point out things like:

warning: writing `&amp;String` instead of `&amp;str` involves a new object where a slice will do.
 --&gt; src/main.rs:9:19
  |
9 | fn shell(version: &amp;String) {
  |                   ^^^^^^^ help: change this to: `&amp;str`
  |
  = note: #[warn(clippy::ptr_arg)] on by default
  = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#ptr_arg

warning: needlessly taken reference of both operands
  --&gt; src/main.rs:15:16
   |
15 |             if &amp;input.trim() == &amp;"ver" || &amp;input.trim() == &amp;"what are you" {
   |                ^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: #[warn(clippy::op_ref)] on by default
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#op_ref
help: use the values directly
   |
15 |             if input.trim() == "ver" || &amp;input.trim() == &amp;"what are you" {
   |                ^^^^^^^^^^^^    ^^^^^


See also:


Why is it discouraged to accept a reference to a String (&amp;String), Vec (&amp;Vec), or Box (&amp;Box) as a function argument?

Use Result::expect instead of doing the match yourself. This has the beenfit of printing out the underlying error message as well.
Store the result of trim to avoid doing the work multiple times.
Consider using a match on the trimmed string to decide what to work on.


use std::io;

fn main() {
    let version = "0.0.1";

    shell(version);
}

fn shell(version: &amp;str) {
    let mut input = String::new();
    loop {
        input.clear();
        io::stdin().read_line(&amp;mut input).expect("incorrect");
        let input = input.trim();

        match input {
            "ver" | "what are you" =&gt; {
                println!("C ute R ust A mateur B eginner Shell ver: {}", version)
            }
            _ =&gt; println!("Command '{}' Not Recognized", input),
        }
    }
}


Now we can consider how best to use enums here. An enum is good for a type that can be one of many values. You have that structure in your "command" decisions. You could create an enum from those strings:

use std::io;

fn main() {
    let version = "0.0.1";

    shell(version);
}

fn shell(version: &amp;str) {
    let mut input = String::new();
    loop {
        input.clear();
        io::stdin().read_line(&amp;mut input).expect("incorrect");
        let command = input.trim().parse::&lt;Command&gt;();

        use Command::*;
        match command {
            Ok(Version) | Ok(WhatAreYou) =&gt; {
                println!("C ute R ust A mateur B eginner Shell ver: {}", version)
            }
            Err(_) =&gt; println!("Command '{}' Not Recognized", input),
        }
    }
}

#[derive(Debug)]
enum Command {
    Version,
    WhatAreYou,
}

impl std::str::FromStr for Command {
    type Err = ();

    fn from_str(input: &amp;str) -&gt; Result&lt;Self, Self::Err&gt; {
        use Command::*;
        Ok(match input {
            "ver" =&gt; Version,
            "what are you" =&gt; WhatAreYou,
            _ =&gt; return Err(()),
        })
    }
}