use std::io::Read;
pub use oxrdf::{BlankNode, Literal, NamedNode, NamedOrBlankNode, Term, Triple};
use crate::IcddError;
pub const MAX_RDF_TRIPLES: usize = 1_000_000;
#[derive(Debug, Clone, Default)]
pub struct RdfXmlOptions {
base_iri: Option<String>,
prefixes: Vec<(String, String)>,
}
impl RdfXmlOptions {
#[must_use]
pub fn new() -> Self {
Self::default()
}
#[must_use]
pub fn with_base_iri(mut self, iri: impl Into<String>) -> Self {
self.base_iri = Some(iri.into());
self
}
#[must_use]
pub fn with_prefix(mut self, prefix: impl Into<String>, iri: impl Into<String>) -> Self {
self.prefixes.push((prefix.into(), iri.into()));
self
}
}
pub fn parse_rdf_xml(reader: impl Read) -> Result<Vec<Triple>, IcddError> {
let mut triples = Vec::new();
for triple in oxrdfxml::RdfXmlParser::new().for_reader(reader) {
if triples.len() == MAX_RDF_TRIPLES {
return Err(IcddError::NotConformant(format!(
"RDF graph exceeds the {MAX_RDF_TRIPLES}-triple limit"
)));
}
triples.push(triple.map_err(|error| IcddError::Rdf(error.to_string()))?);
}
Ok(triples)
}
pub fn serialize_rdf_xml(triples: &[Triple], options: RdfXmlOptions) -> Result<Vec<u8>, IcddError> {
let mut config = oxrdfxml::RdfXmlSerializer::new();
if let Some(base_iri) = options.base_iri {
config = config
.with_base_iri(base_iri)
.map_err(|error| IcddError::Rdf(error.to_string()))?;
}
for (prefix, iri) in options.prefixes {
config = config
.with_prefix(prefix, iri)
.map_err(|error| IcddError::Rdf(error.to_string()))?;
}
let mut ordered = triples.iter().collect::<Vec<_>>();
ordered.sort_by_cached_key(ToString::to_string);
let mut serializer = config.for_writer(Vec::new());
for triple in ordered {
serializer
.serialize_triple(triple.as_ref())
.map_err(|error| IcddError::Rdf(error.to_string()))?;
}
serializer
.finish()
.map_err(|error| IcddError::Rdf(error.to_string()))
}