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