132 lines · 4.9 KB · Rust
RawDownload
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<io::Error>` bound.    type Error: std::error::Error + From<io::Error>;     /// 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<git_hash::ObjectId, Self::Error> {        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<git_hash::ObjectId, Self::Error> {        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<git_hash::ObjectId, Self::Error>;} /// 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/44265pub 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<git_hash::oid>,        buffer: &'a mut Vec<u8>,        pack_cache: &mut impl crate::pack::cache::DecodeEntry,    ) -> Result<Option<data::Object<'a>>, 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<PackEntry<'_>>;} #[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy)]#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))]#[allow(missing_docs)] // TODO: docspub 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<u32>,    /// 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<T> super::Find for std::sync::Arc<T>    where        T: super::Find,    {        type Error = T::Error;         fn find<'a>(            &self,            id: impl AsRef<oid>,            buffer: &'a mut Vec<u8>,            pack_cache: &mut impl pack::cache::DecodeEntry,        ) -> Result<Option<Object<'a>>, Self::Error> {            self.deref().find(id, buffer, pack_cache)        }         fn pack_entry(&self, object: &data::Object<'_>) -> Option<PackEntry<'_>> {            self.deref().pack_entry(object)        }    }     impl<T> super::Find for Box<T>    where        T: super::Find,    {        type Error = T::Error;         fn find<'a>(            &self,            id: impl AsRef<oid>,            buffer: &'a mut Vec<u8>,            pack_cache: &mut impl pack::cache::DecodeEntry,        ) -> Result<Option<Object<'a>>, Self::Error> {            self.deref().find(id, buffer, pack_cache)        }         fn pack_entry(&self, object: &data::Object<'_>) -> Option<PackEntry<'_>> {            self.deref().pack_entry(object)        }    }}