History

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.

Sebastian Thiel committed 2 years ago

Commit 1838cbd1 parent f09ea133 files · +77 −3Browse files

Unified · Split

3 files
  1. gix-object/src/find.rs +6 −0
  2. gix-object/src/lib.rs +10 −1
  3. gix-object/src/traits.rs +61 −2
gix-object/src/find.rs+6−0
@@ -66,6 +66,12 @@ pub mod existing_iter { · 65 unmodified lines
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+10−1
@@ -34,7 +34,7 @@ pub mod data; · 33 unmodified lines
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> { · 216 unmodified lines
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+61−2
@@ -71,6 +71,17 @@ mod find { · 70 unmodified lines
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 { · 9 unmodified lines
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 { · 3 unmodified lines
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 { · 21 unmodified lines
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 { · 3 unmodified lines
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 { · 11 unmodified lines
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 { · 60 unmodified lines
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 { · 15 unmodified lines
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::*;