Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is an idiomatic Rust way to format a value to multiple kinds of strings?

Tags:

rust

I have latitude in degrees in the form of a f64 and I need to convert it into a String. At first I thought about implementing Display, like this:

struct Latitude(f64);

impl fmt::Display for Latitude {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} {}", if self.0 > 0. { "N" } else { "S" }, self.0)
    }
}

fn main() {
    let lat: f64 = 45.;
    println!("{}", Latitude(lat));
}

After that, I have additional requirements. I need convert to one of two representations:

  1. N 70.152351
  2. N 70° 09' 08"

There is also an additional flag; when it is false, I need something like:

  1. - --.------
  2. - --° -' -"

The most simple way to implement this will be:

fn format_lat(degree: f64, use_min_sec_variant: bool, is_valid: bool) -> String;

However, I don't see any free functions in the Rust standard library.

Maybe I should use struct Latitude(f64) and implement a to_string method? Or maybe I should implement some other trait?

like image 796
user1244932 Avatar asked Dec 18 '22 14:12

user1244932


2 Answers

You can create wrapper types with different types of formatting and return them as a method:

struct Latitude(f64);
struct MinutesSeconds(f64);

impl Latitude {
    fn minutes_seconds(&self) -> MinutesSeconds {
        MinutesSeconds(self.0)
    }
}

impl fmt::Display for MinutesSeconds {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "latitude in a different format")
    }
}

This is the same idea as Path::display.

As for the valid / invalid concept, it sounds like you really want a struct Latitude(Option<f64>) and then provide None when it is invalid.

like image 128
Shepmaster Avatar answered Jun 15 '23 16:06

Shepmaster


Basically you're free to do what you want. Without more context on your goals, any method seems good enough for me.

Personally I'd do it as:

struct Latitude(f64);

impl Latitutde {
    pub fn format_as_x(&self, f: &mut fmt::Formatter) -> fmt::Result<(), Error> {}

    pub fn format_as_y(&self, f: &mut fmt::Formatter) -> fmt::Result<(), Error> {}
}

plus a Display trait + to_format_x() -> String convenience functions.

format_as_y are IMO best method since they handle errors, can take any formatter and don't need to allocate a String to return.

By the way, taking bool arguments is usually an anti-pattern: boolean trap.

like image 45
dpc.pw Avatar answered Jun 15 '23 15:06

dpc.pw