]> git.proxmox.com Git - rustc.git/blob - vendor/gix-object/src/tree/write.rs
New upstream version 1.74.1+dfsg1
[rustc.git] / vendor / gix-object / src / tree / write.rs
1 use std::io;
2
3 use bstr::{BString, ByteSlice};
4
5 use crate::{
6 encode::SPACE,
7 tree::{Entry, EntryRef},
8 Kind, Tree, TreeRef,
9 };
10
11 /// The Error used in [`Tree::write_to()`][crate::WriteTo::write_to()].
12 #[derive(Debug, thiserror::Error)]
13 #[allow(missing_docs)]
14 pub enum Error {
15 #[error("Newlines are invalid in file paths: {name:?}")]
16 NewlineInFilename { name: BString },
17 }
18
19 impl From<Error> for io::Error {
20 fn from(err: Error) -> Self {
21 io::Error::new(io::ErrorKind::Other, err)
22 }
23 }
24
25 /// Serialization
26 impl crate::WriteTo for Tree {
27 /// Serialize this tree to `out` in the git internal format.
28 fn write_to(&self, out: &mut dyn io::Write) -> io::Result<()> {
29 debug_assert_eq!(
30 &{
31 let mut entries_sorted = self.entries.clone();
32 entries_sorted.sort();
33 entries_sorted
34 },
35 &self.entries,
36 "entries for serialization must be sorted by filename"
37 );
38 for Entry { mode, filename, oid } in &self.entries {
39 out.write_all(mode.as_bytes())?;
40 out.write_all(SPACE)?;
41
42 if filename.find_byte(b'\n').is_some() {
43 return Err(Error::NewlineInFilename {
44 name: (*filename).to_owned(),
45 }
46 .into());
47 }
48 out.write_all(filename)?;
49 out.write_all(&[b'\0'])?;
50
51 out.write_all(oid.as_bytes())?;
52 }
53 Ok(())
54 }
55
56 fn kind(&self) -> Kind {
57 Kind::Tree
58 }
59
60 fn size(&self) -> usize {
61 self.entries
62 .iter()
63 .map(|Entry { mode, filename, oid }| mode.as_bytes().len() + 1 + filename.len() + 1 + oid.as_bytes().len())
64 .sum()
65 }
66 }
67
68 /// Serialization
69 impl<'a> crate::WriteTo for TreeRef<'a> {
70 /// Serialize this tree to `out` in the git internal format.
71 fn write_to(&self, out: &mut dyn io::Write) -> io::Result<()> {
72 debug_assert_eq!(
73 &{
74 let mut entries_sorted = self.entries.clone();
75 entries_sorted.sort();
76 entries_sorted
77 },
78 &self.entries,
79 "entries for serialization must be sorted by filename"
80 );
81 for EntryRef { mode, filename, oid } in &self.entries {
82 out.write_all(mode.as_bytes())?;
83 out.write_all(SPACE)?;
84
85 if filename.find_byte(b'\n').is_some() {
86 return Err(Error::NewlineInFilename {
87 name: (*filename).to_owned(),
88 }
89 .into());
90 }
91 out.write_all(filename)?;
92 out.write_all(&[b'\0'])?;
93
94 out.write_all(oid.as_bytes())?;
95 }
96 Ok(())
97 }
98
99 fn kind(&self) -> Kind {
100 Kind::Tree
101 }
102
103 fn size(&self) -> usize {
104 self.entries
105 .iter()
106 .map(|EntryRef { mode, filename, oid }| {
107 mode.as_bytes().len() + 1 + filename.len() + 1 + oid.as_bytes().len()
108 })
109 .sum()
110 }
111 }