casting vs. conversion
詳しい違いはよくわからないけど、casting はasを使って行うものであって、conversion はFromとIntoを使って行うものだと思っている。
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
AにFrom<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! )<
}