| @@ -71,6 +71,17 @@ mod find { · 70 unmodified lines |
| 71 | 71 | ) -> Result<Option<crate::Data<'a>>, find::Error>; |
| 72 | 72 | } |
| 73 | 73 | |
| 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 | + |
| 74 | 85 | mod _impls { |
| 75 | 86 | use std::{ops::Deref, rc::Rc, sync::Arc}; |
| 76 | 87 | |
| @@ -86,6 +97,8 @@ mod find { · 9 unmodified lines |
| 86 | 97 | } |
| 87 | 98 | } |
| 88 | 99 | |
| 100 | + impl<T> crate::FindObjectOrHeader for T where T: crate::Find + crate::FindHeader {} |
| 101 | + |
| 89 | 102 | impl<T> crate::Find for &T |
| 90 | 103 | where |
| 91 | 104 | T: crate::Find, |
| @@ -95,6 +108,15 @@ mod find { · 3 unmodified lines |
| 95 | 108 | } |
| 96 | 109 | } |
| 97 | 110 | |
| 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 | + |
| 98 | 120 | impl<T> crate::Exists for Box<T> |
| 99 | 121 | where |
| 100 | 122 | T: crate::Exists, |
| @@ -122,6 +144,15 @@ mod find { · 21 unmodified lines |
| 122 | 144 | } |
| 123 | 145 | } |
| 124 | 146 | |
| 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 | + |
| 125 | 156 | impl<T> crate::Find for Box<T> |
| 126 | 157 | where |
| 127 | 158 | T: crate::Find, |
| @@ -131,6 +162,15 @@ mod find { · 3 unmodified lines |
| 131 | 162 | } |
| 132 | 163 | } |
| 133 | 164 | |
| 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 | + |
| 134 | 174 | impl<T> crate::Exists for Arc<T> |
| 135 | 175 | where |
| 136 | 176 | T: crate::Exists, |
| @@ -148,6 +188,15 @@ mod find { · 11 unmodified lines |
| 148 | 188 | self.deref().try_find(id, buffer) |
| 149 | 189 | } |
| 150 | 190 | } |
| 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 | + } |
| 151 | 200 | } |
| 152 | 201 | |
| 153 | 202 | mod ext { |
| @@ -214,9 +263,19 @@ mod find { · 60 unmodified lines |
| 214 | 263 | }; |
| 215 | 264 | } |
| 216 | 265 | |
| 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 | + |
| 217 | 276 | /// An extension trait with convenience functions. |
| 218 | 277 | 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. |
| 220 | 279 | fn find<'a>( |
| 221 | 280 | &self, |
| 222 | 281 | id: &gix_hash::oid, |
| @@ -238,6 +297,6 @@ mod find { · 15 unmodified lines |
| 238 | 297 | |
| 239 | 298 | impl<T: super::Find + ?Sized> FindExt for T {} |
| 240 | 299 | } |
| 241 | | − pub use ext::FindExt; |
| 300 | + pub use ext::{FindExt, HeaderExt}; |
| 242 | 301 | } |
| 243 | 302 | pub use find::*; |