liveBook · Manning

From trait

As explained in Rust in Action: Systems programming concepts and techniques

From is a Rust standard-library trait for infallibly converting a value of one type into another type.

`From` tells Rust how to convert a value of one type into another. Implement `From<T> for U` and define `from(value: T) -> U`; callers can then write `U::from(value)`. Implementing `From` also normally makes `.into()` available for the reverse calling style. Use `TryFrom` instead when conversion may fail. section 5.5 section 9.9.3 section 5.8

A compact Q7 fixed-point value stores its bits in an `i8`. Converting an `f64` to Q7 scales the value and clamps inputs outside the supported range; converting back scales the stored integer down. Separate implementations handle each direction. Conversion need not preserve exact precision: representations of time can also lose accuracy when converted. section 5.5 section 9.9.3

Listing 5.12 Converting from f64 to Q7
 impl From<f64> for Q7 {
     fn from (n: f64) -> Self {
         // assert!(n >= -1.0);
         // assert!(n <= 1.0);
         if n >= 1.0 {                     #1
             Q7(127)
         } else if n <= -1.0 {             #1
             Q7(-128)
         } else {
             Q7((n * 128.0) as i8)
         }
     }
 }
 
 impl From<Q7> for f64 {
     fn from(n: Q7) -> f64 {
         (n.0 as f64) * 2_f64.powf(-7.0)   #2
     }
 }

Compare the two `impl From` blocks: the source and destination types switch places, and each `from` method performs its own calculation. section 5.5

`From` is also useful when a function can encounter several error types. Define a wrapper error enum with a variant for each upstream error, then implement `From` for each one. A function returning that wrapper can use `?` on both file and address-parsing operations without writing `map_err()` at every call. section 8.5.2 section 8.11

impl From<io::Error> for UpstreamError {
  fn from(error: io::Error) -> Self {
    UpstreamError::IO(error)
  }
}
 
impl From<net::AddrParseError> for UpstreamError {
  fn from(error: net::AddrParseError) -> Self {
    UpstreamError::Parsing(error)
  }
}

Each implementation puts one upstream error into its matching wrapper variant. section 8.5.2

How Rust in Action: Systems programming concepts and techniques covers it

How deep it goes
Works through bidirectional numeric implementations and separate error-wrapper implementations, including how the latter remove repeated map_err calls.
Examples
Shows Q7 conversions with f64 and f32, wrapper conversions for I/O and address-parsing errors, and NTP timestamp conversions.
What it assumes
Builds on Rust types, trait implementations, and Result-based error handling while introducing From through concrete implementations.
What you can do after
Build it from scratch by implementing From for numeric types or wrapper errors, then use from(), into(), or ? where appropriate.
How it connects
Connects From to Into, TryFrom, fixed-point numbers, error enums, Result, and the question-mark operator.

Also explained in

Compare how 4 books explain From trait →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Rust in Action: Systems programming concepts and techniques. The section links point to the parts of the book it draws on.