Skip to content

Commit

Permalink
refactor: simpler buffer handling with dynamic dispatch (#17)
Browse files Browse the repository at this point in the history
* refactor(io): drop boilerplate enums

* refactor(io): use dynamic dispatch for io types

* fix: drop io mod
  • Loading branch information
cmdoret authored Jun 19, 2024
1 parent ec7c831 commit 0863e1a
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 163 deletions.
11 changes: 6 additions & 5 deletions src/converter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,19 @@
//! This module contains the `RdfIO` trait which is used to parse and serialize RDF graphs.
//! Each RDF serialization format should implement this trait.
//!
use std::io::{BufRead, Write};
use std::boxed::Box;

use crate::io::{Input, Output};
use sophia::api::prelude::TripleParser;
use sophia::api::serializer::TripleSerializer;
use sophia::api::source::TripleSource;
use sophia::inmem::graph::FastGraph;

/// The `RdfIO` trait is used to parse and serialize RDF graphs.
pub trait RdfIO<'a, P: TripleParser<Input>, F: TripleSerializer> {
pub trait RdfIO<'a, P: TripleParser<Box<dyn BufRead>>, F: TripleSerializer> {
/// Parse an RDF graph from an input source to an in-memory graph.
fn parse(&self, input: Input) -> Result<FastGraph, String> {
fn parse(&self, input: Box<dyn BufRead>) -> Result<FastGraph, String> {
let mut graph = FastGraph::new();
match self.parser().parse(input).add_to_graph(&mut graph) {
Ok(_) => Ok(graph),
Expand All @@ -40,7 +41,7 @@ pub trait RdfIO<'a, P: TripleParser<Input>, F: TripleSerializer> {
}

/// Serialize an in-memory RDF graph to an output source.
fn serialize(&self, writer: Output, graph: FastGraph) -> Result<(), String> {
fn serialize(&self, writer: Box<dyn Write>, graph: FastGraph) -> Result<(), String> {
let mut formatter = self.serializer(writer);
match formatter.serialize_graph(&graph) {
Ok(_) => Ok(()),
Expand All @@ -52,5 +53,5 @@ pub trait RdfIO<'a, P: TripleParser<Input>, F: TripleSerializer> {
fn parser(&self) -> P;

/// Create a new serializer for this format.
fn serializer(&self, writer: Output) -> F;
fn serializer(&self, writer: Box<dyn Write>) -> F;
}
23 changes: 14 additions & 9 deletions src/formats.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@
//! # Implementation of concrete RDF formats
//!
//! This module implements `RdfIO` trait for each RDF serialization format.
use std::io::{BufRead, Write};

use crate::cli::GraphFormat;
use crate::converter::RdfIO;
use crate::io::{Input, Output};
use sophia::inmem::graph::FastGraph;
use sophia::turtle::parser::nt::NTriplesParser;
use sophia::turtle::parser::turtle::TurtleParser;
Expand All @@ -40,7 +41,7 @@ pub struct RdfParser {
}

impl RdfParser {
pub fn new(input: Input, format: GraphFormat) -> Result<Self, String> {
pub fn new(input: Box<dyn BufRead>, format: GraphFormat) -> Result<Self, String> {
let graph = match format {
GraphFormat::NTriples => NTriples.parse(input),
GraphFormat::Turtle => Turtle.parse(input),
Expand All @@ -55,40 +56,44 @@ impl RdfParser {
pub struct RdfSerializer;

impl RdfSerializer {
pub fn serialize(dest: Output, format: GraphFormat, graph: FastGraph) -> Result<(), String> {
pub fn serialize(
dest: Box<dyn Write>,
format: GraphFormat,
graph: FastGraph,
) -> Result<(), String> {
match format {
GraphFormat::NTriples => NTriples.serialize(dest, graph),
GraphFormat::Turtle => Turtle.serialize(dest, graph),
GraphFormat::RdfXml => RdfXml.serialize(dest, graph),
}
}
}
impl<'a> RdfIO<'a, NTriplesParser, NtSerializer<Output>> for NTriples {
impl<'a> RdfIO<'a, NTriplesParser, NtSerializer<Box<dyn Write>>> for NTriples {
fn parser(&self) -> NTriplesParser {
NTriplesParser {}
}

fn serializer(&self, writer: Output) -> NtSerializer<Output> {
fn serializer(&self, writer: Box<dyn Write>) -> NtSerializer<Box<dyn Write>> {
NtSerializer::new(writer)
}
}

impl<'a> RdfIO<'a, TurtleParser, TurtleSerializer<Output>> for Turtle {
impl<'a> RdfIO<'a, TurtleParser, TurtleSerializer<Box<dyn Write>>> for Turtle {
fn parser(&self) -> TurtleParser {
TurtleParser { base: None }
}

fn serializer(&self, writer: Output) -> TurtleSerializer<Output> {
fn serializer(&self, writer: Box<dyn Write>) -> TurtleSerializer<Box<dyn Write>> {
TurtleSerializer::new(writer)
}
}

impl<'a> RdfIO<'a, RdfXmlParser, RdfXmlSerializer<Output>> for RdfXml {
impl<'a> RdfIO<'a, RdfXmlParser, RdfXmlSerializer<Box<dyn Write>>> for RdfXml {
fn parser(&self) -> RdfXmlParser {
RdfXmlParser { base: None }
}

fn serializer(&self, writer: Output) -> RdfXmlSerializer<Output> {
fn serializer(&self, writer: Box<dyn Write>) -> RdfXmlSerializer<Box<dyn Write>> {
RdfXmlSerializer::new(writer)
}
}
145 changes: 0 additions & 145 deletions src/io.rs

This file was deleted.

11 changes: 7 additions & 4 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,13 @@
mod cli;
mod converter;
mod formats;
mod io;

use crate::cli::{Args, GraphFormat};
use crate::io::{Input, Output};
use clap::Parser;
use formats::{RdfParser, RdfSerializer};
use std::error::Error;
use std::fs::File;
use std::io::{BufRead, BufReader, BufWriter, stdout};
use std::path::Path;

/// Infer RDF serialization format from file extension
Expand All @@ -87,8 +87,11 @@ fn main() -> Result<(), Box<dyn Error>> {
};
let output_format = args.output_format;

let input = Input::new(args.input_file);
let output = Output::new(None);
let input: Box<dyn BufRead> = match args.input_file.unwrap().as_ref() {
"-" => Box::new(BufReader::new(std::io::stdin())),
path => Box::new(BufReader::new(File::open(path)?)),
};
let output = Box::new(BufWriter::new(stdout()));
let parser = RdfParser::new(input, input_format)?;
if !args.no_out {
RdfSerializer::serialize(output, output_format, parser.graph)?;
Expand Down

0 comments on commit 0863e1a

Please sign in to comment.