use crate::Error;
use crate::GitOid;
use crate::HashAlgorithm;
use crate::ObjectType;
use crate::Result;
use std::collections::HashSet;
use std::fs::File;
use std::io::BufReader;
use std::io::Read;
use std::io::Seek;
use std::path::Path;
use std::path::PathBuf;
pub struct Finder {
default_hash_algorithm: HashAlgorithm,
default_object_type: ObjectType,
gitoids: HashSet<GitOid>,
}
impl Finder {
pub fn for_gitoids<'a, I>(
default_hash_algorithm: HashAlgorithm,
default_object_type: ObjectType,
gitoids: I,
) -> Self
where
I: IntoIterator<Item = &'a GitOid>,
{
Finder {
default_hash_algorithm,
default_object_type,
gitoids: gitoids.into_iter().copied().collect(),
}
}
pub fn find<P>(&self, potential: P) -> (P::Id, Result<Option<GitOid>>)
where
P: IntoIdentifiedGitOid,
{
let (id, gitoid_result) =
potential.into_identified_gitoid(self.default_hash_algorithm, self.default_object_type);
(
id,
gitoid_result.map(|gitoid| self.gitoids.get(&gitoid).copied()),
)
}
pub fn find_all<'s, I: 's, P>(
&'s self,
potentials: I,
) -> impl Iterator<Item = (P::Id, Result<Option<GitOid>>)> + 's
where
I: IntoIterator<Item = P>,
P: IntoIdentifiedGitOid,
{
potentials.into_iter().map(|potential| self.find(potential))
}
}
pub trait IntoIdentifiedGitOid {
type Id;
fn into_identified_gitoid(
self,
default_hash_algorithm: HashAlgorithm,
default_object_type: ObjectType,
) -> (Self::Id, Result<GitOid>);
}
impl IntoIdentifiedGitOid for GitOid {
type Id = GitOid;
fn into_identified_gitoid(
self,
_default_hash_algorithm: HashAlgorithm,
_default_object_type: ObjectType,
) -> (Self::Id, Result<GitOid>) {
(self, Ok(self))
}
}
impl<'gitoid> IntoIdentifiedGitOid for &'gitoid GitOid {
type Id = GitOid;
fn into_identified_gitoid(
self,
_default_hash_algorithm: HashAlgorithm,
_default_object_type: ObjectType,
) -> (Self::Id, Result<GitOid>) {
(*self, Ok(*self))
}
}
impl<I> IntoIdentifiedGitOid for (I, GitOid) {
type Id = I;
fn into_identified_gitoid(
self,
_default_hash_algorithm: HashAlgorithm,
_default_object_type: ObjectType,
) -> (Self::Id, Result<GitOid>) {
(self.0, Ok(self.1))
}
}
impl<'gitoid, I> IntoIdentifiedGitOid for (I, &'gitoid GitOid) {
type Id = I;
fn into_identified_gitoid(
self,
_default_hash_algorithm: HashAlgorithm,
_default_object_type: ObjectType,
) -> (Self::Id, Result<GitOid>) {
(self.0, Ok(*self.1))
}
}
impl<'a> IntoIdentifiedGitOid for &'a Path {
type Id = PathBuf;
fn into_identified_gitoid(
self,
default_hash_algorithm: HashAlgorithm,
default_object_type: ObjectType,
) -> (Self::Id, Result<GitOid>) {
let file = match File::open(self) {
Ok(f) => f,
Err(e) => return (self.to_owned(), Err(Error::from(e))),
};
IntoIdentifiedGitOid::into_identified_gitoid(
(self.to_owned(), file),
default_hash_algorithm,
default_object_type,
)
}
}
impl<'a> IntoIdentifiedGitOid for (&'a Path, HashAlgorithm) {
type Id = PathBuf;
fn into_identified_gitoid(
self,
_default_hash_algorithm: HashAlgorithm,
default_object_type: ObjectType,
) -> (Self::Id, Result<GitOid>) {
IntoIdentifiedGitOid::into_identified_gitoid(self.0, self.1, default_object_type)
}
}
impl<'a> IntoIdentifiedGitOid for (&'a Path, ObjectType) {
type Id = PathBuf;
fn into_identified_gitoid(
self,
default_hash_algorithm: HashAlgorithm,
_default_object_type: ObjectType,
) -> (Self::Id, Result<GitOid>) {
IntoIdentifiedGitOid::into_identified_gitoid(self.0, default_hash_algorithm, self.1)
}
}
impl<'a> IntoIdentifiedGitOid for (&'a Path, HashAlgorithm, ObjectType) {
type Id = PathBuf;
fn into_identified_gitoid(
self,
_default_hash_algorithm: HashAlgorithm,
_default_object_type: ObjectType,
) -> (Self::Id, Result<GitOid>) {
IntoIdentifiedGitOid::into_identified_gitoid(self.0, self.1, self.2)
}
}
impl<I, R> IntoIdentifiedGitOid for (I, R)
where
R: Read + Seek,
{
type Id = I;
fn into_identified_gitoid(
mut self,
default_hash_algorithm: HashAlgorithm,
default_object_type: ObjectType,
) -> (Self::Id, Result<GitOid>) {
let reader = BufReader::new(&mut self.1);
let gitoid =
match GitOid::new_from_reader(default_hash_algorithm, default_object_type, reader) {
Ok(g) => g,
Err(e) => return (self.0, Err(e)),
};
IntoIdentifiedGitOid::into_identified_gitoid(
(self.0, gitoid),
default_hash_algorithm,
default_object_type,
)
}
}
impl<I, R> IntoIdentifiedGitOid for (I, R, HashAlgorithm)
where
R: Read + Seek,
{
type Id = I;
fn into_identified_gitoid(
mut self,
_default_hash_algorithm: HashAlgorithm,
default_object_type: ObjectType,
) -> (Self::Id, Result<GitOid>) {
IntoIdentifiedGitOid::into_identified_gitoid(
(self.0, &mut self.1),
self.2,
default_object_type,
)
}
}
impl<I, R> IntoIdentifiedGitOid for (I, R, ObjectType)
where
R: Read + Seek,
{
type Id = I;
fn into_identified_gitoid(
mut self,
default_hash_algorithm: HashAlgorithm,
_default_object_type: ObjectType,
) -> (Self::Id, Result<GitOid>) {
IntoIdentifiedGitOid::into_identified_gitoid(
(self.0, &mut self.1),
default_hash_algorithm,
self.2,
)
}
}
impl<I, R> IntoIdentifiedGitOid for (I, R, HashAlgorithm, ObjectType)
where
R: Read + Seek,
{
type Id = I;
fn into_identified_gitoid(
mut self,
_default_hash_algorithm: HashAlgorithm,
_default_object_type: ObjectType,
) -> (Self::Id, Result<GitOid>) {
IntoIdentifiedGitOid::into_identified_gitoid((self.0, &mut self.1), self.2, self.3)
}
}