use std::ffi::{c_char, CStr}; use std::iter::Iterator; use std::ptr; use crate::graph::Graph; #[allow(non_camel_case_types)] enum geng_iterator {} extern "C" { fn geng_iterator_create( iter: *const *mut geng_iterator, graph_size: usize, batch_size: usize, ); fn geng_iterator_next(iter: *const geng_iterator, g: *mut u32) -> bool; fn geng_iterator_destroy(iter: *const geng_iterator); fn fill_matrix(g: *const u32, n: usize, mat: *mut *mut u32); fn ntog6(g: *const u32, m: usize, n: usize) -> *const c_char; } pub fn get_g6(g: Vec, n: usize) -> String { let s = unsafe { ntog6(g.as_ptr(), 1, n) }; // TODO: free allocated s? ^ let s = unsafe { CStr::from_ptr(s) }; s.to_str().unwrap().trim().to_string() } pub struct GengIterator { pub size: usize, iter: Box, } impl GengIterator { pub fn new(n: usize) -> GengIterator { let iter = unsafe { let iter: *mut geng_iterator = ptr::null_mut(); geng_iterator_create(&iter, n, 10000); Box::from_raw(iter) }; GengIterator { size: n, iter } } } impl Iterator for &GengIterator { type Item = Graph; fn next(&mut self) -> Option { let mut g = vec![0; self.size]; let res = unsafe { let ptr: *const geng_iterator = &*self.iter; geng_iterator_next(ptr, g.as_mut_ptr()) }; if res { let mut mat = vec![vec![0; self.size]; self.size]; unsafe { fill_matrix( g.as_ptr(), self.size, mat.iter_mut() .map(Vec::as_mut_ptr) .collect::>() .as_mut_ptr(), ); } Some(Graph { size: self.size, matrix: mat, }) } else { None } } } impl Drop for GengIterator { fn drop(&mut self) { unsafe { let ptr: *const geng_iterator = &*self.iter; geng_iterator_destroy(ptr); } } }