snark-tool 0.4.0

snark-tool library contains structures and algorithm for (mainly) cubic graph analysis
Documentation
use std::fs::OpenOptions;
use std::io::Write;
use std::path;
use std::{io, marker, result};

use crate::graph::edge::Edge;
use crate::graph::graph;
use crate::graph::vertex::Vertex;
use crate::service::io::error::WriteError;
use crate::service::io::reader_ba;

type Result<T> = result::Result<T, WriteError>;

pub struct BaWriter<G>
where
    G: graph::Graph,
{
    _ph: marker::PhantomData<G>,
}

impl<G> BaWriter<G>
where
    G: graph::Graph,
{
    pub fn write_graphs_to_file<P>(
        graphs: &Vec<(G, P)>,
        path: impl AsRef<path::Path>,
    ) -> Result<()> {
        let file_result = OpenOptions::new().read(true).open(&path);
        if let Err(err) = &file_result {
            if err.kind() == io::ErrorKind::NotFound {
                return BaWriter::write_graphs_to_new_file(graphs, path);
            }
        }
        file_result?;
        return BaWriter::append_graphs_to_file(graphs, path);
    }

    fn write_graphs_to_new_file<P>(
        graphs: &Vec<(G, P)>,
        path: impl AsRef<path::Path>,
    ) -> Result<()> {
        let mut file = OpenOptions::new().create(true).write(true).open(&path)?;
        writeln!(file, "{}", graphs.len())?;
        let mut index = 0;
        for graph in graphs {
            index += 1;
            BaWriter::write_graph_ba(&graph.0, (index) as u32, &mut file)?;
        }
        Ok(())
    }

    fn append_graphs_to_file<P>(graphs: &Vec<(G, P)>, path: impl AsRef<path::Path>) -> Result<()> {
        let file = OpenOptions::new().read(true).open(&path)?;
        // let count_preface = get_graphs_count_with_preface(&file)?;
        let count_preface = reader_ba::read_preface_and_count(&file)?;
        let mut count = count_preface.0;
        let preface = count_preface.1;
        let new_count = count + graphs.len();
        BaWriter::<G>::update_graphs_count(&path, new_count, preface)?;
        let mut file = OpenOptions::new().append(true).open(&path)?;
        for graph in graphs {
            count += 1;
            BaWriter::write_graph_ba(&graph.0, (count) as u32, &mut file)?;
        }
        Ok(())
    }

    pub fn write_graph_ba(graph: &G, index: u32, mut buffer: impl io::Write) -> Result<()> {
        writeln!(buffer)?;
        writeln!(buffer, "{}", index)?;
        writeln!(buffer, "{}", graph.size())?;

        for vertex in graph.vertices() {
            for edges_of_vertex in graph.edges_of_vertex(vertex.index()) {
                if edges_of_vertex.from() == vertex.index() {
                    write!(buffer, "{} ", edges_of_vertex.to())?;
                } else {
                    write!(buffer, "{} ", edges_of_vertex.from())?;
                }
            }
            writeln!(buffer)?;
        }
        Ok(())
    }

    fn update_graphs_count(
        path: impl AsRef<path::Path>,
        new_count: usize,
        preface: String,
    ) -> Result<()> {
        let file = OpenOptions::new().write(true).open(path)?;
        let mut writer = io::LineWriter::new(file);
        writer.write_all(preface.as_bytes())?;
        let count_str = format!("{}", new_count);
        writer.write_all(count_str.as_bytes())?;
        Ok(())
    }
}