gix_date/parse/
mod.rs

1use std::str::FromStr;
2
3use smallvec::SmallVec;
4
5use crate::Time;
6
7#[derive(thiserror::Error, Debug, Clone)]
8#[allow(missing_docs)]
9pub enum Error {
10    #[error("Could not convert a duration into a date")]
11    RelativeTimeConversion,
12    #[error("Date string can not be parsed")]
13    InvalidDateString { input: String },
14    #[error("The heat-death of the universe happens before this date")]
15    InvalidDate(#[from] std::num::TryFromIntError),
16    #[error("Current time is missing but required to handle relative dates.")]
17    MissingCurrentTime,
18}
19
20/// A container for just enough bytes to hold the largest-possible [`time`](Time) instance.
21/// It's used in conjunction with
22#[derive(Default, Clone)]
23pub struct TimeBuf {
24    buf: SmallVec<[u8; Time::MAX.size()]>,
25}
26
27impl TimeBuf {
28    /// Represent this instance as standard string, serialized in a format compatible with
29    /// signature fields in Git commits, also known as anything parseable as [raw format](function::parse_header()).
30    pub fn as_str(&self) -> &str {
31        // SAFETY: We know that serialized times are pure ASCII, a subset of UTF-8.
32        //         `buf` and `len` are written only by time-serialization code.
33        let time_bytes = self.buf.as_slice();
34        #[allow(unsafe_code)]
35        unsafe {
36            std::str::from_utf8_unchecked(time_bytes)
37        }
38    }
39
40    /// Clear the previous content.
41    fn clear(&mut self) {
42        self.buf.clear();
43    }
44}
45
46impl std::io::Write for TimeBuf {
47    fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
48        self.buf.write(buf)
49    }
50
51    fn flush(&mut self) -> std::io::Result<()> {
52        self.buf.flush()
53    }
54}
55
56impl Time {
57    /// Serialize this instance into `buf`, exactly as it would appear in the header of a Git commit,
58    /// and return `buf` as `&str` for easy consumption.
59    pub fn to_str<'a>(&self, buf: &'a mut TimeBuf) -> &'a str {
60        buf.clear();
61        self.write_to(buf)
62            .expect("write to memory of just the right size cannot fail");
63        buf.as_str()
64    }
65}
66
67impl FromStr for Time {
68    type Err = Error;
69
70    fn from_str(s: &str) -> Result<Self, Self::Err> {
71        crate::parse_header(s).ok_or_else(|| Error::InvalidDateString { input: s.into() })
72    }
73}
74
75pub(crate) mod function;
76mod git;
77mod raw;
78mod relative;