1 use crate::{Blob, Commit, Object, Tag, Tree}
;
8 use crate::{Kind, Object, ObjectRef, WriteTo}
;
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
::*;
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
),
23 fn kind(&self) -> Kind
{
27 fn size(&self) -> u64 {
28 use crate::ObjectRef
::*;
32 Commit(v
) => v
.size(),
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
<()> {
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
),
51 fn kind(&self) -> Kind
{
55 fn size(&self) -> u64 {
60 Commit(v
) => v
.size(),
67 /// Convenient extraction of typed object.
69 /// Turns this instance into a [`Blob`], panic otherwise.
70 pub fn into_blob(self) -> Blob
{
73 _
=> panic
!("BUG: not a blob"),
76 /// Turns this instance into a [`Commit`] panic otherwise.
77 pub fn into_commit(self) -> Commit
{
79 Object
::Commit(v
) => v
,
80 _
=> panic
!("BUG: not a commit"),
83 /// Turns this instance into a [`Tree`] panic otherwise.
84 pub fn into_tree(self) -> Tree
{
87 _
=> panic
!("BUG: not a tree"),
90 /// Turns this instance into a [`Tag`] panic otherwise.
91 pub fn into_tag(self) -> Tag
{
94 _
=> panic
!("BUG: not a tag"),
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> {
101 Object
::Blob(v
) => Ok(v
),
105 /// Turns this instance into a [`BlobRef`] if it is a blob.
106 pub fn try_into_blob_ref(&self) -> Option
<BlobRef
<'_
>> {
108 Object
::Blob(v
) => Some(v
.to_ref()),
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> {
116 Object
::Commit(v
) => Ok(v
),
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> {
124 Object
::Tree(v
) => Ok(v
),
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> {
132 Object
::Tag(v
) => Ok(v
),
137 /// Returns a [`Blob`] if it is one.
138 pub fn as_blob(&self) -> Option
<&Blob
> {
140 Object
::Blob(v
) => Some(v
),
144 /// Returns a [`Commit`] if it is one.
145 pub fn as_commit(&self) -> Option
<&Commit
> {
147 Object
::Commit(v
) => Some(v
),
151 /// Returns a [`Tree`] if it is one.
152 pub fn as_tree(&self) -> Option
<&Tree
> {
154 Object
::Tree(v
) => Some(v
),
158 /// Returns a [`Tag`] if it is one.
159 pub fn as_tag(&self) -> Option
<&Tag
> {
161 Object
::Tag(v
) => Some(v
),
165 /// Returns the kind of object stored in this instance.
166 pub fn kind(&self) -> crate::Kind
{
168 Object
::Tree(_
) => crate::Kind
::Tree
,
169 Object
::Blob(_
) => crate::Kind
::Blob
,
170 Object
::Commit(_
) => crate::Kind
::Commit
,
171 Object
::Tag(_
) => crate::Kind
::Tag
,
177 decode
::{loose_header, Error as DecodeError, LooseHeaderDecodeError}
,
178 BlobRef
, CommitRef
, Kind
, ObjectRef
, TagRef
, TreeRef
,
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 }
,
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
)?
;
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",
203 Ok(Self::from_bytes(kind
, body
)?
)
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
> {
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
)?
),
216 /// Convert the immutable object into a mutable version, consuming the source in the process.
218 /// Note that this is an expensive operation.
219 pub fn into_owned(self) -> Object
{
223 /// Convert this immutable object into its mutable counterpart.
225 /// Note that this is an expensive operation.
226 pub fn to_owned(&self) -> Object
{
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
>> {
236 ObjectRef
::Blob(v
) => Some(v
),
240 /// Interpret this object as blob, chainable.
241 pub fn into_blob(self) -> Option
<BlobRef
<'a
>> {
243 ObjectRef
::Blob(v
) => Some(v
),
247 /// Interpret this object as commit.
248 pub fn as_commit(&self) -> Option
<&CommitRef
<'a
>> {
250 ObjectRef
::Commit(v
) => Some(v
),
254 /// Interpret this object as commit, chainable.
255 pub fn into_commit(self) -> Option
<CommitRef
<'a
>> {
257 ObjectRef
::Commit(v
) => Some(v
),
261 /// Interpret this object as tree.
262 pub fn as_tree(&self) -> Option
<&TreeRef
<'a
>> {
264 ObjectRef
::Tree(v
) => Some(v
),
268 /// Interpret this object as tree, chainable
269 pub fn into_tree(self) -> Option
<TreeRef
<'a
>> {
271 ObjectRef
::Tree(v
) => Some(v
),
275 /// Interpret this object as tag.
276 pub fn as_tag(&self) -> Option
<&TagRef
<'a
>> {
278 ObjectRef
::Tag(v
) => Some(v
),
282 /// Interpret this object as tag, chainable.
283 pub fn into_tag(self) -> Option
<TagRef
<'a
>> {
285 ObjectRef
::Tag(v
) => Some(v
),
289 /// Return the kind of object.
290 pub fn kind(&self) -> Kind
{
292 ObjectRef
::Tree(_
) => Kind
::Tree
,
293 ObjectRef
::Blob(_
) => Kind
::Blob
,
294 ObjectRef
::Commit(_
) => Kind
::Commit
,
295 ObjectRef
::Tag(_
) => Kind
::Tag
,