use gix::Repository;
use super::{
Replica,
entity::{Entity, EntityRead, id::entity_id::EntityId, read},
get,
};
use crate::replica::entity::id::Id;
#[derive(Debug)]
pub(super) struct EntityIdIter<E: Entity> {
ids: Vec<Result<EntityId<E>, get::Error>>,
}
impl<E: Entity> EntityIdIter<E> {
pub(super) fn new(repo: &Repository) -> Result<Self, get::Error> {
let ids = {
repo.references()
.map_err(get::Error::PackedBufferOpen)?
.prefixed(format!("refs/{}/", E::NAMESPACE).as_bytes())
.map_err(|err| get::Error::RefsIterPrefixed {
nasp: E::NAMESPACE,
error: err,
})?
.map(|maybe_ref| {
let reference = maybe_ref.map_err(|err| get::Error::RefGet(err.to_string()))?;
let name = reference.name();
let id = name.file_name();
let id = {
Id::from_hex(id).map_err(|err| get::Error::ParseAsHex {
id: id.to_string(),
error: err,
})?
};
Ok::<EntityId<E>, get::Error>(unsafe { EntityId::from_id(id) })
})
.collect::<Vec<_>>()
};
Ok(Self { ids })
}
}
impl<E: Entity> Iterator for EntityIdIter<E> {
type Item = Result<EntityId<E>, get::Error>;
fn next(&mut self) -> Option<Self::Item> {
self.ids.pop()
}
}
#[derive(Debug)]
pub(super) struct EntityIter<'a, E: Entity> {
replica: &'a Replica,
inner: EntityIdIter<E>,
}
impl<E: Entity + EntityRead> Iterator for EntityIter<'_, E> {
type Item = Result<Result<E, read::Error<E>>, get::Error>;
fn next(&mut self) -> Option<Self::Item> {
self.inner
.next()
.map(|next| next.map(|value| E::read(self.replica, value)))
}
}
impl<'a, E: Entity + EntityRead> EntityIter<'a, E> {
pub(super) fn new(replica: &'a Replica) -> Result<Self, get::Error> {
let inner = EntityIdIter::new(replica.repo())?;
Ok(Self { replica, inner })
}
}