#![doc(html_root_url = "https://docs.rs/prost-types/0.7.0")]
#![cfg_attr(not(feature = "std"), no_std)]
use core::convert::TryFrom;
use core::i32;
use core::i64;
use core::time;
include!("protobuf.rs");
pub mod compiler {
include!("compiler.rs");
}
const NANOS_PER_SECOND: i32 = 1_000_000_000;
impl Duration {
pub fn normalize(&mut self) {
if self.nanos <= -NANOS_PER_SECOND || self.nanos >= NANOS_PER_SECOND {
self.seconds += (self.nanos / NANOS_PER_SECOND) as i64;
self.nanos %= NANOS_PER_SECOND;
}
if self.seconds < 0 && self.nanos > 0 {
self.seconds += 1;
self.nanos -= NANOS_PER_SECOND;
} else if self.seconds > 0 && self.nanos < 0 {
self.seconds -= 1;
self.nanos += NANOS_PER_SECOND;
}
}
}
impl From<time::Duration> for Duration {
fn from(duration: time::Duration) -> Duration {
let seconds = duration.as_secs();
let seconds = if seconds > i64::MAX as u64 {
i64::MAX
} else {
seconds as i64
};
let nanos = duration.subsec_nanos();
let nanos = if nanos > i32::MAX as u32 {
i32::MAX
} else {
nanos as i32
};
let mut duration = Duration { seconds, nanos };
duration.normalize();
duration
}
}
impl TryFrom<Duration> for time::Duration {
type Error = time::Duration;
fn try_from(mut duration: Duration) -> Result<time::Duration, time::Duration> {
duration.normalize();
if duration.seconds >= 0 {
Ok(time::Duration::new(
duration.seconds as u64,
duration.nanos as u32,
))
} else {
Err(time::Duration::new(
(-duration.seconds) as u64,
(-duration.nanos) as u32,
))
}
}
}
impl Timestamp {
#[cfg(feature = "std")]
pub fn normalize(&mut self) {
if self.nanos <= -NANOS_PER_SECOND || self.nanos >= NANOS_PER_SECOND {
self.seconds += (self.nanos / NANOS_PER_SECOND) as i64;
self.nanos %= NANOS_PER_SECOND;
}
if self.nanos < 0 {
self.seconds -= 1;
self.nanos += NANOS_PER_SECOND;
}
}
}
#[cfg(feature = "std")]
impl From<std::time::SystemTime> for Timestamp {
fn from(system_time: std::time::SystemTime) -> Timestamp {
let (seconds, nanos) = match system_time.duration_since(std::time::UNIX_EPOCH) {
Ok(duration) => {
let seconds = i64::try_from(duration.as_secs()).unwrap();
(seconds, duration.subsec_nanos() as i32)
}
Err(error) => {
let duration = error.duration();
let seconds = i64::try_from(duration.as_secs()).unwrap();
let nanos = duration.subsec_nanos() as i32;
if nanos == 0 {
(-seconds, 0)
} else {
(-seconds - 1, 1_000_000_000 - nanos)
}
}
};
Timestamp { seconds, nanos }
}
}
#[cfg(feature = "std")]
impl From<Timestamp> for std::time::SystemTime {
fn from(mut timestamp: Timestamp) -> std::time::SystemTime {
timestamp.normalize();
let system_time = if timestamp.seconds >= 0 {
std::time::UNIX_EPOCH + time::Duration::from_secs(timestamp.seconds as u64)
} else {
std::time::UNIX_EPOCH - time::Duration::from_secs((-timestamp.seconds) as u64)
};
system_time + time::Duration::from_nanos(timestamp.nanos as u64)
}
}
#[cfg(test)]
mod tests {
use std::time::{Duration, SystemTime, UNIX_EPOCH};
use proptest::prelude::*;
use super::*;
#[cfg(feature = "std")]
proptest! {
#[test]
fn check_system_time_roundtrip(
system_time in SystemTime::arbitrary(),
) {
prop_assert_eq!(SystemTime::from(Timestamp::from(system_time)), system_time);
}
}
#[cfg(feature = "std")]
#[test]
fn check_timestamp_negative_seconds() {
assert_eq!(
Timestamp::from(UNIX_EPOCH - Duration::new(1_001, 0)),
Timestamp {
seconds: -1_001,
nanos: 0
}
);
assert_eq!(
Timestamp::from(UNIX_EPOCH - Duration::new(0, 999_999_900)),
Timestamp {
seconds: -1,
nanos: 100
}
);
assert_eq!(
Timestamp::from(UNIX_EPOCH - Duration::new(2_001_234, 12_300)),
Timestamp {
seconds: -2_001_235,
nanos: 999_987_700
}
);
assert_eq!(
Timestamp::from(UNIX_EPOCH - Duration::new(768, 65_432_100)),
Timestamp {
seconds: -769,
nanos: 934_567_900
}
);
}
#[cfg(all(unix, feature = "std"))]
#[test]
fn check_timestamp_negative_seconds_1ns() {
assert_eq!(
Timestamp::from(UNIX_EPOCH - Duration::new(0, 999_999_999)),
Timestamp {
seconds: -1,
nanos: 1
}
);
assert_eq!(
Timestamp::from(UNIX_EPOCH - Duration::new(1_234_567, 123)),
Timestamp {
seconds: -1_234_568,
nanos: 999_999_877
}
);
assert_eq!(
Timestamp::from(UNIX_EPOCH - Duration::new(890, 987_654_321)),
Timestamp {
seconds: -891,
nanos: 12_345_679
}
);
}
}