Skip to content

Commit

Permalink
refactor(rdf): created module rdf and moved some source files into …
Browse files Browse the repository at this point in the history
…that
  • Loading branch information
jgeluk committed Sep 25, 2022
1 parent 0d848a0 commit b5b9ae1
Show file tree
Hide file tree
Showing 9 changed files with 199 additions and 45 deletions.
4 changes: 2 additions & 2 deletions src/cursor/cursor_row.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@
use std::{ffi::c_ulong, ptr};

use crate::{
cursor::ResourceValue,
database_call,
root::{CCursor_getResourceLexicalForm, CCursor_getResourceValue, CDatatypeID},
DataType,
Error,
Error::Unknown,
LexicalValue,
OpenedCursor,
ResourceValue,
};

#[derive(Debug)]
Expand Down Expand Up @@ -148,7 +148,7 @@ impl<'a> CursorRow<'a> {
rowid = self.rowid,
multiplicity = self.multiplicity
);
if let Some(resource_id)= resource_id {
if let Some(resource_id) = resource_id {
self.lexical_value_with_id(resource_id)
} else {
Ok(None)
Expand Down
39 changes: 5 additions & 34 deletions src/cursor/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,45 +2,16 @@
//---------------------------------------------------------------

use std::ffi::CStr;

pub use cursor::Cursor;
pub use opened_cursor::OpenedCursor;
pub use cursor_row::CursorRow;
use crate::{DataType, Error};
use crate::Error::Unknown;
pub use opened_cursor::OpenedCursor;

use crate::Error;

mod cursor;
mod opened_cursor;
mod cursor_row;

#[derive(Debug)]
pub struct ResourceValue {
pub data_type: DataType,
pub namespace: Option<&'static str>,
pub value: &'static str,
}

impl ResourceValue {

pub fn from(
data_type: DataType,
namespace: *const u8, namespace_len: usize,
data: *const u8, data_len: usize
) -> Result<Self, Error> {
let ns = if namespace_len == 0 {
None
} else {
Some(ptr_to_cstr(namespace, namespace_len + 1)?.to_str().map_err(|err| {
log::error!("Couldn't convert namespace due to UTF-8 error: {err:?}");
Unknown
})?)
};
Ok(Self {
data_type,
namespace: ns,
value: ptr_to_cstr(data, data_len)?.to_str().unwrap(),
})
}
}
mod opened_cursor;

pub fn ptr_to_cstr<'b>(data: *const u8, len: usize) -> Result<&'b CStr, Error> {
unsafe {
Expand Down
8 changes: 3 additions & 5 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,21 @@ extern crate core;
use core::str::FromStr;

pub use class::Class;
pub use cursor::{Cursor, CursorRow, OpenedCursor, ResourceValue};
pub use cursor::{Cursor, CursorRow, OpenedCursor};
pub use data_store::DataStore;
pub use data_store_connection::DataStoreConnection;
pub use data_type::DataType;
pub use error::Error;
pub use exception::CException;
pub use graph::{Graph, DEFAULT_GRAPH, NS_RDFOX};
pub use graph_connection::GraphConnection;
use lazy_static::lazy_static;
pub use lexical_value::LexicalValue;
pub use license::{find_license, RDFOX_DEFAULT_LICENSE_FILE_NAME, RDFOX_HOME};
pub use mime::Mime;
pub use namespace::*;
pub use parameters::{FactDomain, Parameters, PersistenceMode};
pub use predicate::Predicate;
pub use prefixes::{Prefix, Prefixes, PrefixesBuilder};
pub use rdf::{DataType, LexicalValue, ResourceValue, Term};
pub use role_creds::RoleCreds;
pub use server::Server;
pub use server_connection::ServerConnection;
Expand Down Expand Up @@ -72,17 +71,16 @@ mod class;
mod cursor;
mod data_store;
mod data_store_connection;
mod data_type;
mod error;
mod exception;
mod graph;
mod graph_connection;
mod lexical_value;
mod license;
mod namespace;
mod parameters;
mod predicate;
mod prefixes;
mod rdf;
mod role_creds;
mod server;
mod server_connection;
Expand Down
File renamed without changes.
24 changes: 23 additions & 1 deletion src/lexical_value.rs → src/rdf/lexical_value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use std::{
str::FromStr,
};

use iref::IriBuf;
use iref::{Iri, IriBuf};

use crate::{DataType, Error, Error::Unknown};

Expand Down Expand Up @@ -283,4 +283,26 @@ impl LexicalValue {
},
}
}

pub fn from_iri(iri: &Iri) -> Result<Self, Error> {
Ok(LexicalValue {
data_type: DataType::IriReference,
value: LexicalValueUnion {
iri: ManuallyDrop::new(IriBuf::from(iri)),
},
})
}
}

impl FromStr for LexicalValue {
type Err = Error;

fn from_str(str: &str) -> Result<Self, Self::Err> {
Ok(LexicalValue {
data_type: DataType::String,
value: LexicalValueUnion {
string: ManuallyDrop::new(str.to_string()),
},
})
}
}
11 changes: 11 additions & 0 deletions src/rdf/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Copyright (c) 2018-2022, agnos.ai UK Ltd, all rights reserved.
//---------------------------------------------------------------
mod data_type;
mod lexical_value;
mod resource_value;
mod term;

pub use data_type::DataType;
pub use lexical_value::LexicalValue;
pub use resource_value::ResourceValue;
pub use term::Term;
39 changes: 39 additions & 0 deletions src/rdf/resource_value.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright (c) 2018-2022, agnos.ai UK Ltd, all rights reserved.
//---------------------------------------------------------------
use super::DataType;
use crate::{cursor, Error, Error::Unknown};

#[derive(Debug)]
pub struct ResourceValue {
pub data_type: DataType,
pub namespace: Option<&'static str>,
pub value: &'static str,
}

impl ResourceValue {
pub fn from(
data_type: DataType,
namespace: *const u8,
namespace_len: usize,
data: *const u8,
data_len: usize,
) -> Result<Self, Error> {
let ns = if namespace_len == 0 {
None
} else {
Some(
cursor::ptr_to_cstr(namespace, namespace_len + 1)?
.to_str()
.map_err(|err| {
log::error!("Couldn't convert namespace due to UTF-8 error: {err:?}");
Unknown
})?,
)
};
Ok(Self {
data_type,
namespace: ns,
value: cursor::ptr_to_cstr(data, data_len)?.to_str().unwrap(),
})
}
}
113 changes: 113 additions & 0 deletions src/rdf/term.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
use std::str::FromStr;

// Copyright (c) 2018-2022, agnos.ai UK Ltd, all rights reserved.
//---------------------------------------------------------------
use iref::Iri;

use super::LexicalValue;
use crate::Error;

/// An RDF Term is either an IRI, a literal or a blank node.
/// See https://www.w3.org/TR/rdf11-concepts/#section-triples
pub enum Term {
Iri(LexicalValue),
Literal(LexicalValue),
BlankNode(LexicalValue),
}

impl Term {
pub fn new_iri(iri: &Iri) -> Result<Self, Error> { Ok(Term::Iri(LexicalValue::from_iri(iri)?)) }

pub fn new_str(str: &str) -> Result<Self, Error> {
Ok(Term::Literal(LexicalValue::from_str(str)?))
}

pub fn display_turtle<'a, 'b>(&'a self) -> impl std::fmt::Display + 'a + 'b
where 'a: 'b {
struct TurtleTerm<'b>(&'b Term);
impl<'b> std::fmt::Display for TurtleTerm<'b> {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
let value = match self.0 {
Term::Iri(value) => value,
Term::Literal(value) => value,
Term::BlankNode(value) => value,
};
write!(f, "{:?}", value)
}
}
TurtleTerm(self)
}
}

impl FromStr for Term {
type Err = Error;

fn from_str(str: &str) -> Result<Self, Self::Err> { Term::new_str(str) }
}

#[cfg(test)]
mod tests {
use iref::Iri;

use crate::{rdf::Term, Error};

#[test_log::test]
fn test_term_01() {
let term = Term::new_iri(&Iri::new("https://whatever.url").unwrap()).unwrap();

let turtle = format!("{}", term.display_turtle());

assert_eq!(turtle, "<https://whatever.url>");
}

#[test_log::test]
fn test_term_02() {
let term = Term::new_iri(&Iri::new("unknown-protocol://whatever.url").unwrap()).unwrap();

let turtle = format!("{}", term.display_turtle());

assert_eq!(turtle, "<unknown-protocol://whatever.url>");
}

#[test_log::test]
fn test_term_03() {
// At the moment, we're even accepting wrongly formatted IRIs, we may want to
// validate each IRI
let term = Term::new_iri(&Iri::new("https:/x/whatever.url").unwrap()).unwrap();

let turtle = format!("{}", term.display_turtle());

assert_eq!(turtle, "<https:/x/whatever.url>");
}

#[test_log::test]
fn test_term_04() {
let term = Term::new_str("some string").unwrap();

let turtle = format!("{}", term.display_turtle());

assert_eq!(turtle, "\"some string\"");
}

#[test_log::test]
fn test_term_05() -> Result<(), Error> {
let term: Term = "some string".parse()?;

let turtle = format!("{}", term.display_turtle());

assert_eq!(turtle, "\"some string\"");

Ok(())
}

#[test_log::test]
fn test_term_06() -> Result<(), Error> {
let term: Term = "\"some string\"^^xsd:string".parse()?;

let turtle = format!("{}", term.display_turtle());

assert_eq!(turtle, "\"\\\"some string\\\"^^xsd:string\""); // TODO: This is incorrect, recognise the XSD data type suffix and process it

Ok(())
}
}
6 changes: 3 additions & 3 deletions tests/load.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,15 @@ fn test_define_data_store() -> Result<DataStore, Error> {
DataStore::declare_with_parameters("example", data_store_params)
}

fn test_create_server() -> Result<Server, Error> {
fn test_create_server() -> Result<Arc<Server>, Error> {
log::info!("test_create_server");
let server_params = &Parameters::empty()?
.api_log(true)?
.api_log_directory(Path::new("./tests"))?;
Server::start_with_parameters(RoleCreds::default(), server_params)
}

fn test_create_server_connection(server: &Server) -> Result<ServerConnection, Error> {
fn test_create_server_connection(server: Arc<Server>) -> Result<ServerConnection, Error> {
log::info!("test_create_server_connection");

let server_connection = server.connection_with_default_role()?;
Expand Down Expand Up @@ -208,7 +208,7 @@ fn test_run_query_to_nquads_buffer(
#[test_log::test]
fn load_rdfox() -> Result<(), Error> {
let server = test_create_server()?;
let server_connection = test_create_server_connection(&server)?;
let server_connection = test_create_server_connection(server.clone())?;

let data_store = test_define_data_store()?;

Expand Down

0 comments on commit b5b9ae1

Please sign in to comment.