use std::ffi::CStr;
use std::os::raw::c_char;
use std::os::raw::c_int;
use crate::ffi_apis::symbolic_graph_ffi::handle::RssnGraph;
use crate::symbolic::graph::Graph;
use crate::symbolic::graph_algorithms::bfs;
use crate::symbolic::graph_algorithms::bipartite_maximum_matching;
use crate::symbolic::graph_algorithms::connected_components;
use crate::symbolic::graph_algorithms::dfs;
use crate::symbolic::graph_algorithms::dinic_max_flow;
use crate::symbolic::graph_algorithms::edmonds_karp_max_flow;
use crate::symbolic::graph_algorithms::find_bridges_and_articulation_points;
use crate::symbolic::graph_algorithms::has_cycle;
use crate::symbolic::graph_algorithms::is_bipartite;
use crate::symbolic::graph_algorithms::is_connected;
use crate::symbolic::graph_algorithms::kruskal_mst;
use crate::symbolic::graph_algorithms::strongly_connected_components;
use crate::symbolic::graph_algorithms::topological_sort;
#[unsafe(no_mangle)]
pub extern "C" fn rssn_graph_dfs_api(
graph: *const RssnGraph,
start_node: usize,
) -> *mut c_char {
if graph.is_null() {
return std::ptr::null_mut();
}
unsafe {
let g = &*graph.cast::<Graph<String>>();
let result = dfs(g, start_node);
let json = serde_json::to_string(&result).unwrap_or_default();
std::ffi::CString::new(json).unwrap().into_raw()
}
}
#[unsafe(no_mangle)]
pub extern "C" fn rssn_graph_bfs_api(
graph: *const RssnGraph,
start_node: usize,
) -> *mut c_char {
if graph.is_null() {
return std::ptr::null_mut();
}
unsafe {
let g = &*graph.cast::<Graph<String>>();
let result = bfs(g, start_node);
let json = serde_json::to_string(&result).unwrap_or_default();
std::ffi::CString::new(json).unwrap().into_raw()
}
}
#[unsafe(no_mangle)]
pub extern "C" fn rssn_graph_connected_components_api(graph: *const RssnGraph) -> *mut c_char {
if graph.is_null() {
return std::ptr::null_mut();
}
unsafe {
let g = &*graph.cast::<Graph<String>>();
let result = connected_components(g);
let json = serde_json::to_string(&result).unwrap_or_default();
std::ffi::CString::new(json).unwrap().into_raw()
}
}
#[unsafe(no_mangle)]
pub extern "C" fn rssn_graph_is_connected(graph: *const RssnGraph) -> c_int {
if graph.is_null() {
return 0;
}
unsafe {
let g = &*graph.cast::<Graph<String>>();
i32::from(is_connected(g))
}
}
#[unsafe(no_mangle)]
pub extern "C" fn rssn_graph_strongly_connected_components(graph: *const RssnGraph) -> *mut c_char {
if graph.is_null() {
return std::ptr::null_mut();
}
unsafe {
let g = &*graph.cast::<Graph<String>>();
let result = strongly_connected_components(g);
let json = serde_json::to_string(&result).unwrap_or_default();
std::ffi::CString::new(json).unwrap().into_raw()
}
}
#[unsafe(no_mangle)]
pub extern "C" fn rssn_graph_has_cycle_api(graph: *const RssnGraph) -> c_int {
if graph.is_null() {
return 0;
}
unsafe {
let g = &*graph.cast::<Graph<String>>();
i32::from(has_cycle(g))
}
}
#[unsafe(no_mangle)]
pub extern "C" fn rssn_graph_bridges_and_articulation_points_api(
graph: *const RssnGraph
) -> *mut c_char {
#[derive(serde::Serialize)]
struct BridgesResult {
bridges: Vec<(usize, usize)>,
articulation_points: Vec<usize>,
}
if graph.is_null() {
return std::ptr::null_mut();
}
unsafe {
let g = &*graph.cast::<Graph<String>>();
let (bridges, aps) = find_bridges_and_articulation_points(g);
let result = BridgesResult {
bridges,
articulation_points: aps,
};
let json = serde_json::to_string(&result).unwrap_or_default();
std::ffi::CString::new(json).unwrap().into_raw()
}
}
#[unsafe(no_mangle)]
pub extern "C" fn rssn_graph_kruskal_mst_api(graph: *const RssnGraph) -> *mut RssnGraph {
if graph.is_null() {
return std::ptr::null_mut();
}
unsafe {
let g = &*graph.cast::<Graph<String>>();
let mst_edges = kruskal_mst(g);
let mut mst_graph = Graph::new(g.is_directed);
for node in &g.nodes {
mst_graph.add_node(node.clone());
}
for (u, v, weight) in mst_edges {
mst_graph.add_edge(&g.nodes[u], &g.nodes[v], weight);
}
Box::into_raw(Box::new(mst_graph)).cast::<RssnGraph>()
}
}
#[unsafe(no_mangle)]
pub extern "C" fn rssn_graph_edmonds_karp_max_flow(
graph: *const RssnGraph,
source: usize,
sink: usize,
) -> f64 {
if graph.is_null() {
return 0.0;
}
unsafe {
let g = &*graph.cast::<Graph<String>>();
edmonds_karp_max_flow(g, source, sink)
}
}
#[unsafe(no_mangle)]
pub extern "C" fn rssn_graph_dinic_max_flow(
graph: *const RssnGraph,
source: usize,
sink: usize,
) -> f64 {
if graph.is_null() {
return 0.0;
}
unsafe {
let g = &*graph.cast::<Graph<String>>();
dinic_max_flow(g, source, sink)
}
}
#[unsafe(no_mangle)]
pub extern "C" fn rssn_graph_is_bipartite_api(graph: *const RssnGraph) -> *mut c_char {
if graph.is_null() {
return std::ptr::null_mut();
}
unsafe {
let g = &*graph.cast::<Graph<String>>();
match is_bipartite(g) {
| Some(partition) => {
let json = serde_json::to_string(&partition).unwrap_or_default();
std::ffi::CString::new(json).unwrap().into_raw()
},
| None => std::ptr::null_mut(),
}
}
}
#[unsafe(no_mangle)]
pub extern "C" fn rssn_graph_bipartite_maximum_matching(
graph: *const RssnGraph,
partition_json: *const c_char,
) -> *mut c_char {
if graph.is_null() || partition_json.is_null() {
return std::ptr::null_mut();
}
unsafe {
let g = &*graph.cast::<Graph<String>>();
let partition_str = CStr::from_ptr(partition_json).to_str().unwrap_or("");
let partition: Vec<i8> = match serde_json::from_str(partition_str) {
| Ok(p) => p,
| Err(_) => return std::ptr::null_mut(),
};
let matching = bipartite_maximum_matching(g, &partition);
let json = serde_json::to_string(&matching).unwrap_or_default();
std::ffi::CString::new(json).unwrap().into_raw()
}
}
#[unsafe(no_mangle)]
pub extern "C" fn rssn_graph_topological_sort(graph: *const RssnGraph) -> *mut c_char {
if graph.is_null() {
return std::ptr::null_mut();
}
unsafe {
let g = &*graph.cast::<Graph<String>>();
match topological_sort(g) {
| Some(order) => {
let json = serde_json::to_string(&order).unwrap_or_default();
std::ffi::CString::new(json).unwrap().into_raw()
},
| None => std::ptr::null_mut(),
}
}
}
#[unsafe(no_mangle)]
pub extern "C" fn rssn_free_string_api(ptr: *mut c_char) {
if !ptr.is_null() {
unsafe {
let _ = std::ffi::CString::from_raw(ptr);
}
}
}