Converting a hexadecimal string to a binary string using Rust pattern matching lookup I am getting started in Rust, and as a part of my first exercise, I decided to write a small program that converts a hexadecimal string to a binary string using a pattern matched lookup. I would appreciate a constructive review.

fn main() {
    let binary_value = convert_to_binary_from_hex("0x39A7F8");
    println!("Converted: {}", binary_value);   
}

fn convert_to_binary_from_hex(hex: &amp;str) -&gt; String {
   let to_binary = hex[2 ..]
       .chars()
       .map(|c| to_binary(c))
       .collect();

   to_binary
} 

fn to_binary(c: char) -&gt; String {
    let b = match c {
       '0' =&gt; "0000",
       '1' =&gt; "0001",
       '2' =&gt; "0010",
       '3' =&gt; "0011",
       '4' =&gt; "0100",
       '5' =&gt; "0101",
       '6' =&gt; "0110",
       '7' =&gt; "0111",
       '8' =&gt; "1000",
       '9' =&gt; "1001",
       'A' =&gt; "1010",
       'B' =&gt; "1011",
       'C' =&gt; "1100",
       'D' =&gt; "1101",
       'E' =&gt; "1110",
       'F' =&gt; "1111",
        _  =&gt; "",
    };

   b.to_string()
}
Rustfmt is a tool for automatically formatting Rust code to the community-accepted style.
Clippy is a tool for finding common mistakes that may not be compilation errors but are unlikely to be what the programmer intended.


Rustfmt points out that you are using 3-space indents (Rust uses 4), and that some of your lines don't need to be split.

Clippy points out:

warning: returning the result of a let binding from a block
 --&gt; src/main.rs:9:5
  |
7 |     let to_binary = hex[2..].chars().map(|c| to_binary(c)).collect();
  |     ----------------------------------------------------------------- unnecessary let binding
8 |
9 |     to_binary
  |     ^^^^^^^^^
  |
  = note: #[warn(clippy::let_and_return)] on by default
  = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#let_and_return
help: return the expression directly
  |
7 |
8 |
9 |     hex[2..].chars().map(|c| to_binary(c)).collect()
  |

warning: redundant closure found
 --&gt; src/main.rs:7:42
  |
7 |     let to_binary = hex[2..].chars().map(|c| to_binary(c)).collect();
  |                                          ^^^^^^^^^^^^^^^^ help: remove closure as shown: `to_binary`
  |
  = note: #[warn(clippy::redundant_closure)] on by default
  = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure


There's no reason to return a String here, a &amp;'static str is lighter-weight. See What are the differences between Rust's String and str? for full details, but a String requires a heap allocation, while a &amp;'static str is a reference to some existing data in the compiled binary.

With these changes, all of your tests pass:

fn main() {
    let binary_value = convert_to_binary_from_hex("0x39A7F8");
    println!("Converted: {}", binary_value);
}

fn convert_to_binary_from_hex(hex: &amp;str) -&gt; String {
    hex[2..].chars().map(to_binary).collect()
}

fn to_binary(c: char) -&gt; &amp;'static str {
    match c {
        '0' =&gt; "0000",
        '1' =&gt; "0001",
        '2' =&gt; "0010",
        '3' =&gt; "0011",
        '4' =&gt; "0100",
        '5' =&gt; "0101",
        '6' =&gt; "0110",
        '7' =&gt; "0111",
        '8' =&gt; "1000",
        '9' =&gt; "1001",
        'A' =&gt; "1010",
        'B' =&gt; "1011",
        'C' =&gt; "1100",
        'D' =&gt; "1101",
        'E' =&gt; "1110",
        'F' =&gt; "1111",
        _ =&gt; "",
    }
}


In fact, deleting all of your code causes your tests to pass. It would be a good idea to add some tests!

Depending on what routes you want to look down next, you could try:


to handle strings that do not start with 0x without panicking.
to handle upper- and lower-case hex
to reduce/avoid string munging yourself