parent
273a13b4e5
commit
0287993dbf
@ -0,0 +1,821 @@ |
|||||||
|
#![allow(dead_code, clippy::inherent_to_string, clippy::unused_self)] |
||||||
|
|
||||||
|
use js_sys::{Error, Reflect, UriError}; |
||||||
|
use oxrdf::Triple; |
||||||
|
use oxrdf::*; |
||||||
|
use wasm_bindgen::prelude::*; |
||||||
|
use wasm_bindgen::JsValue; |
||||||
|
|
||||||
|
#[macro_export] |
||||||
|
macro_rules! format_err { |
||||||
|
($msg:literal $(,)?) => { |
||||||
|
::wasm_bindgen::JsValue::from(::js_sys::Error::new($msg)) |
||||||
|
}; |
||||||
|
($fmt:literal, $($arg:tt)*) => { |
||||||
|
::wasm_bindgen::JsValue::from(::js_sys::Error::new(&format!($fmt, $($arg)*))) |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
#[allow(clippy::needless_pass_by_value)] |
||||||
|
pub fn to_err(e: impl ToString) -> JsValue { |
||||||
|
JsValue::from(Error::new(&e.to_string())) |
||||||
|
} |
||||||
|
|
||||||
|
thread_local! { |
||||||
|
pub static FROM_JS: FromJsConverter = FromJsConverter::default(); |
||||||
|
} |
||||||
|
|
||||||
|
#[wasm_bindgen(js_name = namedNode)] |
||||||
|
pub fn named_node(value: String) -> Result<JsNamedNode, JsValue> { |
||||||
|
NamedNode::new(value) |
||||||
|
.map(Into::into) |
||||||
|
.map_err(|v| UriError::new(&v.to_string()).into()) |
||||||
|
} |
||||||
|
|
||||||
|
#[wasm_bindgen(js_name = blankNode)] |
||||||
|
pub fn blank_node(value: Option<String>) -> Result<JsBlankNode, JsValue> { |
||||||
|
Ok(if let Some(value) = value { |
||||||
|
BlankNode::new(value).map_err(to_err)? |
||||||
|
} else { |
||||||
|
BlankNode::default() |
||||||
|
} |
||||||
|
.into()) |
||||||
|
} |
||||||
|
|
||||||
|
#[wasm_bindgen] |
||||||
|
pub fn literal( |
||||||
|
value: Option<String>, |
||||||
|
language_or_datatype: &JsValue, |
||||||
|
) -> Result<JsLiteral, JsValue> { |
||||||
|
if language_or_datatype.is_null() || language_or_datatype.is_undefined() { |
||||||
|
Ok(Literal::new_simple_literal(value.unwrap_or_default()).into()) |
||||||
|
} else if language_or_datatype.is_string() { |
||||||
|
Ok(Literal::new_language_tagged_literal( |
||||||
|
value.unwrap_or_default(), |
||||||
|
language_or_datatype.as_string().unwrap_or_default(), |
||||||
|
) |
||||||
|
.map_err(to_err)? |
||||||
|
.into()) |
||||||
|
} else if let JsTerm::NamedNode(datatype) = FROM_JS.with(|c| c.to_term(language_or_datatype))? { |
||||||
|
Ok(Literal::new_typed_literal(value.unwrap_or_default(), datatype).into()) |
||||||
|
} else { |
||||||
|
Err(format_err!("The literal datatype should be a NamedNode")) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#[wasm_bindgen(js_name = defaultGraph)] |
||||||
|
pub fn default_graph() -> JsDefaultGraph { |
||||||
|
JsDefaultGraph |
||||||
|
} |
||||||
|
|
||||||
|
#[wasm_bindgen(js_name = variable)] |
||||||
|
pub fn variable(value: String) -> Result<JsVariable, JsValue> { |
||||||
|
Ok(Variable::new(value).map_err(to_err)?.into()) |
||||||
|
} |
||||||
|
|
||||||
|
#[wasm_bindgen(js_name = triple)] |
||||||
|
pub fn triple(subject: &JsValue, predicate: &JsValue, object: &JsValue) -> Result<JsQuad, JsValue> { |
||||||
|
quad(subject, predicate, object, &JsValue::UNDEFINED) |
||||||
|
} |
||||||
|
|
||||||
|
#[wasm_bindgen(js_name = quad)] |
||||||
|
pub fn quad( |
||||||
|
subject: &JsValue, |
||||||
|
predicate: &JsValue, |
||||||
|
object: &JsValue, |
||||||
|
graph: &JsValue, |
||||||
|
) -> Result<JsQuad, JsValue> { |
||||||
|
Ok(FROM_JS |
||||||
|
.with(|c| c.to_quad_from_parts(subject, predicate, object, graph))? |
||||||
|
.into()) |
||||||
|
} |
||||||
|
|
||||||
|
#[wasm_bindgen(js_name = fromTerm)] |
||||||
|
pub fn from_term(original: &JsValue) -> Result<JsValue, JsValue> { |
||||||
|
Ok(if original.is_null() { |
||||||
|
JsValue::NULL |
||||||
|
} else { |
||||||
|
FROM_JS.with(|c| c.to_term(original))?.into() |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
#[wasm_bindgen(js_name = fromQuad)] |
||||||
|
pub fn from_quad(original: &JsValue) -> Result<JsValue, JsValue> { |
||||||
|
Ok(if original.is_null() { |
||||||
|
JsValue::NULL |
||||||
|
} else { |
||||||
|
JsQuad::from(FROM_JS.with(|c| c.to_quad(original))?).into() |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
#[wasm_bindgen(js_name = NamedNode)] |
||||||
|
#[derive(Eq, PartialEq, Debug, Clone, Hash)] |
||||||
|
pub struct JsNamedNode { |
||||||
|
inner: NamedNode, |
||||||
|
} |
||||||
|
|
||||||
|
#[wasm_bindgen(js_class = NamedNode)] |
||||||
|
impl JsNamedNode { |
||||||
|
#[wasm_bindgen(getter = termType)] |
||||||
|
pub fn term_type(&self) -> String { |
||||||
|
"NamedNode".to_owned() |
||||||
|
} |
||||||
|
|
||||||
|
#[wasm_bindgen(getter)] |
||||||
|
pub fn value(&self) -> String { |
||||||
|
self.inner.as_str().to_owned() |
||||||
|
} |
||||||
|
|
||||||
|
#[wasm_bindgen(js_name = toString)] |
||||||
|
pub fn to_string(&self) -> String { |
||||||
|
self.inner.to_string() |
||||||
|
} |
||||||
|
|
||||||
|
pub fn equals(&self, other: &JsValue) -> bool { |
||||||
|
if let Ok(Some(JsTerm::NamedNode(other))) = |
||||||
|
FromJsConverter::default().to_optional_term(other) |
||||||
|
{ |
||||||
|
self == &other |
||||||
|
} else { |
||||||
|
false |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl From<NamedNode> for JsNamedNode { |
||||||
|
fn from(inner: NamedNode) -> Self { |
||||||
|
Self { inner } |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl From<JsNamedNode> for NamedNode { |
||||||
|
fn from(node: JsNamedNode) -> Self { |
||||||
|
node.inner |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl From<JsNamedNode> for NamedOrBlankNode { |
||||||
|
fn from(node: JsNamedNode) -> Self { |
||||||
|
node.inner.into() |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl From<JsNamedNode> for Subject { |
||||||
|
fn from(node: JsNamedNode) -> Self { |
||||||
|
node.inner.into() |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl From<JsNamedNode> for Term { |
||||||
|
fn from(node: JsNamedNode) -> Self { |
||||||
|
node.inner.into() |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl From<JsNamedNode> for GraphName { |
||||||
|
fn from(node: JsNamedNode) -> Self { |
||||||
|
node.inner.into() |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#[wasm_bindgen(js_name = BlankNode)] |
||||||
|
#[derive(Eq, PartialEq, Debug, Clone, Hash)] |
||||||
|
pub struct JsBlankNode { |
||||||
|
inner: BlankNode, |
||||||
|
} |
||||||
|
|
||||||
|
#[wasm_bindgen(js_class = BlankNode)] |
||||||
|
impl JsBlankNode { |
||||||
|
#[wasm_bindgen(getter = termType)] |
||||||
|
pub fn term_type(&self) -> String { |
||||||
|
"BlankNode".to_owned() |
||||||
|
} |
||||||
|
|
||||||
|
#[wasm_bindgen(getter)] |
||||||
|
pub fn value(&self) -> String { |
||||||
|
self.inner.as_str().to_owned() |
||||||
|
} |
||||||
|
|
||||||
|
#[wasm_bindgen(js_name = toString)] |
||||||
|
pub fn to_string(&self) -> String { |
||||||
|
self.inner.to_string() |
||||||
|
} |
||||||
|
|
||||||
|
pub fn equals(&self, other: &JsValue) -> bool { |
||||||
|
if let Ok(Some(JsTerm::BlankNode(other))) = |
||||||
|
FromJsConverter::default().to_optional_term(other) |
||||||
|
{ |
||||||
|
self == &other |
||||||
|
} else { |
||||||
|
false |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl From<BlankNode> for JsBlankNode { |
||||||
|
fn from(inner: BlankNode) -> Self { |
||||||
|
Self { inner } |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl From<JsBlankNode> for BlankNode { |
||||||
|
fn from(node: JsBlankNode) -> Self { |
||||||
|
node.inner |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl From<JsBlankNode> for NamedOrBlankNode { |
||||||
|
fn from(node: JsBlankNode) -> Self { |
||||||
|
node.inner.into() |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl From<JsBlankNode> for Subject { |
||||||
|
fn from(node: JsBlankNode) -> Self { |
||||||
|
node.inner.into() |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl From<JsBlankNode> for Term { |
||||||
|
fn from(node: JsBlankNode) -> Self { |
||||||
|
node.inner.into() |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl From<JsBlankNode> for GraphName { |
||||||
|
fn from(node: JsBlankNode) -> Self { |
||||||
|
node.inner.into() |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#[wasm_bindgen(js_name = Literal)] |
||||||
|
#[derive(Eq, PartialEq, Debug, Clone, Hash)] |
||||||
|
pub struct JsLiteral { |
||||||
|
inner: Literal, |
||||||
|
} |
||||||
|
|
||||||
|
#[wasm_bindgen(js_class = Literal)] |
||||||
|
impl JsLiteral { |
||||||
|
#[wasm_bindgen(getter = termType)] |
||||||
|
pub fn term_type(&self) -> String { |
||||||
|
"Literal".to_owned() |
||||||
|
} |
||||||
|
|
||||||
|
#[wasm_bindgen(getter)] |
||||||
|
pub fn value(&self) -> String { |
||||||
|
self.inner.value().to_owned() |
||||||
|
} |
||||||
|
|
||||||
|
#[wasm_bindgen(getter)] |
||||||
|
pub fn language(&self) -> String { |
||||||
|
self.inner.language().unwrap_or("").to_owned() |
||||||
|
} |
||||||
|
|
||||||
|
#[wasm_bindgen(getter)] |
||||||
|
pub fn datatype(&self) -> JsNamedNode { |
||||||
|
self.inner.datatype().into_owned().into() |
||||||
|
} |
||||||
|
|
||||||
|
#[wasm_bindgen(js_name = toString)] |
||||||
|
pub fn to_string(&self) -> String { |
||||||
|
self.inner.to_string() |
||||||
|
} |
||||||
|
|
||||||
|
pub fn equals(&self, other: &JsValue) -> bool { |
||||||
|
if let Ok(Some(JsTerm::Literal(other))) = FromJsConverter::default().to_optional_term(other) |
||||||
|
{ |
||||||
|
self == &other |
||||||
|
} else { |
||||||
|
false |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl From<Literal> for JsLiteral { |
||||||
|
fn from(inner: Literal) -> Self { |
||||||
|
Self { inner } |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl From<JsLiteral> for Literal { |
||||||
|
fn from(node: JsLiteral) -> Self { |
||||||
|
node.inner |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl From<JsLiteral> for Term { |
||||||
|
fn from(node: JsLiteral) -> Self { |
||||||
|
node.inner.into() |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#[wasm_bindgen(js_name = DefaultGraph)] |
||||||
|
#[derive(Eq, PartialEq, Debug, Clone, Hash)] |
||||||
|
pub struct JsDefaultGraph; |
||||||
|
|
||||||
|
#[wasm_bindgen(js_class = DefaultGraph)] |
||||||
|
impl JsDefaultGraph { |
||||||
|
#[wasm_bindgen(getter = termType)] |
||||||
|
pub fn term_type(&self) -> String { |
||||||
|
"DefaultGraph".to_owned() |
||||||
|
} |
||||||
|
|
||||||
|
#[wasm_bindgen(getter)] |
||||||
|
pub fn value(&self) -> String { |
||||||
|
String::new() |
||||||
|
} |
||||||
|
|
||||||
|
#[wasm_bindgen(js_name = toString)] |
||||||
|
pub fn to_string(&self) -> String { |
||||||
|
"DEFAULT".to_owned() |
||||||
|
} |
||||||
|
|
||||||
|
pub fn equals(&self, other: &JsValue) -> bool { |
||||||
|
if let Ok(Some(JsTerm::DefaultGraph(other))) = |
||||||
|
FromJsConverter::default().to_optional_term(other) |
||||||
|
{ |
||||||
|
self == &other |
||||||
|
} else { |
||||||
|
false |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#[wasm_bindgen(js_name = Variable)] |
||||||
|
#[derive(Eq, PartialEq, Debug, Clone, Hash)] |
||||||
|
pub struct JsVariable { |
||||||
|
inner: Variable, |
||||||
|
} |
||||||
|
|
||||||
|
#[wasm_bindgen(js_class = Variable)] |
||||||
|
impl JsVariable { |
||||||
|
#[wasm_bindgen(getter = termType)] |
||||||
|
pub fn term_type(&self) -> String { |
||||||
|
"Variable".to_owned() |
||||||
|
} |
||||||
|
|
||||||
|
#[wasm_bindgen(getter)] |
||||||
|
pub fn value(&self) -> String { |
||||||
|
self.inner.as_str().to_owned() |
||||||
|
} |
||||||
|
|
||||||
|
#[wasm_bindgen(js_name = toString)] |
||||||
|
pub fn to_string(&self) -> String { |
||||||
|
self.inner.to_string() |
||||||
|
} |
||||||
|
|
||||||
|
pub fn equals(&self, other: &JsValue) -> bool { |
||||||
|
if let Ok(Some(JsTerm::Variable(other))) = |
||||||
|
FromJsConverter::default().to_optional_term(other) |
||||||
|
{ |
||||||
|
self == &other |
||||||
|
} else { |
||||||
|
false |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl From<Variable> for JsVariable { |
||||||
|
fn from(inner: Variable) -> Self { |
||||||
|
Self { inner } |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl From<JsVariable> for Variable { |
||||||
|
fn from(node: JsVariable) -> Self { |
||||||
|
node.inner |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#[wasm_bindgen(js_name = Quad)] |
||||||
|
#[derive(Eq, PartialEq, Debug, Clone, Hash)] |
||||||
|
pub struct JsQuad { |
||||||
|
inner: Quad, |
||||||
|
} |
||||||
|
|
||||||
|
#[wasm_bindgen(js_class = Quad)] |
||||||
|
impl JsQuad { |
||||||
|
#[wasm_bindgen(getter = termType)] |
||||||
|
pub fn term_type(&self) -> String { |
||||||
|
"Quad".to_owned() |
||||||
|
} |
||||||
|
|
||||||
|
#[wasm_bindgen(getter)] |
||||||
|
pub fn value(&self) -> String { |
||||||
|
String::new() |
||||||
|
} |
||||||
|
|
||||||
|
#[wasm_bindgen(getter = subject)] |
||||||
|
pub fn subject(&self) -> JsValue { |
||||||
|
JsTerm::from(self.inner.subject.clone()).into() |
||||||
|
} |
||||||
|
|
||||||
|
#[wasm_bindgen(getter = predicate)] |
||||||
|
pub fn predicate(&self) -> JsValue { |
||||||
|
JsTerm::from(self.inner.predicate.clone()).into() |
||||||
|
} |
||||||
|
|
||||||
|
#[wasm_bindgen(getter = object)] |
||||||
|
pub fn object(&self) -> JsValue { |
||||||
|
JsTerm::from(self.inner.object.clone()).into() |
||||||
|
} |
||||||
|
|
||||||
|
#[wasm_bindgen(getter = graph)] |
||||||
|
pub fn graph(&self) -> JsValue { |
||||||
|
JsTerm::from(self.inner.graph_name.clone()).into() |
||||||
|
} |
||||||
|
|
||||||
|
#[wasm_bindgen(js_name = toString)] |
||||||
|
pub fn to_string(&self) -> String { |
||||||
|
self.inner.to_string() |
||||||
|
} |
||||||
|
|
||||||
|
pub fn equals(&self, other: &JsValue) -> bool { |
||||||
|
if let Ok(Some(JsTerm::Quad(other))) = FromJsConverter::default().to_optional_term(other) { |
||||||
|
self == &other |
||||||
|
} else { |
||||||
|
false |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl From<Triple> for JsQuad { |
||||||
|
fn from(inner: Triple) -> Self { |
||||||
|
Self { |
||||||
|
inner: inner.in_graph(GraphName::DefaultGraph), |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl From<Quad> for JsQuad { |
||||||
|
fn from(inner: Quad) -> Self { |
||||||
|
Self { inner } |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl From<JsQuad> for Quad { |
||||||
|
fn from(quad: JsQuad) -> Self { |
||||||
|
quad.inner |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl From<JsQuad> for Triple { |
||||||
|
fn from(quad: JsQuad) -> Self { |
||||||
|
quad.inner.into() |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#[derive(Eq, PartialEq, Debug, Clone, Hash)] |
||||||
|
pub enum JsTerm { |
||||||
|
NamedNode(JsNamedNode), |
||||||
|
BlankNode(JsBlankNode), |
||||||
|
Literal(JsLiteral), |
||||||
|
DefaultGraph(JsDefaultGraph), |
||||||
|
Variable(JsVariable), |
||||||
|
Quad(JsQuad), |
||||||
|
} |
||||||
|
|
||||||
|
impl From<JsTerm> for JsValue { |
||||||
|
fn from(value: JsTerm) -> Self { |
||||||
|
match value { |
||||||
|
JsTerm::NamedNode(v) => v.into(), |
||||||
|
JsTerm::BlankNode(v) => v.into(), |
||||||
|
JsTerm::Literal(v) => v.into(), |
||||||
|
JsTerm::DefaultGraph(v) => v.into(), |
||||||
|
JsTerm::Variable(v) => v.into(), |
||||||
|
JsTerm::Quad(v) => v.into(), |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl From<NamedNode> for JsTerm { |
||||||
|
fn from(node: NamedNode) -> Self { |
||||||
|
Self::NamedNode(node.into()) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl From<BlankNode> for JsTerm { |
||||||
|
fn from(node: BlankNode) -> Self { |
||||||
|
Self::BlankNode(node.into()) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl From<Literal> for JsTerm { |
||||||
|
fn from(literal: Literal) -> Self { |
||||||
|
Self::Literal(literal.into()) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl From<NamedOrBlankNode> for JsTerm { |
||||||
|
fn from(node: NamedOrBlankNode) -> Self { |
||||||
|
match node { |
||||||
|
NamedOrBlankNode::NamedNode(node) => node.into(), |
||||||
|
NamedOrBlankNode::BlankNode(node) => node.into(), |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl From<Subject> for JsTerm { |
||||||
|
fn from(node: Subject) -> Self { |
||||||
|
match node { |
||||||
|
Subject::NamedNode(node) => node.into(), |
||||||
|
Subject::BlankNode(node) => node.into(), |
||||||
|
Subject::Triple(node) => node.into(), |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl From<Term> for JsTerm { |
||||||
|
fn from(term: Term) -> Self { |
||||||
|
match term { |
||||||
|
Term::NamedNode(node) => node.into(), |
||||||
|
Term::BlankNode(node) => node.into(), |
||||||
|
Term::Literal(literal) => literal.into(), |
||||||
|
Term::Triple(node) => node.into(), |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl From<GraphName> for JsTerm { |
||||||
|
fn from(name: GraphName) -> Self { |
||||||
|
match name { |
||||||
|
GraphName::NamedNode(node) => node.into(), |
||||||
|
GraphName::BlankNode(node) => node.into(), |
||||||
|
GraphName::DefaultGraph => Self::DefaultGraph(JsDefaultGraph), |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl From<Variable> for JsTerm { |
||||||
|
fn from(variable: Variable) -> Self { |
||||||
|
Self::Variable(variable.into()) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl From<Triple> for JsTerm { |
||||||
|
fn from(triple: Triple) -> Self { |
||||||
|
Self::Quad(triple.into()) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl From<Box<Triple>> for JsTerm { |
||||||
|
fn from(triple: Box<Triple>) -> Self { |
||||||
|
triple.as_ref().clone().into() |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl From<Quad> for JsTerm { |
||||||
|
fn from(quad: Quad) -> Self { |
||||||
|
Self::Quad(quad.into()) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl TryFrom<JsTerm> for NamedNode { |
||||||
|
type Error = JsValue; |
||||||
|
|
||||||
|
fn try_from(value: JsTerm) -> Result<Self, Self::Error> { |
||||||
|
match value { |
||||||
|
JsTerm::NamedNode(node) => Ok(node.into()), |
||||||
|
JsTerm::BlankNode(node) => Err(format_err!( |
||||||
|
"The blank node {} is not a named node", |
||||||
|
node.inner |
||||||
|
)), |
||||||
|
JsTerm::Literal(literal) => Err(format_err!( |
||||||
|
"The literal {} is not a named node", |
||||||
|
literal.inner |
||||||
|
)), |
||||||
|
JsTerm::DefaultGraph(_) => Err(format_err!("The default graph is not a named node")), |
||||||
|
JsTerm::Variable(variable) => Err(format_err!( |
||||||
|
"The variable {} is not a named node", |
||||||
|
variable.inner |
||||||
|
)), |
||||||
|
JsTerm::Quad(quad) => Err(format_err!("The quad {} is not a named node", quad.inner)), |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl TryFrom<JsTerm> for NamedOrBlankNode { |
||||||
|
type Error = JsValue; |
||||||
|
|
||||||
|
fn try_from(value: JsTerm) -> Result<Self, Self::Error> { |
||||||
|
match value { |
||||||
|
JsTerm::NamedNode(node) => Ok(node.into()), |
||||||
|
JsTerm::BlankNode(node) => Ok(node.into()), |
||||||
|
JsTerm::Literal(literal) => Err(format_err!( |
||||||
|
"The literal {} is not a possible named or blank node term", |
||||||
|
literal.inner |
||||||
|
)), |
||||||
|
JsTerm::DefaultGraph(_) => Err(format_err!( |
||||||
|
"The default graph is not a possible named or blank node term" |
||||||
|
)), |
||||||
|
JsTerm::Variable(variable) => Err(format_err!( |
||||||
|
"The variable {} is not a possible named or blank node term", |
||||||
|
variable.inner |
||||||
|
)), |
||||||
|
JsTerm::Quad(quad) => Err(format_err!( |
||||||
|
"The quad {} is not a possible named or blank node term", |
||||||
|
quad.inner |
||||||
|
)), |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl TryFrom<JsTerm> for Subject { |
||||||
|
type Error = JsValue; |
||||||
|
|
||||||
|
fn try_from(value: JsTerm) -> Result<Self, Self::Error> { |
||||||
|
match value { |
||||||
|
JsTerm::NamedNode(node) => Ok(node.into()), |
||||||
|
JsTerm::BlankNode(node) => Ok(node.into()), |
||||||
|
JsTerm::Literal(literal) => Err(format_err!( |
||||||
|
"The literal {} is not a possible RDF subject", |
||||||
|
literal.inner |
||||||
|
)), |
||||||
|
JsTerm::DefaultGraph(_) => Err(format_err!( |
||||||
|
"The default graph is not a possible RDF subject" |
||||||
|
)), |
||||||
|
JsTerm::Variable(variable) => Err(format_err!( |
||||||
|
"The variable {} is not a possible RDF subject", |
||||||
|
variable.inner |
||||||
|
)), |
||||||
|
JsTerm::Quad(quad) => Ok(Triple::from(quad).into()), |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl TryFrom<JsTerm> for Term { |
||||||
|
type Error = JsValue; |
||||||
|
|
||||||
|
fn try_from(value: JsTerm) -> Result<Self, Self::Error> { |
||||||
|
match value { |
||||||
|
JsTerm::NamedNode(node) => Ok(node.into()), |
||||||
|
JsTerm::BlankNode(node) => Ok(node.into()), |
||||||
|
JsTerm::Literal(literal) => Ok(literal.into()), |
||||||
|
JsTerm::DefaultGraph(_) => { |
||||||
|
Err(format_err!("The default graph is not a possible RDF term")) |
||||||
|
} |
||||||
|
JsTerm::Variable(variable) => Err(format_err!( |
||||||
|
"The variable {} is not a possible RDF term", |
||||||
|
variable.inner |
||||||
|
)), |
||||||
|
JsTerm::Quad(quad) => Ok(Triple::from(quad).into()), |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl TryFrom<JsTerm> for GraphName { |
||||||
|
type Error = JsValue; |
||||||
|
|
||||||
|
fn try_from(value: JsTerm) -> Result<Self, Self::Error> { |
||||||
|
match value { |
||||||
|
JsTerm::NamedNode(node) => Ok(node.into()), |
||||||
|
JsTerm::BlankNode(node) => Ok(node.into()), |
||||||
|
JsTerm::Literal(literal) => Err(format_err!( |
||||||
|
"The literal {} is not a possible graph name", |
||||||
|
literal.inner |
||||||
|
)), |
||||||
|
JsTerm::DefaultGraph(_) => Ok(Self::DefaultGraph), |
||||||
|
JsTerm::Variable(variable) => Err(format_err!( |
||||||
|
"The variable {} is not a possible RDF term", |
||||||
|
variable.inner |
||||||
|
)), |
||||||
|
JsTerm::Quad(quad) => Err(format_err!( |
||||||
|
"The quad {} is not a possible RDF term", |
||||||
|
quad.inner |
||||||
|
)), |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
pub struct FromJsConverter { |
||||||
|
term_type: JsValue, |
||||||
|
value: JsValue, |
||||||
|
language: JsValue, |
||||||
|
datatype: JsValue, |
||||||
|
subject: JsValue, |
||||||
|
predicate: JsValue, |
||||||
|
object: JsValue, |
||||||
|
graph: JsValue, |
||||||
|
} |
||||||
|
|
||||||
|
impl Default for FromJsConverter { |
||||||
|
fn default() -> Self { |
||||||
|
Self { |
||||||
|
term_type: JsValue::from_str("termType"), |
||||||
|
value: JsValue::from_str("value"), |
||||||
|
language: JsValue::from_str("language"), |
||||||
|
datatype: JsValue::from_str("datatype"), |
||||||
|
subject: JsValue::from_str("subject"), |
||||||
|
predicate: JsValue::from_str("predicate"), |
||||||
|
object: JsValue::from_str("object"), |
||||||
|
graph: JsValue::from_str("graph"), |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl FromJsConverter { |
||||||
|
pub fn to_term(&self, value: &JsValue) -> Result<JsTerm, JsValue> { |
||||||
|
let term_type = Reflect::get(value, &self.term_type)?; |
||||||
|
if let Some(term_type) = term_type.as_string() { |
||||||
|
match term_type.as_str() { |
||||||
|
"NamedNode" => Ok(NamedNode::new( |
||||||
|
Reflect::get(value, &self.value)? |
||||||
|
.as_string() |
||||||
|
.ok_or_else(|| format_err!("NamedNode should have a string value"))?, |
||||||
|
) |
||||||
|
.map_err(|v| UriError::new(&v.to_string()))? |
||||||
|
.into()), |
||||||
|
"BlankNode" => Ok(BlankNode::new( |
||||||
|
Reflect::get(value, &self.value)? |
||||||
|
.as_string() |
||||||
|
.ok_or_else(|| format_err!("BlankNode should have a string value"))?, |
||||||
|
) |
||||||
|
.map_err(to_err)? |
||||||
|
.into()), |
||||||
|
"Literal" => { |
||||||
|
if let JsTerm::NamedNode(datatype) = |
||||||
|
self.to_term(&Reflect::get(value, &self.datatype)?)? |
||||||
|
{ |
||||||
|
let datatype = NamedNode::from(datatype); |
||||||
|
let literal_value = Reflect::get(value, &self.value)? |
||||||
|
.as_string() |
||||||
|
.ok_or_else(|| format_err!("Literal should have a string value"))?; |
||||||
|
Ok(match datatype.as_str() { |
||||||
|
"http://www.w3.org/2001/XMLSchema#string" => Literal::new_simple_literal(literal_value), |
||||||
|
"http://www.w3.org/1999/02/22-rdf-syntax-ns#langString" => Literal::new_language_tagged_literal(literal_value, Reflect::get(value, &self.language)?.as_string().ok_or_else( |
||||||
|
|| format_err!("Literal with rdf:langString datatype should have a language"), |
||||||
|
)?).map_err(to_err)?, |
||||||
|
_ => Literal::new_typed_literal(literal_value, datatype) |
||||||
|
}.into()) |
||||||
|
} else { |
||||||
|
Err(format_err!( |
||||||
|
"Literal should have a datatype that is a NamedNode" |
||||||
|
)) |
||||||
|
} |
||||||
|
} |
||||||
|
"DefaultGraph" => Ok(JsTerm::DefaultGraph(JsDefaultGraph)), |
||||||
|
"Variable" => Ok(Variable::new( |
||||||
|
Reflect::get(value, &self.value)? |
||||||
|
.as_string() |
||||||
|
.ok_or_else(|| format_err!("Variable should have a string value"))?, |
||||||
|
) |
||||||
|
.map_err(to_err)? |
||||||
|
.into()), |
||||||
|
"Quad" => Ok(self.to_quad(value)?.into()), |
||||||
|
_ => Err(format_err!( |
||||||
|
"The termType {term_type} is not supported by Oxigraph" |
||||||
|
)), |
||||||
|
} |
||||||
|
} else if term_type.is_undefined() { |
||||||
|
// It's a quad without the proper type
|
||||||
|
if Reflect::has(value, &self.subject)? |
||||||
|
&& Reflect::has(value, &self.predicate)? |
||||||
|
&& Reflect::has(value, &self.object)? |
||||||
|
{ |
||||||
|
Ok(self.to_quad(value)?.into()) |
||||||
|
} else { |
||||||
|
Err(format_err!( |
||||||
|
"RDF term objects should have a termType attribute" |
||||||
|
)) |
||||||
|
} |
||||||
|
} else { |
||||||
|
Err(format_err!("The object termType field should be a string")) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
pub fn to_optional_term(&self, value: &JsValue) -> Result<Option<JsTerm>, JsValue> { |
||||||
|
if value.is_null() || value.is_undefined() { |
||||||
|
Ok(None) |
||||||
|
} else { |
||||||
|
self.to_term(value).map(Some) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
pub fn to_quad(&self, value: &JsValue) -> Result<Quad, JsValue> { |
||||||
|
self.to_quad_from_parts( |
||||||
|
&Reflect::get(value, &self.subject)?, |
||||||
|
&Reflect::get(value, &self.predicate)?, |
||||||
|
&Reflect::get(value, &self.object)?, |
||||||
|
&Reflect::get(value, &self.graph)?, |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
pub fn to_quad_from_parts( |
||||||
|
&self, |
||||||
|
subject: &JsValue, |
||||||
|
predicate: &JsValue, |
||||||
|
object: &JsValue, |
||||||
|
graph_name: &JsValue, |
||||||
|
) -> Result<Quad, JsValue> { |
||||||
|
Ok(Quad { |
||||||
|
subject: Subject::try_from(self.to_term(subject)?)?, |
||||||
|
predicate: NamedNode::try_from(self.to_term(predicate)?)?, |
||||||
|
object: Term::try_from(self.to_term(object)?)?, |
||||||
|
graph_name: if graph_name.is_undefined() { |
||||||
|
GraphName::DefaultGraph |
||||||
|
} else { |
||||||
|
GraphName::try_from(self.to_term(graph_name)?)? |
||||||
|
}, |
||||||
|
}) |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue