Skip to content

Commit 1838cbd

Browse files
committed
feat: support for querying only the header of an object with the FindHeader trait.
That way one can know its decompressed size and its kind. We also add a `FindObjectOrHeader` trait for use as `dyn` trait object that can find objects and access their headers.
1 parent f09ea13 commit 1838cbd

File tree

3 files changed

+77
-3
lines changed

3 files changed

+77
-3
lines changed

gix-object/src/find.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,12 @@ pub mod existing_iter {
6666
#[derive(Debug, Copy, Clone)]
6767
pub struct Never;
6868

69+
impl super::FindHeader for Never {
70+
fn try_header(&self, _id: &gix_hash::oid) -> Result<Option<crate::Header>, Error> {
71+
Ok(None)
72+
}
73+
}
74+
6975
impl super::Find for Never {
7076
fn try_find<'a>(&self, _id: &gix_hash::oid, _buffer: &'a mut Vec<u8>) -> Result<Option<crate::Data<'a>>, Error> {
7177
Ok(None)

gix-object/src/lib.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ pub mod data;
3434
pub mod find;
3535

3636
mod traits;
37-
pub use traits::{Exists, Find, FindExt, WriteTo};
37+
pub use traits::{Exists, Find, FindExt, FindObjectOrHeader, Header as FindHeader, HeaderExt, WriteTo};
3838

3939
pub mod encode;
4040
pub(crate) mod parse;
@@ -257,6 +257,15 @@ pub struct Data<'a> {
257257
pub data: &'a [u8],
258258
}
259259

260+
/// Information about an object, which includes its kind and the amount of bytes it would have when obtained.
261+
#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy)]
262+
pub struct Header {
263+
/// The kind of object.
264+
pub kind: Kind,
265+
/// The object's size in bytes, or the size of the buffer when it's retrieved in full.
266+
pub size: u64,
267+
}
268+
260269
///
261270
pub mod decode {
262271
#[cfg(feature = "verbose-object-parsing-errors")]

gix-object/src/traits.rs

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,17 @@ mod find {
7171
) -> Result<Option<crate::Data<'a>>, find::Error>;
7272
}
7373

74+
/// Find the header of an object in the object store.
75+
pub trait Header {
76+
/// Find the header of the object matching `id` in the database.
77+
///
78+
/// Returns `Some` header if it was present, or the error that occurred during lookup.
79+
fn try_header(&self, id: &gix_hash::oid) -> Result<Option<crate::Header>, find::Error>;
80+
}
81+
82+
/// A combination of [`Find`] and [`Header`] traits to help with `dyn` trait objects.
83+
pub trait FindObjectOrHeader: Find + Header {}
84+
7485
mod _impls {
7586
use std::{ops::Deref, rc::Rc, sync::Arc};
7687

@@ -86,6 +97,8 @@ mod find {
8697
}
8798
}
8899

100+
impl<T> crate::FindObjectOrHeader for T where T: crate::Find + crate::FindHeader {}
101+
89102
impl<T> crate::Find for &T
90103
where
91104
T: crate::Find,
@@ -95,6 +108,15 @@ mod find {
95108
}
96109
}
97110

111+
impl<T> crate::FindHeader for &T
112+
where
113+
T: crate::FindHeader,
114+
{
115+
fn try_header(&self, id: &gix_hash::oid) -> Result<Option<crate::Header>, crate::find::Error> {
116+
(*self).try_header(id)
117+
}
118+
}
119+
98120
impl<T> crate::Exists for Box<T>
99121
where
100122
T: crate::Exists,
@@ -122,6 +144,15 @@ mod find {
122144
}
123145
}
124146

147+
impl<T> crate::FindHeader for Rc<T>
148+
where
149+
T: crate::FindHeader,
150+
{
151+
fn try_header(&self, id: &gix_hash::oid) -> Result<Option<crate::Header>, crate::find::Error> {
152+
self.deref().try_header(id)
153+
}
154+
}
155+
125156
impl<T> crate::Find for Box<T>
126157
where
127158
T: crate::Find,
@@ -131,6 +162,15 @@ mod find {
131162
}
132163
}
133164

165+
impl<T> crate::FindHeader for Box<T>
166+
where
167+
T: crate::FindHeader,
168+
{
169+
fn try_header(&self, id: &gix_hash::oid) -> Result<Option<crate::Header>, crate::find::Error> {
170+
self.deref().try_header(id)
171+
}
172+
}
173+
134174
impl<T> crate::Exists for Arc<T>
135175
where
136176
T: crate::Exists,
@@ -148,6 +188,15 @@ mod find {
148188
self.deref().try_find(id, buffer)
149189
}
150190
}
191+
192+
impl<T> crate::FindHeader for Arc<T>
193+
where
194+
T: crate::FindHeader,
195+
{
196+
fn try_header(&self, id: &gix_hash::oid) -> Result<Option<crate::Header>, crate::find::Error> {
197+
self.deref().try_header(id)
198+
}
199+
}
151200
}
152201

153202
mod ext {
@@ -214,9 +263,19 @@ mod find {
214263
};
215264
}
216265

266+
/// An extension trait with convenience functions.
267+
pub trait HeaderExt: super::Header {
268+
/// Like [`try_header(…)`](super::Header::try_header()), but flattens the `Result<Option<_>>` into a single `Result` making a non-existing header an error.
269+
fn header(&self, id: &gix_hash::oid) -> Result<crate::Header, find::existing::Error> {
270+
self.try_header(id)
271+
.map_err(find::existing::Error::Find)?
272+
.ok_or_else(|| find::existing::Error::NotFound { oid: id.to_owned() })
273+
}
274+
}
275+
217276
/// An extension trait with convenience functions.
218277
pub trait FindExt: super::Find {
219-
/// Like [`try_find(…)`][super::Find::try_find()], but flattens the `Result<Option<_>>` into a single `Result` making a non-existing object an error.
278+
/// Like [`try_find(…)`](super::Find::try_find()), but flattens the `Result<Option<_>>` into a single `Result` making a non-existing object an error.
220279
fn find<'a>(
221280
&self,
222281
id: &gix_hash::oid,
@@ -238,6 +297,6 @@ mod find {
238297

239298
impl<T: super::Find + ?Sized> FindExt for T {}
240299
}
241-
pub use ext::FindExt;
300+
pub use ext::{FindExt, HeaderExt};
242301
}
243302
pub use find::*;

0 commit comments

Comments
 (0)