use pyo3::exceptions::PyRuntimeError;
use pyo3::prelude::*;
use crate::core::single_file::SingleFileDB as RustSingleFileDB;
use crate::graph::db::GraphDB as RustGraphDB;
use crate::graph::edges::{
add_edge as graph_add_edge, delete_edge as graph_delete_edge, edge_exists_db,
};
use crate::graph::iterators::{
count_edges as graph_count_edges, list_edges as graph_list_edges, list_in_edges, list_out_edges,
ListEdgesOptions,
};
use crate::graph::tx::TxHandle as GraphTxHandle;
use crate::types::{ETypeId, NodeId};
use crate::pyo3_bindings::types::{Edge, FullEdge};
pub trait EdgeOps {
fn add_edge_impl(&self, src: i64, etype: u32, dst: i64) -> PyResult<()>;
fn delete_edge_impl(&self, src: i64, etype: u32, dst: i64) -> PyResult<()>;
fn edge_exists_impl(&self, src: i64, etype: u32, dst: i64) -> PyResult<bool>;
fn get_out_edges_impl(&self, node_id: i64) -> PyResult<Vec<Edge>>;
fn get_in_edges_impl(&self, node_id: i64) -> PyResult<Vec<Edge>>;
fn count_edges_impl(&self) -> PyResult<i64>;
fn list_edges_impl(&self, etype: Option<u32>) -> PyResult<Vec<FullEdge>>;
}
pub fn add_edge_single(
db: &RustSingleFileDB,
src: NodeId,
etype: ETypeId,
dst: NodeId,
) -> PyResult<()> {
db.add_edge(src, etype, dst)
.map_err(|e| PyRuntimeError::new_err(format!("Failed to add edge: {e}")))
}
pub fn add_edge_by_name_single(
db: &RustSingleFileDB,
src: NodeId,
etype_name: &str,
dst: NodeId,
) -> PyResult<()> {
db.add_edge_by_name(src, etype_name, dst)
.map_err(|e| PyRuntimeError::new_err(format!("Failed to add edge: {e}")))
}
pub fn delete_edge_single(
db: &RustSingleFileDB,
src: NodeId,
etype: ETypeId,
dst: NodeId,
) -> PyResult<()> {
db.delete_edge(src, etype, dst)
.map_err(|e| PyRuntimeError::new_err(format!("Failed to delete edge: {e}")))
}
pub fn edge_exists_single(db: &RustSingleFileDB, src: NodeId, etype: ETypeId, dst: NodeId) -> bool {
db.edge_exists(src, etype, dst)
}
pub fn get_out_edges_single(db: &RustSingleFileDB, node_id: NodeId) -> Vec<Edge> {
db.get_out_edges(node_id)
.into_iter()
.map(|(etype, dst)| Edge {
etype,
node_id: dst as i64,
})
.collect()
}
pub fn get_in_edges_single(db: &RustSingleFileDB, node_id: NodeId) -> Vec<Edge> {
db.get_in_edges(node_id)
.into_iter()
.map(|(etype, src)| Edge {
etype,
node_id: src as i64,
})
.collect()
}
pub fn get_out_degree_single(db: &RustSingleFileDB, node_id: NodeId) -> i64 {
db.get_out_degree(node_id) as i64
}
pub fn get_in_degree_single(db: &RustSingleFileDB, node_id: NodeId) -> i64 {
db.get_in_degree(node_id) as i64
}
pub fn count_edges_single(db: &RustSingleFileDB) -> i64 {
db.count_edges() as i64
}
pub fn count_edges_by_type_single(db: &RustSingleFileDB, etype: ETypeId) -> i64 {
db.count_edges_by_type(etype) as i64
}
pub fn list_edges_single(db: &RustSingleFileDB, etype: Option<ETypeId>) -> Vec<FullEdge> {
db.list_edges(etype)
.into_iter()
.map(|e| FullEdge {
src: e.src as i64,
etype: e.etype,
dst: e.dst as i64,
})
.collect()
}
pub fn add_edge_graph(
handle: &mut GraphTxHandle,
src: NodeId,
etype: ETypeId,
dst: NodeId,
) -> PyResult<()> {
graph_add_edge(handle, src, etype, dst)
.map_err(|e| PyRuntimeError::new_err(format!("Failed to add edge: {e}")))?;
Ok(())
}
pub fn delete_edge_graph(
handle: &mut GraphTxHandle,
src: NodeId,
etype: ETypeId,
dst: NodeId,
) -> PyResult<()> {
graph_delete_edge(handle, src, etype, dst)
.map_err(|e| PyRuntimeError::new_err(format!("Failed to delete edge: {e}")))?;
Ok(())
}
pub fn edge_exists_graph(db: &RustGraphDB, src: NodeId, etype: ETypeId, dst: NodeId) -> bool {
edge_exists_db(db, src, etype, dst)
}
pub fn get_out_edges_graph(db: &RustGraphDB, node_id: NodeId) -> Vec<Edge> {
list_out_edges(db, node_id)
.into_iter()
.map(|edge| Edge {
etype: edge.etype,
node_id: edge.dst as i64,
})
.collect()
}
pub fn get_in_edges_graph(db: &RustGraphDB, node_id: NodeId) -> Vec<Edge> {
list_in_edges(db, node_id)
.into_iter()
.map(|edge| Edge {
etype: edge.etype,
node_id: edge.dst as i64,
})
.collect()
}
pub fn get_out_degree_graph(db: &RustGraphDB, node_id: NodeId) -> i64 {
list_out_edges(db, node_id).len() as i64
}
pub fn get_in_degree_graph(db: &RustGraphDB, node_id: NodeId) -> i64 {
list_in_edges(db, node_id).len() as i64
}
pub fn count_edges_graph(db: &RustGraphDB, etype: Option<ETypeId>) -> i64 {
graph_count_edges(db, etype) as i64
}
pub fn list_edges_graph(db: &RustGraphDB, etype: Option<ETypeId>) -> Vec<FullEdge> {
let options = ListEdgesOptions { etype };
graph_list_edges(db, options)
.into_iter()
.map(|e| FullEdge {
src: e.src as i64,
etype: e.etype,
dst: e.dst as i64,
})
.collect()
}
#[cfg(test)]
mod tests {
}