#[cfg(feature = "mem_dbg")]
use alloc::{string::String, vec::Vec};
use crate::{
errors::builder::edges::EdgesBuilderError,
impls::MutabilityError,
traits::{Edges, EdgesBuilder, GrowableEdges, SparseMatrixMut},
};
#[cfg_attr(feature = "mem_size", derive(mem_dbg::MemSize))]
#[cfg_attr(feature = "mem_size", mem_size(rec))]
#[cfg_attr(feature = "mem_dbg", derive(mem_dbg::MemDbg))]
pub struct GenericEdgesBuilder<EdgeIterator, GE: GrowableEdges> {
pub(super) edges: Option<EdgeIterator>,
expected_number_of_edges: Option<GE::EdgeId>,
expected_shape: Option<<GE::GrowableMatrix as SparseMatrixMut>::MinimalShape>,
ignore_duplicates: bool,
_edges: core::marker::PhantomData<GE>,
}
impl<EdgeIterator, GE> Clone for GenericEdgesBuilder<EdgeIterator, GE>
where
EdgeIterator: Clone,
GE: GrowableEdges,
GE::EdgeId: Copy,
<GE::GrowableMatrix as SparseMatrixMut>::MinimalShape: Copy,
{
#[inline]
fn clone(&self) -> Self {
Self {
edges: self.edges.clone(),
expected_number_of_edges: self.expected_number_of_edges,
expected_shape: self.expected_shape,
ignore_duplicates: self.ignore_duplicates,
_edges: self._edges,
}
}
}
impl<EdgeIterator, GE> core::fmt::Debug for GenericEdgesBuilder<EdgeIterator, GE>
where
EdgeIterator: core::fmt::Debug,
GE: GrowableEdges,
GE::EdgeId: core::fmt::Debug,
<GE::GrowableMatrix as SparseMatrixMut>::MinimalShape: core::fmt::Debug,
{
#[inline]
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("GenericEdgesBuilder")
.field("edges", &self.edges)
.field("expected_number_of_edges", &self.expected_number_of_edges)
.field("expected_shape", &self.expected_shape)
.field("ignore_duplicates", &self.ignore_duplicates)
.finish()
}
}
impl<EdgeIterator, GE: GrowableEdges> Default for GenericEdgesBuilder<EdgeIterator, GE> {
#[inline]
fn default() -> Self {
Self {
edges: None,
expected_number_of_edges: None,
expected_shape: None,
ignore_duplicates: false,
_edges: core::marker::PhantomData,
}
}
}
impl<EdgeIterator, GE: GrowableEdges> EdgesBuilder for GenericEdgesBuilder<EdgeIterator, GE>
where
GE: GrowableEdges<Error = EdgesBuilderError<GE>>,
EdgeIterator: IntoIterator<Item = GE::Edge>,
{
type EdgeIterator = EdgeIterator;
type IntermediateEdges = GE;
type Edges = GE;
#[inline]
fn expected_number_of_edges(mut self, number_of_edges: GE::EdgeId) -> Self {
self.expected_number_of_edges = Some(number_of_edges);
self
}
#[inline]
fn get_expected_number_of_edges(&self) -> Option<GE::EdgeId> {
self.expected_number_of_edges
}
#[inline]
fn ignore_duplicates(mut self) -> Self {
self.ignore_duplicates = true;
self
}
#[inline]
fn should_ignore_duplicates(&self) -> bool {
self.ignore_duplicates
}
#[inline]
fn expected_shape(
mut self,
shape: <GE::GrowableMatrix as SparseMatrixMut>::MinimalShape,
) -> Self {
self.expected_shape = Some(shape);
self
}
#[inline]
fn get_expected_shape(
&self,
) -> Option<<<GE as GrowableEdges>::GrowableMatrix as SparseMatrixMut>::MinimalShape> {
self.expected_shape
}
#[inline]
fn edges(mut self, edges: Self::EdgeIterator) -> Self {
self.edges = Some(edges);
self
}
}
impl<EdgeIterator, GE> GenericEdgesBuilder<EdgeIterator, GE>
where
GE: GrowableEdges<Error = EdgesBuilderError<GE>>,
GenericEdgesBuilder<EdgeIterator, GE>:
EdgesBuilder<EdgeIterator = EdgeIterator, Edges = GE, IntermediateEdges = GE>,
EdgeIterator: IntoIterator<
Item = <<GenericEdgesBuilder<EdgeIterator, GE> as EdgesBuilder>::Edges as Edges>::Edge,
>,
{
#[inline]
pub fn build(self: GenericEdgesBuilder<EdgeIterator, GE>) -> Result<GE, EdgesBuilderError<GE>> {
let expected_number_of_edges = self.get_expected_number_of_edges();
let mut edges = match (expected_number_of_edges, self.get_expected_shape()) {
(Some(number_of_edges), Some(shape)) => {
GE::with_shaped_capacity(shape, number_of_edges)
}
(Some(number_of_edges), None) => GE::with_capacity(number_of_edges),
(None, Some(shape)) => GE::with_shape(shape),
(None, None) => Default::default(),
};
let should_ignore_duplicates = self.should_ignore_duplicates();
self.edges.ok_or(EdgesBuilderError::MissingAttribute("edges"))?.into_iter().try_for_each(
|edge| {
if let Err(err) = edges.add(edge) {
match err {
crate::errors::builder::edges::EdgesBuilderError::MatrixError(
MutabilityError::DuplicatedEntry(_),
) => {
if should_ignore_duplicates {
Ok(())
} else {
Err(err)
}
}
other => Err(other),
}
} else {
Ok(())
}
},
)?;
if let Some(expected_number_of_edges) = expected_number_of_edges
&& edges.number_of_edges() != expected_number_of_edges
{
return Err(crate::errors::builder::edges::EdgesBuilderError::NumberOfEdges {
expected: expected_number_of_edges,
actual: edges.number_of_edges(),
});
}
Ok(edges)
}
}