liveBook · Manning

Data conversion

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

A type cast is an explicit conversion of a value from one data type to another.

Rust does not automatically convert one numeric type to another, even when both hold integers. If two values have different types, you must make the conversion explicit before comparing them. A type cast uses `as`, as in `b as i32`. section 2.3.1 section 2.3.3

Make a comparison compile

With `let a: i32 = 10;` and `let b: u16 = 100;`, `a < b` does not compile. Write `a < (b as i32)` to convert `b` for the comparison. Casting the smaller type to a larger one is generally safer than converting in the other direction. section 2.3.3

A cast is not a guarantee that the original value will be preserved: `300_i32 as i8` produces `44`. When a conversion might fail, `try_into()` offers a different route; it returns a `Result` containing either a converted value or an error. The example brings `std::convert::TryInto` into scope before calling the method. section 2.3.3

Listing 2.5 The try_into() method converts between types
 use std::convert::TryInto;    #1
 
 fn main() {
   let a: i32 = 10;
   let b: u16 = 100;
 
   let b_ = b.try_into()
             .unwrap();        #2
 
   if a < b_ {
     println!("Ten is less than one hundred.");
   }
 }

Compare the `try_into()` call with the direct `as` cast above; the listing shows the conversion before the comparison. section 2.3.3

Conversions also arise between representations, not just integer widths. Converting an NTP timestamp to a `chrono::DateTime` adjusts for different epochs and translates the fractional second. Because the representations have different precision, some accuracy may be lost. Implementing `From` defines such a conversion and normally makes the reciprocal `Into` implementation available automatically. section 9.9.3

Listing 9.14 Converting between chrono::DateTime and NTP timestamps
19 const NTP_TO_UNIX_SECONDS: i64 = 2_208_988_800;        #1
22 #[derive(Default,Debug,Copy,Clone)]
23 struct NTPTimestamp {                                  #2
24   seconds: u32,                                        #2
25   fraction: u32,                                       #2
26 }
                                                  #2
52  impl From<NTPTimestamp> for DateTime<Utc> {
53    fn from(ntp: NTPTimestamp) -> Self {
54     let secs = ntp.seconds as i64 - NTP_TO_UNIX_SECONDS;
55     let mut nanos = ntp.fraction as f64;
56     nanos *= 1e9;                                      #3
57     nanos /= 2_f64.powi(32);                           #3
58  
59     Utc.timestamp(secs, nanos as u32)
60   }
61 }
62  
63 impl From<DateTime<Utc>> for NTPTimestamp {
64   fn from(utc: DateTime<Utc>) -> Self {
65     let secs = utc.timestamp() + NTP_TO_UNIX_SECONDS;
66     let mut fraction = utc.nanosecond() as f64;
67     fraction *= 2_f64.powi(32);                        #3
68     fraction /= 1e9;                                   #3
69  
70     NTPTimestamp {
71       seconds: secs as u32,
72       fraction: fraction as u32,
73     }
74   }
75 }

The timestamp implementation shows an epoch offset, numeric casts, and fractional-second arithmetic inside a `From` conversion. section 9.9.3

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

How deep it goes
Works through `as` and `try_into()`, then shows `From` implementations; defers a full explanation of traits and error handling.
Examples
Uses an `i32`–`u16` comparison, a `300_i32 as i8` cast, and NTP-to-`chrono::DateTime` conversion.
What it assumes
Assumes basic numeric expressions; introduces traits and `Result` briefly rather than fully explaining them.
What you can do after
Apply it via `as` or `try_into()` for numeric conversion, and build it from scratch with `From` for a timestamp representation.
How it connects
Links type casts to numeric types, comparisons, `Result`, conversion traits, timestamp epochs, and precision loss.

Also explained in

Compare how 21 books explain data conversion →

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.