use std::collections::{BTreeSet, HashMap};
use std::fs::File;
use std::io::{BufRead, BufReader};
use std::path::PathBuf;
use crate::types::VertexKey;
use super::bulk_loader::{BulkEdge, BulkVertex};
pub struct EdgeListSource {
pub path: PathBuf,
pub vertex_label: String,
pub edge_label: String,
pub comment_char: char,
}
impl EdgeListSource {
pub fn open(self) -> std::io::Result<(Vec<BulkVertex>, EdgeListIter)> {
let mut ids = BTreeSet::new();
let file = File::open(&self.path)?;
for line in BufReader::new(file).lines() {
let line = line?;
let trimmed = line.trim();
if trimmed.is_empty() || trimmed.starts_with(self.comment_char) {
continue;
}
let mut parts = trimmed.split_whitespace();
if let (Some(s), Some(d)) = (parts.next(), parts.next()) {
if let (Ok(src), Ok(dst)) = (s.parse::<i64>(), d.parse::<i64>()) {
ids.insert(src as VertexKey);
ids.insert(dst as VertexKey);
}
}
}
let vertices: Vec<BulkVertex> = ids
.into_iter()
.map(|id| BulkVertex { id, label: self.vertex_label.clone(), props: HashMap::new() })
.collect();
let file = File::open(&self.path)?;
let edge_iter =
EdgeListIter { reader: BufReader::new(file), edge_label: self.edge_label, comment_char: self.comment_char };
Ok((vertices, edge_iter))
}
}
pub struct EdgeListIter {
reader: BufReader<File>,
edge_label: String,
comment_char: char,
}
impl Iterator for EdgeListIter {
type Item = BulkEdge;
fn next(&mut self) -> Option<Self::Item> {
let mut line = String::new();
loop {
line.clear();
match self.reader.read_line(&mut line) {
Ok(0) | Err(_) => return None,
Ok(_) => {}
}
let trimmed = line.trim();
if trimmed.is_empty() || trimmed.starts_with(self.comment_char) {
continue;
}
let mut parts = trimmed.split_whitespace();
if let (Some(s), Some(d)) = (parts.next(), parts.next()) {
if let (Ok(src), Ok(dst)) = (s.parse::<i64>(), d.parse::<i64>()) {
return Some(BulkEdge {
src: src as VertexKey,
dst: dst as VertexKey,
label: self.edge_label.clone(),
props: HashMap::new(),
rank: None,
});
}
}
}
}
}