Rust by Example — страница 11 из 66

Into

The Into trait is simply the reciprocal of the From trait. That is, if you have implemented the From trait for your type, Into will call it when necessary.

Using the Into trait will typically require specification of the type to convert into as the compiler is unable to determine this most of the time. However this is a small trade-off considering we get the functionality for free.

use std::convert::From;

#[derive(Debug)]

struct Number {

value: i32,

}

impl From for Number {

fn from(item: i32) -> Self {

Number { value: item }

}

}

fn main() {

let int = 5;

// Try removing the type declaration

let num: Number = int.into();

println!("My number is {:?}", num);

}

הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

TryFromandTryInto

Similar to FromandInto, TryFrom and TryInto are generic traits for converting between types. Unlike From/Into, the TryFrom/TryInto traits are used for fallible conversions, and as such, return Results.

use std::convert::TryFrom;

use std::convert::TryInto;

#[derive(Debug, PartialEq)]

struct EvenNumber(i32);

impl TryFrom for EvenNumber {

type Error = ();

fn try_from(value: i32) -> Result {

if value % 2 == 0 {

Ok(EvenNumber(value))

} else {

Err(())

}

}

}

fn main() {

// TryFrom

assert_eq!(EvenNumber::try_from(8), Ok(EvenNumber(8)));

assert_eq!(EvenNumber::try_from(5), Err(()));

// TryInto

let result: Result = 8i32.try_into();

assert_eq!(result, Ok(EvenNumber(8)));

let result: Result = 5i32.try_into();

assert_eq!(result, Err(()));

}

הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

To and from Strings

Converting to String

To convert any type to a String is as simple as implementing the ToString trait for the type. Rather than doing so directly, you should implement the fmt::Display trait which automagically provides ToString and also allows printing the type as discussed in the section on print!.

use std::fmt;

struct Circle {

radius: i32

}

impl fmt::Display for Circle {

fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {

write!(f, "Circle of radius {}", self.radius)

}

}

fn main() {

let circle = Circle { radius: 6 };

println!("{}", circle.to_string());

}

הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Parsing a String

One of the more common types to convert a string into is a number. The idiomatic approach to this is to use the parse function and either to arrange for type inference or to specify the type to parse using the 'turbofish' syntax. Both alternatives are shown in the following example.

This will convert the string into the type specified so long as the FromStr trait is implemented for that type. This is implemented for numerous types within the standard library. To obtain this functionality on a user defined type simply implement the FromStr trait for that type.

fn main() {

let parsed: i32 = "5".parse().unwrap();

let turbo_parsed = "10".parse::().unwrap();

let sum = parsed + turbo_parsed;

println!("Sum: {:?}", sum);

}

הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Expressions

A Rust program is (mostly) made up of a series of statements:

fn main() {

// statement

// statement

// statement

}

There are a few kinds of statements in Rust. The most common two are declaring a variable binding, and using a ; with an expression:

fn main() {

// variable binding

let x = 5;


// expression;

x;

x + 1;

15;

}

Blocks are expressions too, so they can be used as values in assignments. The last expression in the block will be assigned to the place expression such as a local variable. However, if the last expression of the block ends with a semicolon, the return value will be ().

fn main() {

let x = 5u32;

let y = {

let x_squared = x * x;

let x_cube = x_squared * x;

// This expression will be assigned to `y`

x_cube + x_squared + x

};

let z = {

// The semicolon suppresses this expression and `()` is assigned to `z`

2 * x;

};

println!("x is {:?}", x);

println!("y is {:?}", y);

println!("z is {:?}", z);