Skip to content

Commit

Permalink
well_known_types::Timestamp utilities
Browse files Browse the repository at this point in the history
  • Loading branch information
stepancheg committed Apr 12, 2020
1 parent 8431dea commit 655adb7
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 0 deletions.
5 changes: 5 additions & 0 deletions protobuf/src/cached_size.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ pub struct CachedSize {
}

impl CachedSize {
/// Default value for cached size.
pub const INIT: CachedSize = CachedSize {
size: AtomicUsize::new(0),
};

/// Get cached size
pub fn get(&self) -> u32 {
self.size.load(Ordering::Relaxed) as u32
Expand Down
1 change: 1 addition & 0 deletions protobuf/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ pub mod plugin;
pub mod rustproto;

mod any;
mod timestamp;

mod clear;
mod core;
Expand Down
112 changes: 112 additions & 0 deletions protobuf/src/timestamp.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
use crate::cached_size::CachedSize;
use crate::well_known_types::Timestamp;
use crate::UnknownFields;
use std::time::{Duration, SystemTime};

impl Timestamp {
/// Unix epoch value of timestamp.
pub const UNIX_EPOCH: Timestamp = Timestamp {
seconds: 0,
nanos: 0,
unknown_fields: UnknownFields::INIT,
cached_size: CachedSize::INIT,
};
}

/// Convert from [`Timestamp`].
///
/// # Panics
///
/// This function panics if given `SystemTime` is outside of `Timestamp` range.
impl From<SystemTime> for Timestamp {
fn from(time: SystemTime) -> Self {
match time.duration_since(SystemTime::UNIX_EPOCH) {
Ok(since_epoch) => Timestamp {
seconds: since_epoch.as_secs() as i64,
nanos: since_epoch.subsec_nanos() as i32,
..Default::default()
},
Err(e) => {
let before_epoch = e.duration();
Timestamp {
seconds: -(before_epoch.as_secs() as i64)
- (before_epoch.subsec_nanos() != 0) as i64,
nanos: (1_000_000_000 - before_epoch.subsec_nanos() as i32) % 1_000_000_000,
..Default::default()
}
}
}
}
}

/// Convert into [`SystemTime`].
///
/// The conversion could be lossy if `SystemTime` precision is smaller than nanoseconds.
///
/// # Panics
///
/// This function panics:
/// * if given `Timestamp` is outside of `SystemTime` range
/// * if `Timestamp` is malformed
impl Into<SystemTime> for Timestamp {
fn into(self) -> SystemTime {
if self.seconds >= 0 {
let duration =
Duration::from_secs(self.seconds as u64) + Duration::from_nanos(self.nanos as u64);
SystemTime::UNIX_EPOCH + duration
} else {
let duration =
Duration::from_secs(-self.seconds as u64) - Duration::from_nanos(self.nanos as u64);
SystemTime::UNIX_EPOCH - duration
}
}
}

#[cfg(test)]
mod test {
use crate::well_known_types::Timestamp;
use std::time::Duration;
use std::time::SystemTime;

#[test]
fn from_system_time() {
fn to_from(timestamp: Timestamp, system_time: SystemTime) {
assert_eq!(timestamp, Timestamp::from(system_time));
assert_eq!(system_time, Into::<SystemTime>::into(timestamp));
}

to_from(Timestamp::UNIX_EPOCH, SystemTime::UNIX_EPOCH);
to_from(
Timestamp {
seconds: 0,
nanos: 200_000_000,
..Default::default()
},
SystemTime::UNIX_EPOCH + Duration::from_millis(200),
);
to_from(
Timestamp {
seconds: 3,
nanos: 200_000_000,
..Default::default()
},
SystemTime::UNIX_EPOCH + Duration::from_millis(3_200),
);
to_from(
Timestamp {
seconds: -1,
nanos: 800_000_000,
..Default::default()
},
SystemTime::UNIX_EPOCH - Duration::from_millis(200),
);
to_from(
Timestamp {
seconds: -4,
nanos: 800_000_000,
..Default::default()
},
SystemTime::UNIX_EPOCH - Duration::from_millis(3_200),
);
}
}
5 changes: 5 additions & 0 deletions protobuf/src/unknown.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,11 @@ pub struct UnknownFields {
fields: Option<Box<HashMap<u32, UnknownValues>>>,
}

impl UnknownFields {
/// Field initializer.
pub const INIT: UnknownFields = UnknownFields { fields: None };
}

/// Very simple hash implementation of `Hash` for `UnknownFields`.
/// Since map is unordered, we cannot put entry hashes into hasher,
/// instead we summing hashes of entries.
Expand Down

0 comments on commit 655adb7

Please sign in to comment.