Type conversion in Rust (as, From, and Into)
Tags: rust, programming, gamedev
Published: 2021-01-15 13:47:18

I'm fairly new to [Rust](https://www.rust-lang.org/) and it's a language I've actually enjoyed learning, mainly for game development with [Bevy](https://bevyengine.org/). As someone who is coming for a JS/TS background, there is a huge learning curve and I'm eventually planning to create a video course on how to make a simple game with Rust, but for now, I'm going to document things down (in the form of dev.to articles) as and when I learn them to help people who are having difficulties. 

This particular feature of Rust is something I've seen a lot in Bevy example code particularly when it comes to colours, for example:

```rs
materials.add(Color::rgb(0.7, 0.7, 0.7).into())
```

The **.into()** method is something that I've scratched my brain over for ages and I've finally been able to figure out what it does. Well, at least I think I have.

## as

Simple (explicit) type conversion or casting in Rust can be done with the **as** keyword:

```rs
fn main() {
  let num:u8 = 10;
  let multiplied = times_ten(num as f32);

  println!("{}", multiplied); // 100
}

fn times_ten(val: f32) -> f32 { 
  val * 10.0 
}
```
## From
**From** in Rust is one of two traits for type conversion (if you don't know what a trait I'm planning to write a post on it in the future).

Let's say I want to create my own special type called `MySpecialNumber` and want to convert an existing u32 variable to my custom type, I would do it like this:

```rs
#[derive(Debug)] // needed because struct displays nothing so needs to have a debug view
struct MySpecialNumber(u32);

impl From<u32> for MySpecialNumber {
  fn from(num: u32) -> Self {
    MySpecialNumber(num)
  }
}

fn main() {
  let existing_var = 30;
  let num = MySpecialNumber::from(existing_var);
  println!("{:?}", num); // Prints -> MySpecialNumber(30)
}
```

*If this is the first time you've seen the `struct` or `impl` keyword again, don't worry. I'm planning to cover those in future posts. They're a bit, different if you're coming from Javascript, you can think of them as a slightly more complicated way of making an object.*


The above code snippet takes the `existing_var` of type u32 and changes it to type `MySpecialNumber` using the from method written above.

Because the From method is extending a trait it has to be written in a very specific way for it to work. If I changed the line `fn from(num: u32)` to `fn from(num: f32)` it wouldn't work. The source code for the From trait can be found on the [Rust Github repo](https://github.com/rust-lang/rust/blob/1.49.0/library/core/src/convert/mod.rs#L373).

## Into

**Into** is the second trait in Rust used for type conversion. It works in the opposite direction to the From trait, instead of creating **x** FROM **y**, it turns **y** INTO **x**, makes sense? It's a bit confusing right. I feel like code is the best way to explain things so let's jump straight *into* it (no pun intended).

### First way to use Into

If there's an implementation of the From trait already we can also use the Into trait which is pretty cool.

To use into the main function of the above code snipped can be re-written as:

```rs
...

fn main() {
  let existing_var: u32 = 30;
  let num: MySpecialNumber = existing_var.into();
  println!("{:?}", num); // Prints -> MySpecialNumber(30)
}
```

Arguably this was is more readable. The `existing_var` is being converted to `MySpecialNumber` because it has been added as a type annotation. If that get's removed Rust won't know what type to convert the existing variable to.

```rs
let num = existing_var.into(); // this won't work
```


If you *really* wanted to, you could write a full Into method similar to the way I wrote the From method above using the [Into that from the Rust source code](https://github.com/rust-lang/rust/blob/1.49.0/library/core/src/convert/mod.rs#L278), but I think From is good enough.

### Second way to use Into

For this way we're going back to my `times_ten` function I used above when desiring the **as** keyword.

```rs
fn main() {
  let num:u8 = 10;
  let multiplied = times_ten(num as f32);

  println!("{}", multiplied); // 100
}

fn times_ten(val: f32) -> f32 { 
  val * 10.0 
}
```

Instead of using **as** we can use the **Into** trait like so:

```rs
fn main() {
  let num:u8 = 10;
  let multiplied = times_ten(num);

  println!("{}", multiplied); // 100
}

fn times_ten<T: Into<f32>>(val: T) -> f32 { 
  val.into() * 10.0 
}
```
So if you compare the last two code snippets, you'll see we can omit the **as** keyword and the type to convert to and move that logic to the times_ten function in the form of a [generic data type](https://doc.rust-lang.org/rust-by-example/generics.html) `T` and the Into trait.

No matter what type the argument is that is passed into the times_ten function it will always be converted fo an f32 before it is multiplied by 10. 

Don't worry if this doesn't make sense now, the more you use it, the more sense it will make.

---

Like I said at the beginning I'm new to Rust so there's a chance I haven't explained something properly or I've missed something out when it comes to type conversion then please let me know.

I've tried my best to explain this in the simplest way possible but if something I've said doesn't make any sense, again please let me know.



### Sources
https://doc.rust-lang.org/rust-by-example/conversion/from_into.html
https://www.youtube.com/watch?v=vH5xXr81a2Y
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=c749b272a173bfb34371092c562551fa