diff --git a/prost-types/src/datetime.rs b/prost-types/src/datetime.rs index 69bc10292..4c9467753 100644 --- a/prost-types/src/datetime.rs +++ b/prost-types/src/datetime.rs @@ -989,10 +989,7 @@ mod tests { let date_time = DateTime::from(timestamp); let roundtrip = Timestamp::try_from(date_time).unwrap(); - let mut normalized_timestamp = timestamp; - normalized_timestamp.normalize(); - - prop_assert_eq!(normalized_timestamp, roundtrip); + prop_assert_eq!(timestamp.normalized(), roundtrip); } #[test] diff --git a/prost-types/src/duration.rs b/prost-types/src/duration.rs index 42abc2385..3ce993ee5 100644 --- a/prost-types/src/duration.rs +++ b/prost-types/src/duration.rs @@ -58,6 +58,17 @@ impl Duration { // debug_assert!(self.seconds >= -315_576_000_000 && self.seconds <= 315_576_000_000, // "invalid duration: {:?}", self); } + + /// Returns a normalized copy of the duration to a canonical format. + /// + /// Based on [`google::protobuf::util::CreateNormalized`][1]. + /// + /// [1]: https://github.com/google/protobuf/blob/v3.3.2/src/google/protobuf/util/time_util.cc#L79-L100 + pub fn normalized(&self) -> Self { + let mut result = *self; + result.normalize(); + result + } } impl Name for Duration { @@ -77,9 +88,8 @@ impl TryFrom for Duration { let seconds = i64::try_from(duration.as_secs()).map_err(|_| DurationError::OutOfRange)?; let nanos = duration.subsec_nanos() as i32; - let mut duration = Duration { seconds, nanos }; - duration.normalize(); - Ok(duration) + let duration = Duration { seconds, nanos }; + Ok(duration.normalized()) } } @@ -105,8 +115,7 @@ impl TryFrom for time::Duration { impl fmt::Display for Duration { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut d = *self; - d.normalize(); + let d = self.normalized(); if self.seconds < 0 || self.nanos < 0 { write!(f, "-")?; } @@ -407,14 +416,13 @@ mod tests { ]; for case in cases.iter() { - let mut test_duration = Duration { + let test_duration = Duration { seconds: case.1, nanos: case.2, }; - test_duration.normalize(); assert_eq!( - test_duration, + test_duration.normalized(), Duration { seconds: case.3, nanos: case.4, diff --git a/prost-types/src/timestamp.rs b/prost-types/src/timestamp.rs index 813d9f883..1d7e609f4 100644 --- a/prost-types/src/timestamp.rs +++ b/prost-types/src/timestamp.rs @@ -62,6 +62,17 @@ impl Timestamp { } } + /// Return a normalized copy of the timestamp to a canonical format. + /// + /// Based on [`google::protobuf::util::CreateNormalized`][1]. + /// + /// [1]: https://github.com/google/protobuf/blob/v3.3.2/src/google/protobuf/util/time_util.cc#L59-L77 + pub fn normalized(&self) -> Self { + let mut result = *self; + result.normalize(); + result + } + /// Creates a new `Timestamp` at the start of the provided UTC date. pub fn date(year: i64, month: u8, day: u8) -> Result { Timestamp::date_time_nanos(year, month, day, 0, 0, 0, 0) @@ -399,14 +410,13 @@ mod tests { ]; for case in cases.iter() { - let mut test_timestamp = crate::Timestamp { + let test_timestamp = crate::Timestamp { seconds: case.1, nanos: case.2, }; - test_timestamp.normalize(); assert_eq!( - test_timestamp, + test_timestamp.normalized(), crate::Timestamp { seconds: case.3, nanos: case.4,