1 use std::cmp::Ordering; 2 3 use libc::{c_char, c_int}; 4 5 use crate::raw; 6 use crate::util::Binding; 7 8 /// Time in a signature 9 #[derive(Copy, Clone, Debug, Eq, PartialEq)] 10 pub struct Time { 11 raw: raw::git_time, 12 } 13 14 /// Time structure used in a git index entry. 15 #[derive(Copy, Clone, Debug, Eq, PartialEq)] 16 pub struct IndexTime { 17 raw: raw::git_index_time, 18 } 19 20 impl Time { 21 /// Creates a new time structure from its components. new(time: i64, offset: i32) -> Time22 pub fn new(time: i64, offset: i32) -> Time { 23 unsafe { 24 Binding::from_raw(raw::git_time { 25 time: time as raw::git_time_t, 26 offset: offset as c_int, 27 sign: if offset < 0 { '-' } else { '+' } as c_char, 28 }) 29 } 30 } 31 32 /// Return the time, in seconds, from epoch seconds(&self) -> i6433 pub fn seconds(&self) -> i64 { 34 self.raw.time as i64 35 } 36 37 /// Return the timezone offset, in minutes offset_minutes(&self) -> i3238 pub fn offset_minutes(&self) -> i32 { 39 self.raw.offset as i32 40 } 41 42 /// Return whether the offset was positive or negative. Primarily useful 43 /// in case the offset is specified as a negative zero. sign(&self) -> char44 pub fn sign(&self) -> char { 45 self.raw.sign as u8 as char 46 } 47 } 48 49 impl PartialOrd for Time { partial_cmp(&self, other: &Time) -> Option<Ordering>50 fn partial_cmp(&self, other: &Time) -> Option<Ordering> { 51 Some(self.cmp(other)) 52 } 53 } 54 55 impl Ord for Time { cmp(&self, other: &Time) -> Ordering56 fn cmp(&self, other: &Time) -> Ordering { 57 (self.raw.time, self.raw.offset).cmp(&(other.raw.time, other.raw.offset)) 58 } 59 } 60 61 impl Binding for Time { 62 type Raw = raw::git_time; from_raw(raw: raw::git_time) -> Time63 unsafe fn from_raw(raw: raw::git_time) -> Time { 64 Time { raw } 65 } raw(&self) -> raw::git_time66 fn raw(&self) -> raw::git_time { 67 self.raw 68 } 69 } 70 71 impl IndexTime { 72 /// Creates a new time structure from its components. new(seconds: i32, nanoseconds: u32) -> IndexTime73 pub fn new(seconds: i32, nanoseconds: u32) -> IndexTime { 74 unsafe { 75 Binding::from_raw(raw::git_index_time { 76 seconds, 77 nanoseconds, 78 }) 79 } 80 } 81 82 /// Returns the number of seconds in the second component of this time. seconds(&self) -> i3283 pub fn seconds(&self) -> i32 { 84 self.raw.seconds 85 } 86 /// Returns the nanosecond component of this time. nanoseconds(&self) -> u3287 pub fn nanoseconds(&self) -> u32 { 88 self.raw.nanoseconds 89 } 90 } 91 92 impl Binding for IndexTime { 93 type Raw = raw::git_index_time; from_raw(raw: raw::git_index_time) -> IndexTime94 unsafe fn from_raw(raw: raw::git_index_time) -> IndexTime { 95 IndexTime { raw } 96 } raw(&self) -> raw::git_index_time97 fn raw(&self) -> raw::git_index_time { 98 self.raw 99 } 100 } 101 102 impl PartialOrd for IndexTime { partial_cmp(&self, other: &IndexTime) -> Option<Ordering>103 fn partial_cmp(&self, other: &IndexTime) -> Option<Ordering> { 104 Some(self.cmp(other)) 105 } 106 } 107 108 impl Ord for IndexTime { cmp(&self, other: &IndexTime) -> Ordering109 fn cmp(&self, other: &IndexTime) -> Ordering { 110 let me = (self.raw.seconds, self.raw.nanoseconds); 111 let other = (other.raw.seconds, other.raw.nanoseconds); 112 me.cmp(&other) 113 } 114 } 115 116 #[cfg(test)] 117 mod tests { 118 use crate::Time; 119 120 #[test] smoke()121 fn smoke() { 122 assert_eq!(Time::new(1608839587, -300).seconds(), 1608839587); 123 assert_eq!(Time::new(1608839587, -300).offset_minutes(), -300); 124 assert_eq!(Time::new(1608839587, -300).sign(), '-'); 125 assert_eq!(Time::new(1608839587, 300).sign(), '+'); 126 } 127 } 128