gix_date/time/
write.rs

1use bstr::BString;
2
3use crate::{time::Sign, Time};
4
5/// Serialization with standard `git` format
6impl Time {
7    /// Serialize this instance into memory, similar to what [`write_to()`][Self::write_to()] would do with arbitrary `Write` implementations.
8    ///
9    /// # Panics
10    ///
11    /// If the underlying call fails as this instance can't be represented, typically due to an invalid offset.
12    pub fn to_bstring(&self) -> BString {
13        let mut buf = Vec::with_capacity(64);
14        self.write_to(&mut buf).expect("write to memory cannot fail");
15        buf.into()
16    }
17
18    /// Serialize this instance to `out` in a format suitable for use in header fields of serialized git commits or tags.
19    pub fn write_to(&self, out: &mut dyn std::io::Write) -> std::io::Result<()> {
20        const SECONDS_PER_HOUR: u32 = 60 * 60;
21        let offset = self.offset.unsigned_abs();
22        let hours = offset / SECONDS_PER_HOUR;
23        let minutes = (offset - (hours * SECONDS_PER_HOUR)) / 60;
24
25        if hours > 99 {
26            return Err(std::io::Error::new(
27                std::io::ErrorKind::Other,
28                "Cannot represent offsets larger than +-9900",
29            ));
30        }
31
32        let mut itoa = itoa::Buffer::new();
33        out.write_all(itoa.format(self.seconds).as_bytes())?;
34        out.write_all(b" ")?;
35        out.write_all(match self.sign {
36            Sign::Plus => b"+",
37            Sign::Minus => b"-",
38        })?;
39
40        const ZERO: &[u8; 1] = b"0";
41
42        if hours < 10 {
43            out.write_all(ZERO)?;
44        }
45        out.write_all(itoa.format(hours).as_bytes())?;
46
47        if minutes < 10 {
48            out.write_all(ZERO)?;
49        }
50        out.write_all(itoa.format(minutes).as_bytes()).map(|_| ())
51    }
52
53    /// Computes the number of bytes necessary to write it using [`Time::write_to()`].
54    pub fn size(&self) -> usize {
55        (if self.seconds >= 1_000_000_000_000_000_000 {
56            19
57        } else if self.seconds >= 100_000_000_000_000_000 {
58            18
59        } else if self.seconds >= 10_000_000_000_000_000 {
60            17
61        } else if self.seconds >= 1_000_000_000_000_000 {
62            16
63        } else if self.seconds >= 100_000_000_000_000 {
64            15
65        } else if self.seconds >= 10_000_000_000_000 {
66            14
67        } else if self.seconds >= 1_000_000_000_000 {
68            13
69        } else if self.seconds >= 100_000_000_000 {
70            12
71        } else if self.seconds >= 10_000_000_000 {
72            11
73        } else if self.seconds >= 1_000_000_000 {
74            10
75        } else if self.seconds >= 100_000_000 {
76            9
77        } else if self.seconds >= 10_000_000 {
78            8
79        } else if self.seconds >= 1_000_000 {
80            7
81        } else if self.seconds >= 100_000 {
82            6
83        } else if self.seconds >= 10_000 {
84            5
85        } else if self.seconds >= 1_000 {
86            4
87        } else if self.seconds >= 100 {
88            3
89        } else if self.seconds >= 10 {
90            2
91        } else if self.seconds >= 0 {
92            1
93            // from here, it's sign + num-digits characters
94        } else if self.seconds >= -10 {
95            2
96        } else if self.seconds >= -100 {
97            3
98        } else if self.seconds >= -1_000 {
99            4
100        } else if self.seconds >= -10_000 {
101            5
102        } else if self.seconds >= -100_000 {
103            6
104        } else if self.seconds >= -1_000_000 {
105            7
106        } else if self.seconds >= -10_000_000 {
107            8
108        } else if self.seconds >= -100_000_000 {
109            9
110        } else if self.seconds >= -1_000_000_000 {
111            10
112        } else if self.seconds >= -10_000_000_000 {
113            11
114        } else if self.seconds >= -100_000_000_000 {
115            12
116        } else if self.seconds >= -1_000_000_000_000 {
117            13
118        } else if self.seconds >= -10_000_000_000_000 {
119            14
120        } else if self.seconds >= -100_000_000_000_000 {
121            15
122        } else if self.seconds >= -1_000_000_000_000_000 {
123            16
124        } else if self.seconds >= -10_000_000_000_000_000 {
125            17
126        } else if self.seconds >= -100_000_000_000_000_000 {
127            18
128        } else if self.seconds >= -1_000_000_000_000_000_000 {
129            19
130        } else {
131            20
132        }) + 2 /*space + offset sign*/ + 2 /*offset hours*/ + 2 /*offset minutes*/
133    }
134}