1use gix_error::validation;
2use std::io;
3
4use bstr::ByteSlice;
5
6use crate::{
7 Kind, Tree, TreeRef,
8 encode::SPACE,
9 tree::{Entry, EntryRef},
10};
11
12impl crate::WriteTo for Tree {
14 fn write_to(&self, out: &mut dyn io::Write) -> io::Result<()> {
18 debug_assert_eq!(
19 &self.entries,
20 &{
21 let mut entries_sorted = self.entries.clone();
22 entries_sorted.sort();
23 entries_sorted
24 },
25 "entries for serialization must be sorted by filename"
26 );
27 let mut buf = Default::default();
28 for Entry { mode, filename, oid } in &self.entries {
29 out.write_all(mode.as_bytes(&mut buf))?;
30 out.write_all(SPACE)?;
31
32 if filename.find_byte(0).is_some() {
33 return Err(io::Error::other(
34 validation("Nullbytes are invalid in file paths as they are separators")
35 .with_input(filename.as_bstr()),
36 ));
37 }
38 out.write_all(filename)?;
39 out.write_all(b"\0")?;
40
41 out.write_all(oid.as_bytes())?;
42 }
43 Ok(())
44 }
45
46 fn kind(&self) -> Kind {
47 Kind::Tree
48 }
49
50 fn size(&self) -> u64 {
51 let mut buf = Default::default();
52 self.entries
53 .iter()
54 .map(|Entry { mode, filename, oid }| {
55 (mode.as_bytes(&mut buf).len() + 1 + filename.len() + 1 + oid.as_bytes().len()) as u64
56 })
57 .sum()
58 }
59}
60
61impl crate::WriteTo for TreeRef<'_> {
63 fn write_to(&self, out: &mut dyn io::Write) -> io::Result<()> {
67 debug_assert_eq!(
68 &{
69 let mut entries_sorted = self.entries.clone();
70 entries_sorted.sort();
71 entries_sorted
72 },
73 &self.entries,
74 "entries for serialization must be sorted by filename"
75 );
76 let mut buf = Default::default();
77 for EntryRef { mode, filename, oid } in &self.entries {
78 out.write_all(mode.as_bytes(&mut buf))?;
79 out.write_all(SPACE)?;
80
81 if filename.find_byte(0).is_some() {
82 return Err(io::Error::other(
83 validation("Nullbytes are invalid in file paths as they are separators").with_input(*filename),
84 ));
85 }
86 out.write_all(filename)?;
87 out.write_all(b"\0")?;
88
89 out.write_all(oid.as_bytes())?;
90 }
91 Ok(())
92 }
93
94 fn kind(&self) -> Kind {
95 Kind::Tree
96 }
97
98 fn size(&self) -> u64 {
99 let mut buf = Default::default();
100 self.entries
101 .iter()
102 .map(|EntryRef { mode, filename, oid }| {
103 (mode.as_bytes(&mut buf).len() + 1 + filename.len() + 1 + oid.as_bytes().len()) as u64
104 })
105 .sum()
106 }
107}