sophia_api/term/
_native_literal.rs1use super::*;
2use crate::ns::xsd;
3
4lazy_static::lazy_static! {
5 static ref XSD_DOUBLE: Box<str> = xsd::double.iri().unwrap().unwrap().into();
6 static ref XSD_INTEGER: Box<str> = xsd::integer.iri().unwrap().unwrap().into();
7 static ref XSD_STRING: Box<str> = xsd::string.iri().unwrap().unwrap().into();
8 static ref XSD_BOOLEAN: Box<str> = xsd::boolean.iri().unwrap().unwrap().into();
9}
10
11impl Term for f64 {
28 type BorrowTerm<'x> = Self;
29
30 fn kind(&self) -> TermKind {
31 TermKind::Literal
32 }
33 fn lexical_form(&self) -> Option<MownStr> {
34 Some(MownStr::from(format!("{}", self)))
35 }
36 fn datatype(&self) -> Option<IriRef<MownStr>> {
37 Some(IriRef::new_unchecked(MownStr::from_ref(&XSD_DOUBLE)))
38 }
39 fn language_tag(&self) -> Option<LanguageTag<MownStr>> {
40 None
41 }
42 fn borrow_term(&self) -> Self::BorrowTerm<'_> {
43 *self
44 }
45}
46
47impl Term for i32 {
64 type BorrowTerm<'x> = Self;
65
66 fn kind(&self) -> TermKind {
67 TermKind::Literal
68 }
69 fn lexical_form(&self) -> Option<MownStr> {
70 Some(MownStr::from(format!("{}", self)))
71 }
72 fn datatype(&self) -> Option<IriRef<MownStr>> {
73 Some(IriRef::new_unchecked(MownStr::from_ref(&XSD_INTEGER)))
74 }
75 fn language_tag(&self) -> Option<LanguageTag<MownStr>> {
76 None
77 }
78 fn borrow_term(&self) -> Self::BorrowTerm<'_> {
79 *self
80 }
81}
82
83impl Term for isize {
101 type BorrowTerm<'x> = Self;
102
103 fn kind(&self) -> TermKind {
104 TermKind::Literal
105 }
106 fn lexical_form(&self) -> Option<MownStr> {
107 Some(MownStr::from(format!("{}", self)))
108 }
109 fn datatype(&self) -> Option<IriRef<MownStr>> {
110 Some(IriRef::new_unchecked(MownStr::from_ref(&XSD_INTEGER)))
111 }
112 fn language_tag(&self) -> Option<LanguageTag<MownStr>> {
113 None
114 }
115 fn borrow_term(&self) -> Self::BorrowTerm<'_> {
116 *self
117 }
118}
119
120impl Term for usize {
138 type BorrowTerm<'x> = Self;
139
140 fn kind(&self) -> TermKind {
141 TermKind::Literal
142 }
143 fn lexical_form(&self) -> Option<MownStr> {
144 Some(MownStr::from(format!("{}", self)))
145 }
146 fn datatype(&self) -> Option<IriRef<MownStr>> {
147 Some(IriRef::new_unchecked(MownStr::from_ref(&XSD_INTEGER)))
148 }
149 fn language_tag(&self) -> Option<LanguageTag<MownStr>> {
150 None
151 }
152 fn borrow_term(&self) -> Self::BorrowTerm<'_> {
153 *self
154 }
155}
156
157impl Term for str {
174 type BorrowTerm<'x> = &'x Self where Self: 'x;
175
176 fn kind(&self) -> TermKind {
177 TermKind::Literal
178 }
179 fn lexical_form(&self) -> Option<MownStr> {
180 Some(MownStr::from(self))
181 }
182 fn datatype(&self) -> Option<IriRef<MownStr>> {
183 Some(IriRef::new_unchecked(MownStr::from_ref(&XSD_STRING)))
184 }
185 fn language_tag(&self) -> Option<LanguageTag<MownStr>> {
186 None
187 }
188 fn borrow_term(&self) -> Self::BorrowTerm<'_> {
189 self
190 }
191}
192
193impl Term for bool {
210 type BorrowTerm<'x> = Self;
211
212 fn kind(&self) -> TermKind {
213 TermKind::Literal
214 }
215 fn lexical_form(&self) -> Option<MownStr> {
216 Some(MownStr::from(if *self { "true" } else { "false" }))
217 }
218 fn datatype(&self) -> Option<IriRef<MownStr>> {
219 Some(IriRef::new_unchecked(MownStr::from_ref(&XSD_BOOLEAN)))
220 }
221 fn language_tag(&self) -> Option<LanguageTag<MownStr>> {
222 None
223 }
224 fn borrow_term(&self) -> Self::BorrowTerm<'_> {
225 *self
226 }
227}
228
229impl TryFromTerm for f64 {
232 type Error = std::num::ParseFloatError;
233
234 fn try_from_term<T: Term>(term: T) -> Result<Self, Self::Error> {
235 if let Some(lex) = term.lexical_form() {
236 if Term::eq(&term.datatype().unwrap(), xsd::double)
237 || Term::eq(&term.datatype().unwrap(), xsd::float)
238 || Term::eq(&term.datatype().unwrap(), xsd::decimal)
239 {
240 lex.parse()
241 } else {
242 "wrong datatype".parse()
243 }
244 } else {
245 "not a literal".parse()
246 }
247 }
248}
249
250impl TryFromTerm for i32 {
253 type Error = std::num::ParseIntError;
254
255 fn try_from_term<T: Term>(term: T) -> Result<Self, Self::Error> {
256 if let Some(lex) = term.lexical_form() {
257 if Term::eq(&term.datatype().unwrap(), xsd::integer)
258 || Term::eq(&term.datatype().unwrap(), xsd::long)
259 || Term::eq(&term.datatype().unwrap(), xsd::int)
260 || Term::eq(&term.datatype().unwrap(), xsd::short)
261 || Term::eq(&term.datatype().unwrap(), xsd::unsignedLong)
262 || Term::eq(&term.datatype().unwrap(), xsd::unsignedInt)
263 || Term::eq(&term.datatype().unwrap(), xsd::unsignedShort)
264 || Term::eq(&term.datatype().unwrap(), xsd::unsignedByte)
265 || Term::eq(&term.datatype().unwrap(), xsd::nonNegativeInteger)
266 || Term::eq(&term.datatype().unwrap(), xsd::nonPositiveInteger)
267 || Term::eq(&term.datatype().unwrap(), xsd::negativeInteger)
268 || Term::eq(&term.datatype().unwrap(), xsd::positiveInteger)
269 {
270 lex.parse()
271 } else {
272 "wrong datatype".parse()
273 }
274 } else {
275 "not a literal".parse()
276 }
277 }
278}
279
280impl TryFromTerm for isize {
283 type Error = std::num::ParseIntError;
284
285 fn try_from_term<T: Term>(term: T) -> Result<Self, Self::Error> {
286 if let Some(lex) = term.lexical_form() {
287 if Term::eq(&term.datatype().unwrap(), xsd::integer)
288 || Term::eq(&term.datatype().unwrap(), xsd::long)
289 || Term::eq(&term.datatype().unwrap(), xsd::int)
290 || Term::eq(&term.datatype().unwrap(), xsd::short)
291 || Term::eq(&term.datatype().unwrap(), xsd::unsignedLong)
292 || Term::eq(&term.datatype().unwrap(), xsd::unsignedInt)
293 || Term::eq(&term.datatype().unwrap(), xsd::unsignedShort)
294 || Term::eq(&term.datatype().unwrap(), xsd::unsignedByte)
295 || Term::eq(&term.datatype().unwrap(), xsd::nonNegativeInteger)
296 || Term::eq(&term.datatype().unwrap(), xsd::nonPositiveInteger)
297 || Term::eq(&term.datatype().unwrap(), xsd::negativeInteger)
298 || Term::eq(&term.datatype().unwrap(), xsd::positiveInteger)
299 {
300 lex.parse()
301 } else {
302 "wrong datatype".parse()
303 }
304 } else {
305 "not a literal".parse()
306 }
307 }
308}
309
310impl TryFromTerm for usize {
313 type Error = std::num::ParseIntError;
314
315 fn try_from_term<T: Term>(term: T) -> Result<Self, Self::Error> {
316 if let Some(lex) = term.lexical_form() {
317 if Term::eq(&term.datatype().unwrap(), xsd::integer)
318 || Term::eq(&term.datatype().unwrap(), xsd::long)
319 || Term::eq(&term.datatype().unwrap(), xsd::int)
320 || Term::eq(&term.datatype().unwrap(), xsd::short)
321 || Term::eq(&term.datatype().unwrap(), xsd::unsignedLong)
322 || Term::eq(&term.datatype().unwrap(), xsd::unsignedInt)
323 || Term::eq(&term.datatype().unwrap(), xsd::unsignedShort)
324 || Term::eq(&term.datatype().unwrap(), xsd::unsignedByte)
325 || Term::eq(&term.datatype().unwrap(), xsd::nonNegativeInteger)
326 || Term::eq(&term.datatype().unwrap(), xsd::positiveInteger)
327 {
328 lex.parse()
329 } else {
330 "wrong datatype".parse()
331 }
332 } else {
333 "not a literal".parse()
334 }
335 }
336}
337
338impl TryFromTerm for bool {
341 type Error = std::str::ParseBoolError;
342
343 fn try_from_term<T: Term>(term: T) -> Result<Self, Self::Error> {
344 if let Some(lex) = term.lexical_form() {
345 if Term::eq(&term.datatype().unwrap(), xsd::boolean) {
346 lex.parse()
347 } else {
348 "wrong datatype".parse()
349 }
350 } else {
351 "not a literal".parse()
352 }
353 }
354}
355
356#[cfg(test)]
357mod test {
358 use super::*;
359
360 #[test]
361 fn i32_as_literal() {
362 let lit = 42;
363 assert_consistent_term_impl::<i32>(&lit);
364 assert_eq!(lit.kind(), TermKind::Literal);
365 assert_eq!(lit.lexical_form().unwrap(), "42");
366 assert_eq!(lit.datatype(), xsd::integer.iri());
367 assert_eq!(lit.borrow_term(), lit);
368 }
369
370 #[test]
371 fn isize_as_literal() {
372 let lit = 42;
373 assert_consistent_term_impl::<isize>(&lit);
374 assert_eq!(lit.kind(), TermKind::Literal);
375 assert_eq!(lit.lexical_form().unwrap(), "42");
376 assert_eq!(lit.datatype(), xsd::integer.iri());
377 assert_eq!(lit.borrow_term(), lit);
378 }
379
380 #[test]
381 fn usize_as_literal() {
382 let lit = 42;
383 assert_consistent_term_impl::<usize>(&lit);
384 assert_eq!(lit.kind(), TermKind::Literal);
385 assert_eq!(lit.lexical_form().unwrap(), "42");
386 assert_eq!(lit.datatype(), xsd::integer.iri());
387 assert_eq!(lit.borrow_term(), lit);
388 }
389
390 #[test]
391 fn f64_as_literal() {
392 #[allow(clippy::approx_constant)]
393 let lit = 3.14;
394 assert_consistent_term_impl::<f64>(&lit);
395 assert_eq!(lit.kind(), TermKind::Literal);
396 assert_eq!(lit.lexical_form().unwrap(), "3.14");
397 assert_eq!(lit.datatype(), xsd::double.iri());
398 assert_eq!(lit.borrow_term(), lit);
399 }
400
401 #[test]
402 fn str_as_literal() {
403 let lit = "hello world";
404 assert_consistent_term_impl::<&str>(&lit);
405 assert_eq!(lit.kind(), TermKind::Literal);
406 assert_eq!(lit.lexical_form().unwrap(), lit);
407 assert_eq!(lit.datatype(), xsd::string.iri());
408 assert_eq!(lit.borrow_term(), lit);
409 }
410
411 #[test]
412 fn bool_as_literal() {
413 let lit = false;
414 assert_consistent_term_impl::<bool>(&lit);
415 assert_eq!(lit.kind(), TermKind::Literal);
416 assert_eq!(lit.lexical_form().unwrap(), "false");
417 assert_eq!(lit.datatype(), xsd::boolean.iri());
418 assert_eq!(lit.borrow_term(), lit);
419 }
420
421 #[test]
422 fn iri_to_native() {
423 assert!(f64::try_from_term(xsd::ID).is_err());
424 assert!(i32::try_from_term(xsd::ID).is_err());
425 assert!(isize::try_from_term(xsd::ID).is_err());
426 assert!(usize::try_from_term(xsd::ID).is_err());
427 }
428
429 #[test]
430 fn wrong_datatype_to_native() {
431 assert!(f64::try_from_term("foo").is_err());
432 assert!(i32::try_from_term("foo").is_err());
433 assert!(isize::try_from_term("foo").is_err());
434 assert!(usize::try_from_term("foo").is_err());
435 }
436
437 #[test]
438 fn correct_datatype_to_native() {
439 assert_eq!(f64::try_from_term(3.15).unwrap(), 3.15);
440 assert_eq!(i32::try_from_term(42).unwrap(), 42);
441 assert_eq!(isize::try_from_term(42).unwrap(), 42);
442 assert_eq!(usize::try_from_term(42).unwrap(), 42);
443 }
444}