1use crate::{data, find};
2
3pub trait Find {
15 fn contains(&self, id: &gix_hash::oid) -> bool;
17
18 fn try_find<'a>(
25 &self,
26 id: &gix_hash::oid,
27 buffer: &'a mut Vec<u8>,
28 ) -> Result<Option<(gix_object::Data<'a>, Option<data::entry::Location>)>, gix_object::find::Error> {
29 self.try_find_cached(id, buffer, &mut crate::cache::Never)
30 }
31
32 fn try_find_cached<'a>(
39 &self,
40 id: &gix_hash::oid,
41 buffer: &'a mut Vec<u8>,
42 pack_cache: &mut dyn crate::cache::DecodeEntry,
43 ) -> Result<Option<(gix_object::Data<'a>, Option<data::entry::Location>)>, gix_object::find::Error>;
44
45 fn location_by_oid(&self, id: &gix_hash::oid, buf: &mut Vec<u8>) -> Option<data::entry::Location>;
50
51 fn pack_offsets_and_oid(&self, pack_id: u32) -> Option<Vec<(data::Offset, gix_hash::ObjectId)>>;
53
54 fn entry_by_location(&self, location: &data::entry::Location) -> Option<find::Entry>;
64}
65
66mod ext {
67 use gix_object::{BlobRef, CommitRef, CommitRefIter, Kind, ObjectRef, TagRef, TagRefIter, TreeRef, TreeRefIter};
68
69 macro_rules! make_obj_lookup {
70 ($method:ident, $object_variant:path, $object_kind:path, $object_type:ty) => {
71 fn $method<'a>(
74 &self,
75 id: &gix_hash::oid,
76 buffer: &'a mut Vec<u8>,
77 ) -> Result<($object_type, Option<crate::data::entry::Location>), gix_object::find::existing_object::Error>
78 {
79 let id = id.as_ref();
80 self.try_find(id, buffer)
81 .map_err(gix_object::find::existing_object::Error::Find)?
82 .ok_or_else(|| gix_object::find::existing_object::Error::NotFound {
83 oid: id.as_ref().to_owned(),
84 })
85 .and_then(|(o, l)| {
86 o.decode()
87 .map_err(|err| gix_object::find::existing_object::Error::Decode {
88 source: err,
89 oid: id.to_owned(),
90 })
91 .map(|o| (o, l))
92 })
93 .and_then(|(o, l)| match o {
94 $object_variant(o) => return Ok((o, l)),
95 o => Err(gix_object::find::existing_object::Error::ObjectKind {
96 oid: id.to_owned(),
97 actual: o.kind(),
98 expected: $object_kind,
99 }),
100 })
101 }
102 };
103 }
104
105 macro_rules! make_iter_lookup {
106 ($method:ident, $object_kind:path, $object_type:ty, $into_iter:tt) => {
107 fn $method<'a>(
110 &self,
111 id: &gix_hash::oid,
112 buffer: &'a mut Vec<u8>,
113 ) -> Result<($object_type, Option<crate::data::entry::Location>), gix_object::find::existing_iter::Error> {
114 let id = id.as_ref();
115 self.try_find(id, buffer)
116 .map_err(gix_object::find::existing_iter::Error::Find)?
117 .ok_or_else(|| gix_object::find::existing_iter::Error::NotFound {
118 oid: id.as_ref().to_owned(),
119 })
120 .and_then(|(o, l)| {
121 o.$into_iter()
122 .ok_or_else(|| gix_object::find::existing_iter::Error::ObjectKind {
123 oid: id.to_owned(),
124 actual: o.kind,
125 expected: $object_kind,
126 })
127 .map(|i| (i, l))
128 })
129 }
130 };
131 }
132
133 pub trait FindExt: super::Find {
135 fn find<'a>(
137 &self,
138 id: &gix_hash::oid,
139 buffer: &'a mut Vec<u8>,
140 ) -> Result<(gix_object::Data<'a>, Option<crate::data::entry::Location>), gix_object::find::existing::Error>
141 {
142 self.try_find(id, buffer)
143 .map_err(gix_object::find::existing::Error::Find)?
144 .ok_or_else(|| gix_object::find::existing::Error::NotFound {
145 oid: id.as_ref().to_owned(),
146 })
147 }
148
149 make_obj_lookup!(find_commit, ObjectRef::Commit, Kind::Commit, CommitRef<'a>);
150 make_obj_lookup!(find_tree, ObjectRef::Tree, Kind::Tree, TreeRef<'a>);
151 make_obj_lookup!(find_tag, ObjectRef::Tag, Kind::Tag, TagRef<'a>);
152 make_obj_lookup!(find_blob, ObjectRef::Blob, Kind::Blob, BlobRef<'a>);
153 make_iter_lookup!(find_commit_iter, Kind::Blob, CommitRefIter<'a>, try_into_commit_iter);
154 make_iter_lookup!(find_tree_iter, Kind::Tree, TreeRefIter<'a>, try_into_tree_iter);
155 make_iter_lookup!(find_tag_iter, Kind::Tag, TagRefIter<'a>, try_into_tag_iter);
156 }
157
158 impl<T: super::Find + ?Sized> FindExt for T {}
159}
160pub use ext::FindExt;
161
162mod find_impls {
163 use std::{ops::Deref, rc::Rc};
164
165 use gix_hash::oid;
166
167 use crate::{data, find};
168
169 impl<T> crate::Find for &T
170 where
171 T: crate::Find,
172 {
173 fn contains(&self, id: &oid) -> bool {
174 (*self).contains(id)
175 }
176
177 fn try_find_cached<'a>(
178 &self,
179 id: &oid,
180 buffer: &'a mut Vec<u8>,
181 pack_cache: &mut dyn crate::cache::DecodeEntry,
182 ) -> Result<Option<(gix_object::Data<'a>, Option<data::entry::Location>)>, gix_object::find::Error> {
183 (*self).try_find_cached(id, buffer, pack_cache)
184 }
185
186 fn location_by_oid(&self, id: &oid, buf: &mut Vec<u8>) -> Option<data::entry::Location> {
187 (*self).location_by_oid(id, buf)
188 }
189
190 fn pack_offsets_and_oid(&self, pack_id: u32) -> Option<Vec<(data::Offset, gix_hash::ObjectId)>> {
191 (*self).pack_offsets_and_oid(pack_id)
192 }
193
194 fn entry_by_location(&self, location: &data::entry::Location) -> Option<find::Entry> {
195 (*self).entry_by_location(location)
196 }
197 }
198
199 impl<T> super::Find for std::sync::Arc<T>
200 where
201 T: super::Find,
202 {
203 fn contains(&self, id: &oid) -> bool {
204 self.deref().contains(id)
205 }
206
207 fn try_find_cached<'a>(
208 &self,
209 id: &oid,
210 buffer: &'a mut Vec<u8>,
211 pack_cache: &mut dyn crate::cache::DecodeEntry,
212 ) -> Result<Option<(gix_object::Data<'a>, Option<data::entry::Location>)>, gix_object::find::Error> {
213 self.deref().try_find_cached(id, buffer, pack_cache)
214 }
215
216 fn location_by_oid(&self, id: &oid, buf: &mut Vec<u8>) -> Option<data::entry::Location> {
217 self.deref().location_by_oid(id, buf)
218 }
219
220 fn pack_offsets_and_oid(&self, pack_id: u32) -> Option<Vec<(data::Offset, gix_hash::ObjectId)>> {
221 self.deref().pack_offsets_and_oid(pack_id)
222 }
223
224 fn entry_by_location(&self, object: &data::entry::Location) -> Option<find::Entry> {
225 self.deref().entry_by_location(object)
226 }
227 }
228
229 impl<T> super::Find for Rc<T>
230 where
231 T: super::Find,
232 {
233 fn contains(&self, id: &oid) -> bool {
234 self.deref().contains(id)
235 }
236
237 fn try_find_cached<'a>(
238 &self,
239 id: &oid,
240 buffer: &'a mut Vec<u8>,
241 pack_cache: &mut dyn crate::cache::DecodeEntry,
242 ) -> Result<Option<(gix_object::Data<'a>, Option<data::entry::Location>)>, gix_object::find::Error> {
243 self.deref().try_find_cached(id, buffer, pack_cache)
244 }
245
246 fn location_by_oid(&self, id: &oid, buf: &mut Vec<u8>) -> Option<data::entry::Location> {
247 self.deref().location_by_oid(id, buf)
248 }
249
250 fn pack_offsets_and_oid(&self, pack_id: u32) -> Option<Vec<(data::Offset, gix_hash::ObjectId)>> {
251 self.deref().pack_offsets_and_oid(pack_id)
252 }
253
254 fn entry_by_location(&self, location: &data::entry::Location) -> Option<find::Entry> {
255 self.deref().entry_by_location(location)
256 }
257 }
258
259 impl<T> super::Find for Box<T>
260 where
261 T: super::Find,
262 {
263 fn contains(&self, id: &oid) -> bool {
264 self.deref().contains(id)
265 }
266
267 fn try_find_cached<'a>(
268 &self,
269 id: &oid,
270 buffer: &'a mut Vec<u8>,
271 pack_cache: &mut dyn crate::cache::DecodeEntry,
272 ) -> Result<Option<(gix_object::Data<'a>, Option<data::entry::Location>)>, gix_object::find::Error> {
273 self.deref().try_find_cached(id, buffer, pack_cache)
274 }
275
276 fn location_by_oid(&self, id: &oid, buf: &mut Vec<u8>) -> Option<data::entry::Location> {
277 self.deref().location_by_oid(id, buf)
278 }
279
280 fn pack_offsets_and_oid(&self, pack_id: u32) -> Option<Vec<(data::Offset, gix_hash::ObjectId)>> {
281 self.deref().pack_offsets_and_oid(pack_id)
282 }
283
284 fn entry_by_location(&self, location: &data::entry::Location) -> Option<find::Entry> {
285 self.deref().entry_by_location(location)
286 }
287 }
288}