1use core::fmt;
2use std::borrow::Borrow;
3
4use iri_rs::{Iri, IriBuf, iri};
5use rdfx::{
6 BlankId, BlankIdBuf, Datatype, DatatypeRef, Id, Interpretation, InterpretationMut, Literal,
7 LiteralType, LiteralTypeRef, LocalTerm, LocalTermRef, Quad,
8};
9
10pub type RdfId = Id;
12pub type RdfTerm = LocalTerm;
14pub type RdfTermRef<'a> = LocalTermRef<'a>;
16
17pub type RdfQuad = Quad<Id, IriBuf, LocalTerm, Id>;
19
20pub type InterpretedQuad<I> = Quad<
22 <I as Interpretation>::Resource,
23 <I as Interpretation>::Resource,
24 <I as Interpretation>::Resource,
25 <I as Interpretation>::Resource,
26>;
27
28#[derive(Debug, Clone)]
29pub enum CowRdfTerm<'a> {
31 Borrowed(BorrowedRdfTerm<'a>),
33 Owned(OwnedRdfTerm),
35}
36
37#[derive(Debug, Clone, Copy)]
38pub enum BorrowedRdfTerm<'a> {
40 Iri(Iri<&'a str>),
42 BlankId(&'a BlankId),
44 Literal(RdfLiteralRef<'a>),
46}
47
48#[derive(Debug, Clone)]
49pub enum OwnedRdfTerm {
51 Iri(IriBuf),
53 BlankId(BlankIdBuf),
55 Literal(RdfLiteral),
57}
58
59impl OwnedRdfTerm {
60 pub fn into_id(self) -> Option<Id> {
62 match self {
63 Self::Iri(iri) => Some(Id::Iri(iri)),
64 Self::BlankId(b) => Some(Id::BlankId(b)),
65 Self::Literal(_) => None,
66 }
67 }
68}
69
70fn datatype_ref_or_unchecked(ty: Iri<&str>) -> DatatypeRef<'_> {
71 DatatypeRef::new(ty).unwrap_or_else(|_| unsafe { DatatypeRef::new_unchecked(ty) })
72}
73
74fn datatype_or_unchecked(ty: IriBuf) -> Datatype {
75 Datatype::new(ty.clone()).unwrap_or_else(|_| unsafe { Datatype::new_unchecked(ty) })
76}
77
78impl<'a> CowRdfTerm<'a> {
79 pub fn from_str(value: &'a str, ty: Iri<&'a str>) -> Self {
81 use xsd_rs::ValueRef;
82
83 if ty.as_str() == RDF_JSON.as_str() {
84 use jstrict::Parse;
85 match jstrict::Value::parse_str(value) {
86 Ok((json, _)) => CowRdfTerm::Owned(OwnedRdfTerm::Literal(RdfLiteral::Json(json))),
87 Err(_) => CowRdfTerm::Borrowed(BorrowedRdfTerm::Literal(RdfLiteralRef::Any(
88 value,
89 LiteralTypeRef::Any(datatype_ref_or_unchecked(ty)),
90 ))),
91 }
92 } else {
93 match xsd_rs::Datatype::from_iri(&ty) {
94 Some(xsd_rs::Datatype::String(xsd_rs::StringDatatype::String)) => {
95 CowRdfTerm::Borrowed(BorrowedRdfTerm::Literal(RdfLiteralRef::Xsd(
96 ValueRef::String(value),
97 )))
98 }
99 Some(xsd_ty) => match xsd_ty.parse(value) {
100 Ok(xsd_value) => {
101 CowRdfTerm::Owned(OwnedRdfTerm::Literal(RdfLiteral::Xsd(xsd_value)))
102 }
103 Err(_) => CowRdfTerm::Borrowed(BorrowedRdfTerm::Literal(RdfLiteralRef::Any(
104 value,
105 LiteralTypeRef::Any(datatype_ref_or_unchecked(ty)),
106 ))),
107 },
108 None => CowRdfTerm::Borrowed(BorrowedRdfTerm::Literal(RdfLiteralRef::Any(
109 value,
110 LiteralTypeRef::Any(datatype_ref_or_unchecked(ty)),
111 ))),
112 }
113 }
114 }
115
116 pub fn into_owned(self) -> OwnedRdfTerm {
118 match self {
119 Self::Borrowed(b) => match b {
120 BorrowedRdfTerm::Iri(i) => OwnedRdfTerm::Iri(i.into()),
121 BorrowedRdfTerm::BlankId(b) => OwnedRdfTerm::BlankId(b.to_owned()),
122 BorrowedRdfTerm::Literal(l) => OwnedRdfTerm::Literal(l.into_owned()),
123 },
124 Self::Owned(o) => o,
125 }
126 }
127}
128
129pub enum CowRef<'a, T> {
131 Borrowed(&'a T),
133 Owned(T),
135}
136
137impl<'a, T> AsRef<T> for CowRef<'a, T> {
138 fn as_ref(&self) -> &T {
139 match self {
140 Self::Borrowed(t) => t,
141 Self::Owned(t) => t,
142 }
143 }
144}
145
146impl<'a, T> Borrow<T> for CowRef<'a, T> {
147 fn borrow(&self) -> &T {
148 match self {
149 Self::Borrowed(t) => t,
150 Self::Owned(t) => t,
151 }
152 }
153}
154
155pub trait RdfLiteralValue: From<String> + From<xsd_rs::Value> + From<jstrict::Value> {}
157
158impl<T: From<String> + From<xsd_rs::Value> + From<jstrict::Value>> RdfLiteralValue for T {}
159
160pub trait AsRdfLiteral {
162 fn as_rdf_literal<'a>(&'a self, ty: LiteralTypeRef<'a>) -> CowRdfLiteral<'a>;
164}
165
166impl AsRdfLiteral for str {
167 fn as_rdf_literal<'a>(&'a self, ty: LiteralTypeRef<'a>) -> CowRdfLiteral<'a> {
168 CowRdfLiteral::Borrowed(RdfLiteralRef::Any(self, ty))
169 }
170}
171
172impl AsRdfLiteral for String {
173 fn as_rdf_literal<'a>(&'a self, ty: LiteralTypeRef<'a>) -> CowRdfLiteral<'a> {
174 self.as_str().as_rdf_literal(ty)
175 }
176}
177
178#[derive(Debug, Clone)]
179pub enum RdfLiteral {
181 Any(String, LiteralType),
183 Xsd(xsd_rs::Value),
185 Json(jstrict::Value),
187}
188
189impl RdfLiteral {
190 pub fn into_lexical(self) -> Literal {
192 match self {
193 Self::Any(s, ty) => Literal::new(s, ty),
194 Self::Xsd(value) => {
195 let ty = value.datatype().iri().to_owned();
196 Literal::new(value.to_string(), datatype_or_unchecked(ty.into()))
197 }
198 Self::Json(mut value) => {
199 value.canonicalize();
200 Literal::new(value.to_string(), datatype_or_unchecked(RDF_JSON.into()))
201 }
202 }
203 }
204
205 pub fn as_literal_ref(&self) -> RdfLiteralRef<'_> {
207 match self {
208 Self::Any(value, ty) => RdfLiteralRef::Any(value, ty.as_ref()),
209 Self::Xsd(value) => RdfLiteralRef::Xsd(value.as_ref()),
210 Self::Json(value) => RdfLiteralRef::Json(value),
211 }
212 }
213
214 pub fn embed_into<I: InterpretationMut>(self, interpretation: &mut I) -> I::Resource {
216 interpretation.insert_literal(self.into_lexical().into_cow())
217 }
218}
219
220impl fmt::Display for RdfLiteral {
221 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
222 match self {
223 Self::Any(v, _) => v.fmt(f),
224 Self::Xsd(v) => v.fmt(f),
225 Self::Json(v) => v.fmt(f),
226 }
227 }
228}
229
230pub const RDF_JSON: Iri<&'static str> = iri!("http://www.w3.org/1999/02/22-rdf-syntax-ns#JSON");
233
234#[derive(Debug, Clone, Copy)]
235pub enum RdfLiteralRef<'a> {
237 Any(&'a str, LiteralTypeRef<'a>),
239 Xsd(xsd_rs::ValueRef<'a>),
241 Json(&'a jstrict::Value),
243}
244
245impl<'a> RdfLiteralRef<'a> {
246 pub fn into_lexical(self) -> Literal {
248 match self {
249 Self::Any(s, ty) => Literal::new(s.to_owned(), ty.into_owned()),
250 Self::Xsd(value) => {
251 let ty = value.datatype().iri().to_owned();
252 Literal::new(value.to_string(), datatype_or_unchecked(ty.into()))
253 }
254 Self::Json(value) => {
255 let mut value = value.clone();
256 value.canonicalize();
257 Literal::new(value.to_string(), datatype_or_unchecked(RDF_JSON.into()))
258 }
259 }
260 }
261
262 pub fn into_owned(self) -> RdfLiteral {
264 match self {
265 Self::Any(value, ty) => RdfLiteral::Any(value.to_owned(), ty.into_owned()),
266 Self::Xsd(value) => RdfLiteral::Xsd(value.into_owned()),
267 Self::Json(value) => RdfLiteral::Json(value.clone()),
268 }
269 }
270}
271
272pub enum CowRdfLiteral<'a> {
274 Borrowed(RdfLiteralRef<'a>),
276 Owned(RdfLiteral),
278}
279
280impl<'a> CowRdfLiteral<'a> {
281 pub fn into_owned(self) -> RdfLiteral {
283 match self {
284 Self::Borrowed(l) => l.into_owned(),
285 Self::Owned(l) => l,
286 }
287 }
288
289 pub fn as_literal_ref(&self) -> RdfLiteralRef<'_> {
291 match self {
292 Self::Borrowed(l) => *l,
293 Self::Owned(l) => l.as_literal_ref(),
294 }
295 }
296}