rust

Rust by Examples のお勉強 - Types, Conversion

casting vs. conversion

詳しい違いはよくわからないけど、casting はasを使って行うものであって、conversion はFromIntoを使って行うものだと思っている。

casting

let dec = 65.4321_f32;
let int = dec as u8;
let ch = int as char;
println!("{} -> {} -> {}", dec, int, ch); // 65.4321 -> 65 -> A

From

AFrom<B>を実装すると、A::from()を使ってBからAへの conversion が出来る。use std::convert::From;を忘れずに。

use std::convert::From;

#[derive(Debug)]
struct Wrap(i32);

impl From<i32> for Wrap {
    fn from(x: i32) -> Wrap {
        Wrap(x)
    }
}

fn main() {
    let w = Wrap::from(12);
    println!("{:?}", w); // Wrap(12)
}

Into

Fromを実装すれば、Intoも自動的に実装される。しかし、Fromと違って、コンパイラはIntoがどの型に convert しているのが分からないので、type annotation を書く必要がある。

fn main() {
    let w: Wrap = 12.into();
    println!("{:?}", w"); // Wrap(12)
}

ToString

std::string::ToStringにある。std::fmt::Displayを実装すれば、ToStringを実装する必要はない。

次の例では、Stringを返すマクロformat!を使っている。

use std::string::ToString;

#[derive(Debug)]
struct Wrap(i32);

impl ToString for Wrap {
    fn to_string(&self) -> String {
        format!("<< {} >>", self.0)
    }
}

fn main() {
    let w = Wrap(12);
    println!("{}", w.to_string()); // << 12 >>
}

FromStr

std::str::FromStrにある。Stringではなく&strからの変換だと言うことに注意。変換先の型自体ではなく、Resultを返すので、自分のエラー型Errも書かないといけない。

use std::str::FromStr;
use std::string::*;
use std::fmt;

struct MessageFish {
    msg: String,
}

#[derive(Debug)]
struct MessageFishErr;

impl fmt::Display for MessageFish {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "(x ")?;
        write!(f, "{}", self.msg)?;
        write!(f, " )<")
    }
}

impl FromStr for MessageFish {
    type Err = MessageFishErr;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Ok(MessageFish {
            msg: String::from_str(s).unwrap()
        })
    }
}

fn main() {
    let msg = "rust is fun!";
    let fish = msg.parse::<MessageFish>().unwrap();
    println!("{}", &fish);            // 
    println!("{}", fish.to_string()); // (x rust is fun! )<
}