use crate::{data, pack}; use git_object::mutable; use std::io; /// Describe the capability to write git objects into an object store. pub trait Write { /// The error type used for all trait methods. /// /// _Note_ the default implementations require the `From` bound. type Error: std::error::Error + From; /// Write [`object`][mutable::Object] using the given kind of [`hash`][git_hash::Kind] into the database, /// returning id to reference it in subsequent reads. fn write(&self, object: &mutable::Object, hash: git_hash::Kind) -> Result { let mut buf = Vec::with_capacity(2048); object.write_to(&mut buf)?; self.write_stream(object.kind(), buf.len() as u64, buf.as_slice(), hash) } /// As [`write`][Write::write], but takes an [`object` kind][git_object::Kind] along with its encoded bytes. fn write_buf( &self, object: git_object::Kind, from: &[u8], hash: git_hash::Kind, ) -> Result { self.write_stream(object, from.len() as u64, from, hash) } /// As [`write`][Write::write], but takes an input stream. /// This is commonly used for writing blobs directly without reading them to memory first. fn write_stream( &self, kind: git_object::Kind, size: u64, from: impl io::Read, hash: git_hash::Kind, ) -> Result; } /// Describe how object can be located in an object store /// /// ## Notes /// /// Locate effectively needs [generic associated types][issue] to allow a trait for the returned object type. /// Until then, we will have to make due with explicit types and give them the potentially added features we want. /// /// [issue]: https://github.com/rust-lang/rust/issues/44265 pub trait Find { /// The error returned by [`find()`][Find::find()] type Error: std::error::Error + 'static; /// Find an object matching `id` in the database while placing its raw, undecoded data into `buffer`. /// A `pack_cache` can be used to speed up subsequent lookups, set it to [`pack::cache::Never`] if the /// workload isn't suitable for caching. /// /// Returns `Some` object if it was present in the database, or the error that occurred during lookup or object /// retrieval. fn find<'a>( &self, id: impl AsRef, buffer: &'a mut Vec, pack_cache: &mut impl crate::pack::cache::DecodeEntry, ) -> Result>, Self::Error>; /// Return the [`PackEntry`] for `object` if it is backed by a pack. /// /// Note that this is only in the interest of avoiding duplicate work during pack generation /// as the input for this is an already decoded [`data::Object`] that is fully known. /// /// # Notes /// /// Custom implementations might be interested in providing their own meta-data with `object`, /// which currently isn't possible as the `Locate` trait requires GATs to work like that. fn pack_entry(&self, object: &data::Object<'_>) -> Option>; } #[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy)] #[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] #[allow(missing_docs)] // TODO: docs pub struct PackEntry<'a> { /// The encoded data of the entry as present in the pack file, including the header followed by compressed data. pub data: &'a [u8], /// The crc32 hash over the entirety of `data`, or None if the pack file format doesn't support it yet. pub crc32: Option, /// The version of the pack file containing `data` pub version: pack::data::Version, } mod locate_impls { use crate::{data, data::Object, pack, PackEntry}; use git_hash::oid; use std::ops::Deref; impl super::Find for std::sync::Arc where T: super::Find, { type Error = T::Error; fn find<'a>( &self, id: impl AsRef, buffer: &'a mut Vec, pack_cache: &mut impl pack::cache::DecodeEntry, ) -> Result>, Self::Error> { self.deref().find(id, buffer, pack_cache) } fn pack_entry(&self, object: &data::Object<'_>) -> Option> { self.deref().pack_entry(object) } } impl super::Find for Box where T: super::Find, { type Error = T::Error; fn find<'a>( &self, id: impl AsRef, buffer: &'a mut Vec, pack_cache: &mut impl pack::cache::DecodeEntry, ) -> Result>, Self::Error> { self.deref().find(id, buffer, pack_cache) } fn pack_entry(&self, object: &data::Object<'_>) -> Option> { self.deref().pack_entry(object) } } }