use pyo3::exceptions::PyRuntimeError;
use pyo3::prelude::*;
use crate::core::single_file::SingleFileDB as RustSingleFileDB;
use crate::types::{ETypeId, NodeId, PropKeyId, PropValue};
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 out_edges_impl(&self, node_id: i64) -> PyResult<Vec<Edge>>;
fn 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 upsert_edge_single(
db: &RustSingleFileDB,
src: NodeId,
etype: ETypeId,
dst: NodeId,
props: &[(PropKeyId, Option<PropValue>)],
) -> PyResult<bool> {
db.upsert_edge_with_props(src, etype, dst, props.iter().cloned())
.map_err(|e| PyRuntimeError::new_err(format!("Failed to upsert edge: {e}")))
}
pub fn edge_exists_single(db: &RustSingleFileDB, src: NodeId, etype: ETypeId, dst: NodeId) -> bool {
db.edge_exists(src, etype, dst)
}
pub fn out_edges_single(db: &RustSingleFileDB, node_id: NodeId) -> Vec<Edge> {
db.out_edges(node_id)
.into_iter()
.map(|(etype, dst)| Edge {
etype,
node_id: dst as i64,
})
.collect()
}
pub fn in_edges_single(db: &RustSingleFileDB, node_id: NodeId) -> Vec<Edge> {
db.in_edges(node_id)
.into_iter()
.map(|(etype, src)| Edge {
etype,
node_id: src as i64,
})
.collect()
}
pub fn out_degree_single(db: &RustSingleFileDB, node_id: NodeId) -> i64 {
db.out_degree(node_id) as i64
}
pub fn in_degree_single(db: &RustSingleFileDB, node_id: NodeId) -> i64 {
db.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()
}
#[cfg(test)]
mod tests {
}