How to Do RGB to Hex Conversion in Rust


The challenge

The rgb function is incomplete. Complete it so that passing in RGB decimal values will result in a hexadecimal representation being returned. Valid decimal values for RGB are 0 – 255. Any values that fall out of that range must be rounded to the closest valid value.

Note: Your answer should always be 6 characters long, the shorthand with 3 will not work here.

The following are examples of expected output values:

challenge.rgb(255, 255, 255) -- returns FFFFFF
challenge.rgb(255, 255, 300) -- returns FFFFFF
challenge.rgb(0, 0, 0) -- returns 000000
challenge.rgb(148, 0, 211) -- returns 9400D3

The solution in Rust

Option 1:

fn rgb(r: i32, g: i32, b: i32) -> String {
    format!(
        "{:02X}{:02X}{:02X}",
        r.clamp(0, 255),
        g.clamp(0, 255),
        b.clamp(0, 255)
    ) 
}

Option 2:

fn rgb(r: i32, g: i32, b: i32) -> String {
  format!("{0:02X}{1:02X}{2:02X}", r.min(255).max(0), g.min(255).max(0), b.min(255).max(0))
}

Option 3:

fn rgb(r: i32, g: i32, b: i32) -> String {
    let r = r.min(255).max(0);
    let g = g.min(255).max(0);
    let b = b.min(255).max(0);
    format!("{:02X}{:02X}{:02X}", r, g, b)
}

Test cases to validate our solution

extern crate rand;
use self::rand::Rng;

fn solve(r: i32, g: i32, b: i32) -> String {
    let clamp = |x: i32| -> i32 { if x < 0 { 0 } else { if x > 255 { 255 } else { x } } };
    format!("{:02X}{:02X}{:02X}", clamp(r), clamp(g), clamp(b))
}
macro_rules! compare {
  ( $got : expr, $expected : expr ) => {
    if $got != $expected { panic!("Got: {}\nExpected: {}\n", $got, $expected); }
  };
}

#[cfg(test)]
mod tests {
    use self::super::*;

    #[test]
    fn basic_tests() {
        compare!(rgb(0, 0, 0), "000000");
        compare!(rgb(1, 2, 3), "010203");
        compare!(rgb(255, 255, 255), "FFFFFF");
        compare!(rgb(254, 253, 252), "FEFDFC");
        compare!(rgb(-20, 275, 125), "00FF7D");
    }
    
    #[test]
    fn random_tests() {
        for _ in 0..50 {
            let r = rand::thread_rng().gen_range(-32..288);
            let g = rand::thread_rng().gen_range(-32..288);
            let b = rand::thread_rng().gen_range(-32..288);
            compare!(rgb(r, g, b), solve(r, g, b));
        }
    }
}