use std::cmp::Ordering; use libc::{c_char, c_int}; use crate::raw; use crate::util::Binding; /// Time in a signature #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub struct Time { raw: raw::git_time, } /// Time structure used in a git index entry. #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub struct IndexTime { raw: raw::git_index_time, } impl Time { /// Creates a new time structure from its components. pub fn new(time: i64, offset: i32) -> Time { unsafe { Binding::from_raw(raw::git_time { time: time as raw::git_time_t, offset: offset as c_int, sign: if offset < 0 { '-' } else { '+' } as c_char, }) } } /// Return the time, in seconds, from epoch pub fn seconds(&self) -> i64 { self.raw.time as i64 } /// Return the timezone offset, in minutes pub fn offset_minutes(&self) -> i32 { self.raw.offset as i32 } /// Return whether the offset was positive or negative. Primarily useful /// in case the offset is specified as a negative zero. pub fn sign(&self) -> char { self.raw.sign as u8 as char } } impl PartialOrd for Time { fn partial_cmp(&self, other: &Time) -> Option { Some(self.cmp(other)) } } impl Ord for Time { fn cmp(&self, other: &Time) -> Ordering { (self.raw.time, self.raw.offset).cmp(&(other.raw.time, other.raw.offset)) } } impl Binding for Time { type Raw = raw::git_time; unsafe fn from_raw(raw: raw::git_time) -> Time { Time { raw } } fn raw(&self) -> raw::git_time { self.raw } } impl IndexTime { /// Creates a new time structure from its components. pub fn new(seconds: i32, nanoseconds: u32) -> IndexTime { unsafe { Binding::from_raw(raw::git_index_time { seconds, nanoseconds, }) } } /// Returns the number of seconds in the second component of this time. pub fn seconds(&self) -> i32 { self.raw.seconds } /// Returns the nanosecond component of this time. pub fn nanoseconds(&self) -> u32 { self.raw.nanoseconds } } impl Binding for IndexTime { type Raw = raw::git_index_time; unsafe fn from_raw(raw: raw::git_index_time) -> IndexTime { IndexTime { raw } } fn raw(&self) -> raw::git_index_time { self.raw } } impl PartialOrd for IndexTime { fn partial_cmp(&self, other: &IndexTime) -> Option { Some(self.cmp(other)) } } impl Ord for IndexTime { fn cmp(&self, other: &IndexTime) -> Ordering { let me = (self.raw.seconds, self.raw.nanoseconds); let other = (other.raw.seconds, other.raw.nanoseconds); me.cmp(&other) } } #[cfg(test)] mod tests { use crate::Time; #[test] fn smoke() { assert_eq!(Time::new(1608839587, -300).seconds(), 1608839587); assert_eq!(Time::new(1608839587, -300).offset_minutes(), -300); assert_eq!(Time::new(1608839587, -300).sign(), '-'); assert_eq!(Time::new(1608839587, 300).sign(), '+'); } }