]> git.proxmox.com Git - rustc.git/blob - vendor/gix-object/src/object/mod.rs
New upstream version 1.75.0+dfsg1
[rustc.git] / vendor / gix-object / src / object / mod.rs
1 use crate::{Blob, Commit, Object, Tag, Tree};
2
3 mod convert;
4
5 mod write {
6 use std::io;
7
8 use crate::{Kind, Object, ObjectRef, WriteTo};
9
10 /// Serialization
11 impl<'a> WriteTo for ObjectRef<'a> {
12 /// Write the contained object to `out` in the git serialization format.
13 fn write_to(&self, out: &mut dyn io::Write) -> io::Result<()> {
14 use crate::ObjectRef::*;
15 match self {
16 Tree(v) => v.write_to(out),
17 Blob(v) => v.write_to(out),
18 Commit(v) => v.write_to(out),
19 Tag(v) => v.write_to(out),
20 }
21 }
22
23 fn kind(&self) -> Kind {
24 self.kind()
25 }
26
27 fn size(&self) -> u64 {
28 use crate::ObjectRef::*;
29 match self {
30 Tree(v) => v.size(),
31 Blob(v) => v.size(),
32 Commit(v) => v.size(),
33 Tag(v) => v.size(),
34 }
35 }
36 }
37
38 /// Serialization
39 impl WriteTo for Object {
40 /// Write the contained object to `out` in the git serialization format.
41 fn write_to(&self, out: &mut dyn io::Write) -> io::Result<()> {
42 use crate::Object::*;
43 match self {
44 Tree(v) => v.write_to(out),
45 Blob(v) => v.write_to(out),
46 Commit(v) => v.write_to(out),
47 Tag(v) => v.write_to(out),
48 }
49 }
50
51 fn kind(&self) -> Kind {
52 self.kind()
53 }
54
55 fn size(&self) -> u64 {
56 use crate::Object::*;
57 match self {
58 Tree(v) => v.size(),
59 Blob(v) => v.size(),
60 Commit(v) => v.size(),
61 Tag(v) => v.size(),
62 }
63 }
64 }
65 }
66
67 /// Convenient extraction of typed object.
68 impl Object {
69 /// Turns this instance into a [`Blob`], panic otherwise.
70 pub fn into_blob(self) -> Blob {
71 match self {
72 Object::Blob(v) => v,
73 _ => panic!("BUG: not a blob"),
74 }
75 }
76 /// Turns this instance into a [`Commit`] panic otherwise.
77 pub fn into_commit(self) -> Commit {
78 match self {
79 Object::Commit(v) => v,
80 _ => panic!("BUG: not a commit"),
81 }
82 }
83 /// Turns this instance into a [`Tree`] panic otherwise.
84 pub fn into_tree(self) -> Tree {
85 match self {
86 Object::Tree(v) => v,
87 _ => panic!("BUG: not a tree"),
88 }
89 }
90 /// Turns this instance into a [`Tag`] panic otherwise.
91 pub fn into_tag(self) -> Tag {
92 match self {
93 Object::Tag(v) => v,
94 _ => panic!("BUG: not a tag"),
95 }
96 }
97 /// Turns this instance into a [`Blob`] if it is one.
98 #[allow(clippy::result_large_err)]
99 pub fn try_into_blob(self) -> Result<Blob, Self> {
100 match self {
101 Object::Blob(v) => Ok(v),
102 _ => Err(self),
103 }
104 }
105 /// Turns this instance into a [`BlobRef`] if it is a blob.
106 pub fn try_into_blob_ref(&self) -> Option<BlobRef<'_>> {
107 match self {
108 Object::Blob(v) => Some(v.to_ref()),
109 _ => None,
110 }
111 }
112 /// Turns this instance into a [`Commit`] if it is one.
113 #[allow(clippy::result_large_err)]
114 pub fn try_into_commit(self) -> Result<Commit, Self> {
115 match self {
116 Object::Commit(v) => Ok(v),
117 _ => Err(self),
118 }
119 }
120 /// Turns this instance into a [`Tree`] if it is one.
121 #[allow(clippy::result_large_err)]
122 pub fn try_into_tree(self) -> Result<Tree, Self> {
123 match self {
124 Object::Tree(v) => Ok(v),
125 _ => Err(self),
126 }
127 }
128 /// Turns this instance into a [`Tag`] if it is one.
129 #[allow(clippy::result_large_err)]
130 pub fn try_into_tag(self) -> Result<Tag, Self> {
131 match self {
132 Object::Tag(v) => Ok(v),
133 _ => Err(self),
134 }
135 }
136
137 /// Returns a [`Blob`] if it is one.
138 pub fn as_blob(&self) -> Option<&Blob> {
139 match self {
140 Object::Blob(v) => Some(v),
141 _ => None,
142 }
143 }
144 /// Returns a [`Commit`] if it is one.
145 pub fn as_commit(&self) -> Option<&Commit> {
146 match self {
147 Object::Commit(v) => Some(v),
148 _ => None,
149 }
150 }
151 /// Returns a [`Tree`] if it is one.
152 pub fn as_tree(&self) -> Option<&Tree> {
153 match self {
154 Object::Tree(v) => Some(v),
155 _ => None,
156 }
157 }
158 /// Returns a [`Tag`] if it is one.
159 pub fn as_tag(&self) -> Option<&Tag> {
160 match self {
161 Object::Tag(v) => Some(v),
162 _ => None,
163 }
164 }
165 /// Returns the kind of object stored in this instance.
166 pub fn kind(&self) -> crate::Kind {
167 match self {
168 Object::Tree(_) => crate::Kind::Tree,
169 Object::Blob(_) => crate::Kind::Blob,
170 Object::Commit(_) => crate::Kind::Commit,
171 Object::Tag(_) => crate::Kind::Tag,
172 }
173 }
174 }
175
176 use crate::{
177 decode::{loose_header, Error as DecodeError, LooseHeaderDecodeError},
178 BlobRef, CommitRef, Kind, ObjectRef, TagRef, TreeRef,
179 };
180
181 #[derive(Debug, thiserror::Error)]
182 #[allow(missing_docs)]
183 pub enum LooseDecodeError {
184 #[error(transparent)]
185 InvalidHeader(#[from] LooseHeaderDecodeError),
186 #[error(transparent)]
187 InvalidContent(#[from] DecodeError),
188 #[error("Object sized {size} does not fit into memory - this can happen on 32 bit systems")]
189 OutOfMemory { size: u64 },
190 }
191
192 impl<'a> ObjectRef<'a> {
193 /// Deserialize an object from a loose serialisation
194 pub fn from_loose(data: &'a [u8]) -> Result<ObjectRef<'a>, LooseDecodeError> {
195 let (kind, size, offset) = loose_header(data)?;
196
197 let body = &data[offset..]
198 .get(..size.try_into().map_err(|_| LooseDecodeError::OutOfMemory { size })?)
199 .ok_or(LooseHeaderDecodeError::InvalidHeader {
200 message: "object data was shorter than its size declared in the header",
201 })?;
202
203 Ok(Self::from_bytes(kind, body)?)
204 }
205
206 /// Deserialize an object of `kind` from the given `data`.
207 pub fn from_bytes(kind: Kind, data: &'a [u8]) -> Result<ObjectRef<'a>, crate::decode::Error> {
208 Ok(match kind {
209 Kind::Tree => ObjectRef::Tree(TreeRef::from_bytes(data)?),
210 Kind::Blob => ObjectRef::Blob(BlobRef { data }),
211 Kind::Commit => ObjectRef::Commit(CommitRef::from_bytes(data)?),
212 Kind::Tag => ObjectRef::Tag(TagRef::from_bytes(data)?),
213 })
214 }
215
216 /// Convert the immutable object into a mutable version, consuming the source in the process.
217 ///
218 /// Note that this is an expensive operation.
219 pub fn into_owned(self) -> Object {
220 self.into()
221 }
222
223 /// Convert this immutable object into its mutable counterpart.
224 ///
225 /// Note that this is an expensive operation.
226 pub fn to_owned(&self) -> Object {
227 self.clone().into()
228 }
229 }
230
231 /// Convenient access to contained objects.
232 impl<'a> ObjectRef<'a> {
233 /// Interpret this object as blob.
234 pub fn as_blob(&self) -> Option<&BlobRef<'a>> {
235 match self {
236 ObjectRef::Blob(v) => Some(v),
237 _ => None,
238 }
239 }
240 /// Interpret this object as blob, chainable.
241 pub fn into_blob(self) -> Option<BlobRef<'a>> {
242 match self {
243 ObjectRef::Blob(v) => Some(v),
244 _ => None,
245 }
246 }
247 /// Interpret this object as commit.
248 pub fn as_commit(&self) -> Option<&CommitRef<'a>> {
249 match self {
250 ObjectRef::Commit(v) => Some(v),
251 _ => None,
252 }
253 }
254 /// Interpret this object as commit, chainable.
255 pub fn into_commit(self) -> Option<CommitRef<'a>> {
256 match self {
257 ObjectRef::Commit(v) => Some(v),
258 _ => None,
259 }
260 }
261 /// Interpret this object as tree.
262 pub fn as_tree(&self) -> Option<&TreeRef<'a>> {
263 match self {
264 ObjectRef::Tree(v) => Some(v),
265 _ => None,
266 }
267 }
268 /// Interpret this object as tree, chainable
269 pub fn into_tree(self) -> Option<TreeRef<'a>> {
270 match self {
271 ObjectRef::Tree(v) => Some(v),
272 _ => None,
273 }
274 }
275 /// Interpret this object as tag.
276 pub fn as_tag(&self) -> Option<&TagRef<'a>> {
277 match self {
278 ObjectRef::Tag(v) => Some(v),
279 _ => None,
280 }
281 }
282 /// Interpret this object as tag, chainable.
283 pub fn into_tag(self) -> Option<TagRef<'a>> {
284 match self {
285 ObjectRef::Tag(v) => Some(v),
286 _ => None,
287 }
288 }
289 /// Return the kind of object.
290 pub fn kind(&self) -> Kind {
291 match self {
292 ObjectRef::Tree(_) => Kind::Tree,
293 ObjectRef::Blob(_) => Kind::Blob,
294 ObjectRef::Commit(_) => Kind::Commit,
295 ObjectRef::Tag(_) => Kind::Tag,
296 }
297 }
298 }