• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use std::f64;
2 
3 #[derive(Debug)]
4 pub enum ProtobufFloatParseError {
5     EmptyString,
6     CannotParseFloat,
7 }
8 
9 pub type ProtobufFloatParseResult<T> = Result<T, ProtobufFloatParseError>;
10 
11 pub const PROTOBUF_NAN: &str = "nan";
12 pub const PROTOBUF_INF: &str = "inf";
13 
14 /// Format float as in protobuf `.proto` files
format_protobuf_float(f: f64) -> String15 pub fn format_protobuf_float(f: f64) -> String {
16     if f.is_nan() {
17         PROTOBUF_NAN.to_owned()
18     } else if f.is_infinite() {
19         if f > 0.0 {
20             format!("{}", PROTOBUF_INF)
21         } else {
22             format!("-{}", PROTOBUF_INF)
23         }
24     } else {
25         let i = f as i64;
26         if i as f64 == f {
27             // Older rust versions did print float without `.0` suffix
28             format!("{:?}.0", i)
29         } else {
30             // TODO: make sure doesn't lose precision
31             format!("{:?}", f)
32         }
33     }
34 }
35 
36 /// Parse float from `.proto` format
parse_protobuf_float(s: &str) -> ProtobufFloatParseResult<f64>37 pub fn parse_protobuf_float(s: &str) -> ProtobufFloatParseResult<f64> {
38     if s.is_empty() {
39         return Err(ProtobufFloatParseError::EmptyString);
40     }
41     if s == PROTOBUF_NAN {
42         return Ok(f64::NAN);
43     }
44     if s == PROTOBUF_INF || s == format!("+{}", PROTOBUF_INF) {
45         return Ok(f64::INFINITY);
46     }
47     if s == format!("-{}", PROTOBUF_INF) {
48         return Ok(f64::NEG_INFINITY);
49     }
50     match s.parse() {
51         Ok(f) => Ok(f),
52         Err(_) => Err(ProtobufFloatParseError::CannotParseFloat),
53     }
54 }
55 
56 #[cfg(test)]
57 mod test {
58     use super::*;
59 
60     #[test]
test_format_protobuf_float()61     fn test_format_protobuf_float() {
62         assert_eq!("10.0", format_protobuf_float(10.0));
63         assert_eq!("-10.0", format_protobuf_float(-10.0));
64         assert_eq!("10.5", format_protobuf_float(10.5));
65         assert_eq!("-10.5", format_protobuf_float(-10.5));
66     }
67 }
68