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