gix_object/commit/
write.rs

1use std::io;
2
3use bstr::ByteSlice;
4
5use crate::{encode, encode::NL, Commit, CommitRef, Kind};
6
7impl crate::WriteTo for Commit {
8    /// Serializes this instance to `out` in the git serialization format.
9    fn write_to(&self, mut out: &mut dyn io::Write) -> io::Result<()> {
10        encode::trusted_header_id(b"tree", &self.tree, &mut out)?;
11        for parent in &self.parents {
12            encode::trusted_header_id(b"parent", parent, &mut out)?;
13        }
14        encode::trusted_header_signature(b"author", &self.author.to_ref(), &mut out)?;
15        encode::trusted_header_signature(b"committer", &self.committer.to_ref(), &mut out)?;
16        if let Some(encoding) = self.encoding.as_ref() {
17            encode::header_field(b"encoding", encoding, &mut out)?;
18        }
19        for (name, value) in &self.extra_headers {
20            encode::header_field_multi_line(name, value, &mut out)?;
21        }
22        out.write_all(NL)?;
23        out.write_all(&self.message)
24    }
25
26    fn kind(&self) -> Kind {
27        Kind::Commit
28    }
29
30    fn size(&self) -> u64 {
31        let hash_in_hex = self.tree.kind().len_in_hex();
32        (b"tree".len() + 1 /*space*/ + hash_in_hex + 1 /* nl */
33        + self.parents.iter().count() * (b"parent".len() + 1 + hash_in_hex + 1)
34            + b"author".len() + 1 /* space */ + self.author.size() + 1 /* nl */
35            + b"committer".len() + 1 /* space */ + self.committer.size() + 1 /* nl */
36            + self
37                .encoding
38                .as_ref()
39                .map_or(0, |e| b"encoding".len() + 1 /* space */ + e.len() + 1 /* nl */)
40            + self
41                .extra_headers
42                .iter()
43                .map(|(name, value)| {
44                    // each header *value* is preceded by a space, and it starts right after the name.
45                    name.len() + value.lines_with_terminator().map(|s| s.len() + 1).sum::<usize>() + usize::from(!value.ends_with_str(b"\n"))
46                })
47                .sum::<usize>()
48            + 1 /* nl */
49            + self.message.len()) as u64
50    }
51}
52
53impl crate::WriteTo for CommitRef<'_> {
54    /// Serializes this instance to `out` in the git serialization format.
55    fn write_to(&self, mut out: &mut dyn io::Write) -> io::Result<()> {
56        encode::trusted_header_id(b"tree", &self.tree(), &mut out)?;
57        for parent in self.parents() {
58            encode::trusted_header_id(b"parent", &parent, &mut out)?;
59        }
60        encode::trusted_header_signature(b"author", &self.author, &mut out)?;
61        encode::trusted_header_signature(b"committer", &self.committer, &mut out)?;
62        if let Some(encoding) = self.encoding.as_ref() {
63            encode::header_field(b"encoding", encoding, &mut out)?;
64        }
65        for (name, value) in &self.extra_headers {
66            encode::header_field_multi_line(name, value, &mut out)?;
67        }
68        out.write_all(NL)?;
69        out.write_all(self.message)
70    }
71
72    fn kind(&self) -> Kind {
73        Kind::Commit
74    }
75
76    fn size(&self) -> u64 {
77        let hash_in_hex = self.tree().kind().len_in_hex();
78        (b"tree".len() + 1 /* space */ + hash_in_hex + 1 /* nl */
79            + self.parents.iter().count() * (b"parent".len() + 1 /* space */ + hash_in_hex + 1 /* nl */)
80            + b"author".len() + 1 /* space */ + self.author.size() + 1 /* nl */
81            + b"committer".len() + 1 /* space */ + self.committer.size() + 1 /* nl */
82            + self
83                .encoding
84                .as_ref()
85                .map_or(0, |e| b"encoding".len() + 1 /* space */ + e.len() + 1 /* nl */)
86            + self
87                .extra_headers
88                .iter()
89                .map(|(name, value)| {
90                    // each header *value* is preceded by a space, and it starts right after the name.
91                    name.len() + value.lines_with_terminator().map(|s| s.len() + 1).sum::<usize>() + usize::from(!value.ends_with_str(b"\n"))
92                })
93                .sum::<usize>()
94            + 1 /* nl */
95            + self.message.len()) as u64
96    }
97}