How can I generate a Select prompt with dialoguer from an enum? - rust

I have the following code that prompts for a color:
enum Color {
Red,
Yellow,
Green,
Blue
}
let color_response: usize = Select::with_theme(&ColorfulTheme::default())
.with_prompt("Color")
.default(0)
.items(/* this takes a slice with strings. what should i put here? */)
.interact()
.unwrap();
let color: Color = // what to put here? should I use a match statement
I am unsure how to properly generate the enum names and index the enum to get the name from it. How can I accomplish this?

Related

Find what std::convert::try_into, converts to

I am learning Rust and here is the sample from the book
use std::convert::TryInto;
fn main() {
let a: i32 = 10;
let b: u16 = 100;
let b_ = b.try_into()
.unwrap();
if a < b_ {
println!("Ten is less than one hundred.");
}
}
Author says b.try_into() converts b to i32. But where do we specify this in code? b_ is not given an explicit type, so why would a u16 get converted to i32 and not to a u32 or something else?
Thanks.
Rust has a quite smart compiler and it can look at nearby code to determine what type a variable should get. This is called type inference.
If you explicitly want to set the type that the .try_into() function should convert, you can put the type in the usual position.
let b_: i32 = b.try_into().unwrap();
You also need to remember that you cannot specify any type for conversion because they are manually implemented in the Rust standard library.
My guess is that the compiler looks at the bottom if statement and infers that b_ should be a i32 (So that it can perform the if check with a which it already knows is an i32).
I also tested that reversing the condition i.e if b_ > a causes a compile error. I guess it is because it wants to know what type b_ is before going for a

Rust Book Example: Does dbg! return ownership or not?

In the Rust official guide chapter 5.2:
#[derive(Debug)]
struct Rectangle {
width: u32,
height: u32,
}
fn main() {
let scale = 2;
let rect1 = Rectangle {
width: dbg!(30 * scale),
height: 50,
};
dbg!(&rect1);
}
We can put dbg! around the expression 30 * scale and, because dbg! returns ownership of the expression’s value,
the width field will get the same value as if we didn’t have the dbg!
call there. We don’t want dbg! to take ownership of rect1, so we use a
reference to rect1 in the next call.
The guide states that dbg! returns ownership of the width expressions value, then right after it says we don't want dbg! to take ownership of rect1 so we use a reference. Why wouldn't dbg! return ownership of rect1?
The point is that dbg! takes the ownership and then returns it back as a value it evaluates to. It works as something like this function:
fn dbg<T: Debug>(val: T) -> T {
// some debug printing of `val`
val
}
(The real implementation is a little more complex, since it uses the file-line-column information, exact evaluated expression, and works correctly with lifetimes of temporaries)
That is, the value is moved into the dbg!, but then moved again from dbg! into whatever binding you assign it to.
In the first case, therefore, the value of dbg! is assigned to the struct field, so this field will be equal to 30 * scale. The second case, on the other hand, also be written like this:
let rect1 = dbg!(rect1);
That is, you move the value out of rect1, print it, and then store it into new binding, also named rect1.
In that second case, it actually takes ownership of what is passed to it, that is, a reference to rect1, not rect1, which it then returns, before instantly discarding it because you are not retrieving it (ie. you are not doing something like let ref_to_rect1 = dbg!(&rect1);).

How do I get a vector of u8 RGB values when using the image crate?

I need to take an image and get a list of RGB byte values. I am using the image crate. This is what I have:
extern crate image;
fn main() {
let im = image::open("wall.jpg").unwrap().to_rgb();
let data: Vec<[u8; 3]> = im.pixels().flat_map(|p| vec![p.data]).collect();
let rgb: Vec<&u8> = data.iter().flat_map(|p| p.iter()).collect();
println!("First Pixel: {} {} {}", rgb[0], rgb[1], rgb[2]);
}
This seems pretty ugly. I have to introduce an intermediate variable and I get a vector of pointers to the values I really need, so before I can do something else, I would have to map over it again to get the actual values.
All I want is a vector of u8. How do I get that?
As of 0.23.12, to_rgb has been deprecated use DynamicImage::to_rgb8 or DynamicImage::to_bytes instead:
let im = image::open("wall.jpg").unwrap().to_rgb8();
let rgb: Vec<u8> = im.into_raw();
// Alternatively
let bytes = image::open("wall.jpg").unwrap().to_bytes();
Prior to 0.23.12, if you just want the raw data itself, you can just call DynamicImage::raw_pixels:
let im = image::open("wall.jpg").unwrap().to_rgb();
let rgb: Vec<u8> = im.raw_pixels();
If all you're actually interested in is the first pixel though, I'd recommend calling GenericImage::get_pixel:
let im = image::open("wall.jpg").unwrap();
let first_pixel = im.get_pixel(0, 0);
Which you can then turn into a [u8; 3] array of RGB data:
let rgb = first_pixel.to_rbg();
println!("First Pixel: {} {} {}", rgb.data[0], rgb.data[1], rgb.data[2]);

How do I use read_scanline from the piston image crate?

I just started learning Rust and I really like to learn by building something 'real'. So I read through the Book, installed Rust, played around with the language and got cargo run working.
I then decided to try and read an image from disk and convert that image into a Vec. In this case, I want to detect the color of the pixels and store that somehow.
I broke it into multiple parts to learn Rust and its syntax:
Starting with:
Read an image from disk
Get the pixels of an image
Show colour code
This led me to the following code using the image crate:
extern crate image;
use std::path::Path;
use image::GenericImage;
fn main() {
let img = image::open(&Path::new("src/maze.gif")).unwrap();
let pixels = img.pixels();
for e in pixels {
let (_, _, color) = e;
println!("Pixel colour {:?}", color);
}
println!("Dimensions {:?}", img.dimensions());
}
So proud as I am, I see some information popping up:
* snip *
Pixel colour Rgba { data: [255, 255, 255, 255] }
Pixel colour Rgba { data: [0, 0, 0, 255] }
Pixel colour Rgba { data: [255, 255, 255, 255] }
* snip *
Now I want to store for each line of the image its pixel information. I would like to have a Vec (is that correct?) with the info. A PHP array would look like this:
$a = [
0 => [ Color, Color, Color, Color],
1 => [ Color, Color, Color, Color]
];
Therefore my assumption is to use read_scanline. This is where reading AND understanding the documentation fails me completely.
What I think I need to do is:
Get the decoder for the current opened image
Call read_scanline on that decoder
Iterate over the results
But how?!
The code reads this:
read_scanline(&mut self, buf: &mut [u8]) -> ImageResult<u32>
I break this down as follows:
First argument, an ImageDecoder object.
Second argument a mutable 8 bit value.
It returns an ImageResult object.
So I tried adapting the code slightly:
extern crate image;
use std::path::Path;
use image::GenericImage;
use image::ImageDecoder;
fn main() {
let img = image::open(&Path::new("src/maze.gif")).unwrap();
let pixels = img.pixels();
let something: &mut [u8];
let result = image::ImageDecoder::read_scanline(img, something);
for e in pixels {
let (_, _, color) = e;
println!("Pixel colour {:?}", color);
}
println!("Dimensions {:?}", img.dimensions());
}
Which, as you might have guessed fails miserably.
error: mismatched types:
expected `&mut _`,
found `image::dynimage::DynamicImage`
(expected &-ptr,
found enum `image::dynimage::DynamicImage`) [E0308]
src/main.rs:13 let result = image::ImageDecoder::read_scanline(img, something);
Obviously this is due to the fact I didn't pass an ImageDecoder object. But how can I? How should I read and understand the documentation. I think it is due to not understanding &mut self. I also do not understand how I should initiate this.
I hope someone can explain what it is I am missing and point me into the right direction.
Note I'm having trouble actually opening a GIF as each line says it is 0 bytes, so there's the possibility I've missed something important... I'll use a JPEG to demonstrate instead.
ImageDecoder is a trait. You need to use a concrete implementation of the trait. The documentation lists all known implementors of the trait, one of which is image::gif::Decoder, another is image::jpeg::JPEGDecoder.
read_scanline accepts a mutable self, which means that you normally will call it with method syntax: object.method(arg1). The first non-self argument is a mutable slice of bytes. The documentation states:
Reads one row from the image into buf and returns the row index
So the pixel data will be stored in the buffer. The next trick is to figure out how many bytes we need for a row and how many rows there are. ImageDecoder::row_len and ImageDecoder::dimensions address that respectively. Put together, we get something like this:
extern crate image;
use std::fs::File;
use image::jpeg;
use image::{GenericImage, ImageDecoder};
use image::{ColorType, Rgb, Pixel};
fn main() {
let f = File::open("/tmp/cat.jpg").unwrap();
let mut decoder = jpeg::JPEGDecoder::new(f);
let (width, height) = decoder.dimensions().unwrap();
let row_len = decoder.row_len().unwrap();
println!("{} x {}, {}", width, height, row_len);
let rows: Vec<_> = (0..height).map(|_| {
let mut row = vec![0; row_len];
decoder.read_scanline(&mut row).unwrap();
row
}).collect();
}
This loads the JPEG, row-by-row, into a Vec<Vec<u8>> - a vector of vectors of bytes.
To convert the raw data into pixels, we can use Pixel::from_slice, another trait method. In this case, I only handle one type of pixel - 8-bit RGB:
let colortype = decoder.colortype().unwrap();
assert_eq!(colortype, ColorType::RGB(8)); // Others are left to you!
let row_colors: Vec<Vec<_>> = rows.iter().map(|r| {
r.chunks(3).map(|p| Rgb::from_slice(p)).collect()
}).collect();
I'm not in love with this because of the hard-coded 3. There should be some way of knowing that this pixel type only takes 3 bytes, but I'm not seeing anything obvious.

Get an enum field from a struct: cannot move out of borrowed content

I'm new to Rust and trying to wrap my head around the ownership/borrowing concept. Now I have reduced my code to this minimal code sample that gives a compile error.
pub struct Display {
color: Color,
}
pub enum Color {
Blue = 0x1,
Red = 0x4,
}
impl Display {
fn get_color_value(&self) -> u16 {
self.color as u16
}
}
src/display.rs:12:9: 12:13 error: cannot move out of borrowed content
src/display.rs:12 self.color as u16
^~~~
error: aborting due to previous error
Could not compile.
I'm still in the everything is copied by value mindset, where it is perfectly legal to do self.color as that would get me a copy of Color. Apparently, I am wrong. I found some other questions about this same error on SO, but no solution to my issue.
As I understand it, the field is owned by whomever owns the Display. Since I only borrowed a
reference to the Display, I don't own it. Extracting color attempts to transfer ownership of
the Color to me, which is not possible since I don't own the Display. Is this correct?
How do I solve it?
I'm still in the everything is copied by value mindset, where it is
perfectly legal to do self.color as that would get me a copy of Color.
Apparently, I am wrong. I found some other questions about this same
error on SO, but no solution to my issue.
Anything that can be copied in rust must be explicitly mared with a trait Copy. Copy was implicit in the past but that was changed (rfc).
As I understand it, the field is owned by whomever owns the Display.
Since I only borrowed a reference to the Display, I don't own it.
Extracting color attempts to transfer ownership of the Color to me,
which is not possible since I don't own the Display. Is this correct?
Yes. When you encounter this error there are three possible solutions:
Derive the trait Copy for the type (if appropriate)
Use/derive Clone (self.color.clone())
Return a reference
To solve this you derive Copy for Color:
#[derive(Copy, Clone)]
pub enum Color {
Blue = 0x1,
Red = 0x4,
}
This is the same as:
impl Copy for Color {}

Resources