1use {
2 crate::{DataType, LiteralIdUrlDisplay, LiteralUrlDisplay, LiteralValue, Term},
3 std::{
4 fmt::{Debug, Display, Formatter},
5 mem::ManuallyDrop,
6 ops::Deref,
7 str::FromStr,
8 },
9};
10
11#[derive(Default)]
27pub struct Literal {
28 pub data_type: DataType,
29 literal_value: LiteralValue,
30}
31
32impl PartialEq for Literal {
33 fn eq(&self, other: &Self) -> bool {
34 let data_type = self.data_type;
35 if data_type != other.data_type {
36 return false;
37 }
38 unsafe {
39 if data_type.is_iri() {
40 self.literal_value.iri.as_str() == other.literal_value.iri.as_str()
41 } else if data_type.is_string() {
42 self.literal_value.string == other.literal_value.string
43 } else if data_type.is_boolean() {
44 self.literal_value.boolean == other.literal_value.boolean
45 } else if data_type.is_signed_integer() {
46 self.literal_value.signed_integer == other.literal_value.signed_integer
47 } else if data_type.is_unsigned_integer() {
48 self.literal_value.unsigned_integer == other.literal_value.unsigned_integer
49 } else if data_type.is_blank_node() {
50 self.literal_value.blank_node == other.literal_value.blank_node
51 } else if data_type.is_decimal() {
52 self.literal_value.string == other.literal_value.string
53 } else if data_type.is_date() {
54 self.literal_value.date == other.literal_value.date
55 } else if data_type.is_date_time() {
56 self.literal_value.date_time == other.literal_value.date_time
57 } else {
58 panic!("Cannot compare, unimplemented datatype {data_type:?}")
59 }
60 }
61 }
62}
63
64impl Eq for Literal {}
65
66impl std::hash::Hash for Literal {
67 fn hash<H>(&self, state: &mut H)
68 where H: std::hash::Hasher {
69 let data_type = self.data_type;
70 data_type.hash(state);
71 unsafe {
72 #[allow(clippy::if_same_then_else)]
73 if data_type.is_iri() {
74 self.literal_value.iri.as_str().hash(state)
75 } else if data_type.is_string() {
76 self.literal_value.string.hash(state)
77 } else if data_type.is_blank_node() {
78 self.literal_value.blank_node.hash(state)
79 } else if data_type.is_boolean() {
80 self.literal_value.boolean.hash(state)
81 } else if data_type.is_signed_integer() {
82 self.literal_value.signed_integer.hash(state)
83 } else if data_type.is_unsigned_integer() {
84 self.literal_value.unsigned_integer.hash(state)
85 } else if data_type.is_decimal() {
86 self.literal_value.string.hash(state)
87 } else if data_type.is_duration() {
88 self.literal_value.string.hash(state)
89 } else if data_type.is_date() {
90 self.literal_value.date.hash(state)
91 } else if data_type.is_date_time() {
92 self.literal_value.date_time.hash(state)
93 } else {
94 panic!("Cannot hash, unimplemented datatype {data_type:?}")
95 }
96 }
97 }
98}
99
100impl Debug for Literal {
101 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
102 let data_type = self.data_type;
103 write!(f, "Literal({:?},", data_type)?;
104 unsafe {
105 #[allow(clippy::if_same_then_else)]
106 if data_type.is_iri() {
107 write!(f, "{}", self)?
108 } else if data_type.is_string() {
109 write!(f, "\"{}\"", self.literal_value.string.as_str())?
110 } else if data_type.is_blank_node() {
111 write!(f, "_:{}", self.literal_value.blank_node.as_str())?
112 } else if data_type.is_boolean() {
113 write!(f, "{}", self.literal_value.boolean)?
114 } else if data_type.is_signed_integer() {
115 write!(f, "{}", self.literal_value.signed_integer)?
116 } else if data_type.is_unsigned_integer() {
117 write!(f, "{}", self.literal_value.unsigned_integer)?
118 } else if data_type.is_decimal() {
119 write!(f, "{}", self.literal_value.string.as_str())?
120 } else if data_type.is_duration() || data_type.is_date_time_stamp() {
121 write!(f, "{}", self.literal_value.string.as_str())?
122 } else if data_type.is_date() {
123 write!(
124 f,
125 "{}",
126 self.literal_value.date.format("%Y-%m-%d")
127 )?
128 } else if data_type.is_date_time() {
129 write!(f, "{:}", self.literal_value.date_time)?
130 } else {
131 panic!("Cannot format, unimplemented datatype {data_type:?}")
132 }
133 }
134 write!(f, ")")
135 }
136}
137
138impl Display for Literal {
139 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
140 if self.data_type.is_iri() {
141 write!(f, "<{}>", self.as_iri().unwrap())
142 } else if self.data_type.is_blank_node() {
143 write!(f, "_:{}", self.as_string().unwrap().as_str())
144 } else if self.data_type.is_string() {
145 if let Some(str) = self.as_string() {
146 write!(f, "\"{}\"", str.as_str())
147 } else {
148 write!(f, "ERROR, could not convert to String")
149 }
150 } else if self.data_type.is_boolean() {
151 write!(f, "{}", self.as_boolean().unwrap())
152 } else if self.data_type.is_date() {
153 write!(f, "{}", self.as_date().unwrap())
154 } else if self.data_type.is_date_time() {
155 write!(f, "{}", self.as_date_time().unwrap())
156 } else if let Some(str) = self.as_string() {
157 write!(f, "{} ({:?})", str.as_str(), self.data_type)
158 } else {
159 write!(
160 f,
161 "ERROR, could not convert to String ({:?})",
162 self.data_type
163 )
164 }
165 }
166}
167
168impl Clone for Literal {
169 fn clone(&self) -> Self {
171 if self.data_type.is_iri() {
172 if let Some(ref iri) = self.as_iri() {
173 Literal {
174 data_type: self.data_type,
175 literal_value: LiteralValue::new_iri(iri.borrow()),
176 }
177 } else {
178 todo!("the situation where the iri in a lexical value is empty")
179 }
180 } else if self.data_type.is_blank_node() {
181 if let Some(blank_node) = self.as_str() {
182 Literal::new_blank_node_with_datatype(blank_node, self.data_type).unwrap()
183 } else {
184 todo!("the situation where the blank_node in a lexical value is empty")
185 }
186 } else if self.data_type.is_string() {
187 if let Some(str) = self.as_str() {
188 Literal::new_string_with_datatype(str, self.data_type).unwrap()
189 } else {
190 todo!("the situation where the string in a lexical value is empty")
191 }
192 } else if self.data_type.is_boolean() {
193 if let Some(boolean) = self.as_boolean() {
194 Literal::new_boolean_with_datatype(boolean, self.data_type).unwrap()
195 } else {
196 todo!("the situation where the boolean in a lexical value is not a boolean")
197 }
198 } else if self.data_type.is_date() {
199 if let Some(date) = self.as_date() {
200 Literal::new_date_with_datatype(date, self.data_type).unwrap()
201 } else {
202 todo!("the situation where the naive date in a lexical value is not a naive date")
203 }
204 } else if self.data_type.is_date_time() {
205 if let Some(date_time) = self.as_date_time() {
206 Literal::new_date_time_with_datatype(*date_time, self.data_type).unwrap()
207 } else {
208 todo!("the situation where the boolean in a lexical value is not a boolean")
209 }
210 } else if self.data_type.is_signed_integer() {
211 if let Some(long) = self.as_signed_long() {
212 Literal::new_signed_integer_with_datatype(long, self.data_type).unwrap()
213 } else {
214 todo!("the situation where the signed integer value is not a long")
215 }
216 } else if self.data_type.is_unsigned_integer() {
217 if let Some(long) = self.as_unsigned_long() {
218 Literal::new_unsigned_integer_with_datatype(long, self.data_type).unwrap()
219 } else {
220 todo!("the situation where the unsigned integer value is not a long")
221 }
222 } else if self.data_type.is_decimal() {
223 if let Some(decimal) = self.as_decimal() {
224 Literal::new_decimal_with_datatype(decimal, self.data_type).unwrap()
225 } else {
226 todo!("the situation where the decimal value is not a decimal")
227 }
228 } else if self.data_type.is_duration() {
229 if let Some(duration) = self.as_duration() {
230 Literal::new_duration_with_datatype(duration, self.data_type).unwrap()
231 } else {
232 todo!("the situation where the duration value is not a duration")
233 }
234 } else {
235 todo!(
236 "dealing with other datatypes: {:?}",
237 self.data_type
238 )
239 }
240 }
241}
242
243#[cfg(feature = "serde")]
244impl serde::Serialize for Literal {
245 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
246 where S: serde::Serializer {
247 let data_type = self.data_type;
248 unsafe {
249 if data_type.is_iri() {
250 serializer.serialize_str(self.literal_value.iri.as_str())
251 } else if data_type.is_string() {
252 serializer.serialize_str(self.literal_value.string.as_str())
253 } else if data_type.is_blank_node() {
254 serializer.serialize_str(self.literal_value.blank_node.as_str())
255 } else if data_type.is_boolean() {
256 serializer.serialize_bool(self.literal_value.boolean)
257 } else if data_type.is_signed_integer() {
258 serializer.serialize_i64(self.literal_value.signed_integer)
259 } else if data_type.is_unsigned_integer() {
260 serializer.serialize_u64(self.literal_value.unsigned_integer)
261 } else if data_type.is_decimal() {
262 serializer.serialize_str(self.literal_value.string.as_str())
263 } else if data_type.is_duration() || data_type.is_date_time_stamp() {
264 serializer.serialize_str(self.literal_value.string.as_str())
265 } else if data_type.is_date() {
266 serializer.serialize_str(self.literal_value.date.to_string().as_str())
267 } else if data_type.is_date_time() {
268 serializer.serialize_str(self.literal_value.date_time.to_string().as_str())
269 } else {
270 panic!("Cannot serialize, unimplemented datatype {data_type:?}")
271 }
272 }
273 }
274}
275
276#[cfg(feature = "serde")]
277impl<'a> serde::Deserialize<'a> for Literal {
278 fn deserialize<D: serde::Deserializer<'a>>(deserializer: D) -> Result<Self, D::Error> {
279 deserializer.deserialize_str(LiteralDeserializeVisitor)
280 }
281}
282
283impl FromStr for Literal {
284 type Err = ekg_error::Error;
285
286 fn from_str(str: &str) -> Result<Self, Self::Err> { Self::new_plain_literal_string(str) }
287}
288
289#[cfg(feature = "oxigraph")]
290impl From<oxrdf::Literal> for Literal {
291 fn from(value: oxrdf::Literal) -> Self {
292 Self::from_str(value.value()).unwrap()
294 }
295}
296
297impl From<&str> for Literal {
298 fn from(value: &str) -> Self { Literal::from_str(value).unwrap() }
299}
300
301impl Literal {
302 pub fn as_term(&self) -> Term {
303 match self.data_type {
304 DataType::IriReference | DataType::AnyUri => Term::Iri(self.clone()),
305 DataType::BlankNode => Term::BlankNode(self.clone()),
306 _ => Term::Literal(self.clone()),
307 }
308 }
309
310 pub fn as_iri(&self) -> Option<fluent_uri::Uri<String>> {
311 if self.data_type.is_iri() {
312 Some(unsafe { self.literal_value.iri.deref().clone() })
313 } else {
314 None
315 }
316 }
317
318 pub fn as_iri_ref(&self) -> Option<&fluent_uri::Uri<&str>> {
319 if self.data_type.is_iri() {
320 Some(unsafe { self.literal_value.iri.borrow() })
321 } else {
322 None
323 }
324 }
325
326 pub fn as_iref_iri_ref(&self) -> Option<&iref::Iri> {
327 if self.data_type.is_iri() {
328 Some(unsafe { iref::Iri::new(self.literal_value.iri.as_str()).unwrap() })
329 } else {
330 None
331 }
332 }
333
334 pub fn as_local_name(&self) -> Option<String> {
335 self.as_iri_ref()
336 .map(|iri| iri.to_string())
337 .and_then(|ref iri| {
338 match fancy_regex::Regex::new(r#"(?:.*)[#/](.*)"#) {
339 Ok(re) => {
340 if let Ok(Some(captures)) = re.captures(iri.as_str()) {
341 captures.get(1).map(|mat| String::from(mat.as_str()))
342 } else {
343 None
344 }
345 },
346 Err(_err) => {
347 tracing::error!(
348 target: crate::consts::LOG_TARGET_DATABASE,
349 "Literal::as_local_name failed with iri: {}", iri.as_str()
350 );
351 None
352 },
353 }
354 })
355 }
356
357 pub fn as_str(&self) -> Option<&str> {
358 #[allow(clippy::if_same_then_else)]
359 if self.data_type.is_string() {
360 unsafe { Some(self.literal_value.string.as_str()) }
361 } else if self.data_type.is_signed_integer() {
362 None
363 } else if self.data_type.is_unsigned_integer() {
364 None
365 } else if self.data_type.is_blank_node() {
366 unsafe { Some(self.literal_value.blank_node.as_str()) }
367 } else if self.data_type.is_boolean() {
368 unsafe {
369 if self.literal_value.boolean {
370 Some("true")
371 } else {
372 Some("false")
373 }
374 }
375 } else if self.data_type.is_decimal() {
376 unsafe { Some(self.literal_value.string.as_str()) }
377 } else if self.data_type.is_duration() {
378 unsafe { Some(self.literal_value.string.as_str()) }
379 } else if self.data_type.is_date_time() {
380 unsafe { Some(self.literal_value.string.as_str()) }
381 } else {
382 panic!("Data type {:?} not yet supported", self.data_type);
383 }
384 }
385
386 pub fn as_string(&self) -> Option<String> { self.as_str().map(|v| v.to_owned()) }
387
388 pub fn as_boolean(&self) -> Option<bool> {
389 match self.data_type {
390 DataType::Boolean => Some(unsafe { self.literal_value.boolean }),
391 _ => None,
392 }
393 }
394
395 pub fn as_signed_long(&self) -> Option<i64> {
396 if self.data_type.is_signed_integer() {
397 Some(unsafe { self.literal_value.signed_integer })
398 } else {
399 None
400 }
401 }
402
403 pub fn as_unsigned_long(&self) -> Option<u64> {
404 if self.data_type.is_unsigned_integer() {
405 Some(unsafe { self.literal_value.unsigned_integer })
406 } else {
407 None
408 }
409 }
410
411 pub fn as_date(&self) -> Option<chrono::NaiveDate> {
412 match self.data_type {
413 DataType::Date => Some(unsafe { *self.literal_value.date }),
414 DataType::DateTime => self.as_date_time().map(|dt| dt.naive_utc().date()),
415 _ => None,
416 }
417 }
418
419 pub fn as_date_time(&self) -> Option<&chrono::DateTime<chrono::Utc>> {
420 match self.data_type {
421 DataType::DateTime => Some(unsafe { &self.literal_value.date_time }),
422 _ => None,
423 }
424 }
425
426 pub fn as_decimal(&self) -> Option<&str> {
427 match self.data_type {
428 DataType::Decimal => Some(unsafe { &self.literal_value.string }),
429 _ => None,
430 }
431 }
432
433 pub fn as_duration(&self) -> Option<&str> {
434 match self.data_type {
435 DataType::Duration => Some(unsafe { &self.literal_value.string }),
436 _ => None,
437 }
438 }
439
440 pub fn from_type_and_c_buffer(
441 data_type: DataType,
442 buffer: &[u8],
443 ) -> Result<Option<Literal>, ekg_error::Error> {
444 let str_buffer = std::ffi::CStr::from_bytes_until_nul(buffer)
445 .map_err(|err| {
446 tracing::error!(
447 target: crate::consts::LOG_TARGET_DATABASE,
448 "Cannot read buffer: {err:?}"
449 );
450 ekg_error::Error::Unknown })?
452 .to_str()
453 .map_err(|err| {
454 tracing::error!(
455 target: crate::consts::LOG_TARGET_DATABASE,
456 "Cannot convert buffer to string: {err:?}"
457 );
458 ekg_error::Error::Unknown })?;
460 Self::from_type_and_buffer(data_type, str_buffer, None)
461 }
462
463 pub fn from_type_and_buffer(
464 data_type: DataType,
465 buffer: &str,
466 id_base_iri: Option<&fluent_uri::Uri<&str>>,
467 ) -> Result<Option<Literal>, ekg_error::Error> {
468 match data_type {
469 DataType::AnyUri | DataType::IriReference => {
470 if buffer.starts_with('<') && buffer.ends_with('>') {
471 return Self::from_type_and_buffer(
472 data_type,
473 &buffer[1..buffer.len() - 1],
474 id_base_iri,
475 );
476 }
477 if let Ok(iri) = fluent_uri::Uri::parse(buffer) {
478 Ok(Some(Literal::new_iri_with_datatype(
479 &iri, data_type,
480 )?))
481 } else if id_base_iri.is_some() {
482 Ok(Some(Literal::new_iri_from_string_with_datatype(
483 buffer,
484 data_type,
485 id_base_iri,
486 )?))
487 } else {
488 return match fluent_uri::Uri::parse(buffer) {
489 Ok(iri) => {
490 tracing::error!(
491 target: crate::consts::LOG_TARGET_DATABASE,
492 "Cannot convert [{:?}] to a valid IRI",
493 iri
494 );
495 Err(ekg_error::Error::UnknownValueForDataType {
496 data_type_xsd_iri: data_type.as_xsd_iri_str().to_string(),
497 value: buffer.to_string(),
498 })
499 },
500 Err(error) => {
501 tracing::error!(
502 target: crate::consts::LOG_TARGET_DATABASE,
503 "Cannot convert [{buffer}] to an IRI"
504 );
505 Err(ekg_error::Error::from(error))
506 },
507 };
508 }
509 },
510 DataType::BlankNode => {
511 Ok(Some(Literal::new_blank_node_with_datatype(
512 buffer, data_type,
513 )?))
514 },
515 DataType::Boolean => {
516 match buffer {
517 "true" | "false" => {
518 Ok(Some(Literal::new_boolean_with_datatype(
519 buffer.starts_with("true"),
520 data_type,
521 )?))
522 },
523 _ => Err(ekg_error::Error::UnknownNTriplesValue { value: buffer.to_string() }),
524 }
525 },
526 DataType::String | DataType::PlainLiteral => {
527 Ok(Some(Literal::new_string_with_datatype(
528 buffer, data_type,
529 )?))
530 },
531 DataType::Date | DataType::DateTime => Self::date_from_str(buffer),
532 DataType::Int |
533 DataType::Integer |
534 DataType::NegativeInteger |
535 DataType::NonPositiveInteger |
536 DataType::Long |
537 DataType::Short => {
538 let signed_integer: i64 = buffer.parse()?; Ok(Some(Literal::new_signed_integer_with_datatype(
540 signed_integer,
541 data_type,
542 )?))
543 },
544 DataType::PositiveInteger |
545 DataType::NonNegativeInteger |
546 DataType::UnsignedByte |
547 DataType::UnsignedInt |
548 DataType::UnsignedShort |
549 DataType::UnsignedLong => {
550 let unsigned_integer: u64 = buffer.parse().unwrap(); Ok(Some(Literal::new_unsigned_integer_with_datatype(
552 unsigned_integer,
553 data_type,
554 )?))
555 },
556 DataType::Decimal => {
557 Ok(Some(Literal::new_decimal_with_datatype(
558 buffer, data_type,
559 )?))
560 },
561 DataType::Duration => {
562 Ok(Some(Literal::new_duration_with_datatype(
563 buffer, data_type,
564 )?))
565 },
566 DataType::UnboundValue => Ok(None),
567 _ => {
568 tracing::warn!(
569 target: crate::consts::LOG_TARGET_DATABASE,
570 "Unsupported datatype: {data_type:?} value={buffer}"
571 );
572 Err(ekg_error::Error::Unknown)
573 },
574 }
575 }
576
577 fn date_from_str(buffer: &str) -> Result<Option<Literal>, ekg_error::Error> {
578 if let Ok(date_time) = chrono::DateTime::parse_from_rfc2822(buffer) {
579 return Ok(Some(Literal::new_date_time_with_datatype(
580 chrono::DateTime::from(date_time),
581 DataType::DateTime,
582 )?));
583 }
584 if let Ok(date_time) = chrono::DateTime::parse_from_rfc3339(buffer) {
585 return Ok(Some(Literal::new_date_time_with_datatype(
586 chrono::DateTime::from(date_time),
587 DataType::DateTime,
588 )?));
589 }
590 if let Ok(date_time) = chrono::DateTime::parse_from_str(buffer, "%Y-%m-%d %H:%M:%S %z") {
591 return Ok(Some(Literal::new_date_time_with_datatype(
592 chrono::DateTime::from(date_time),
593 DataType::DateTime,
594 )?));
595 }
596 if let Ok(date_time) = chrono::NaiveDateTime::parse_from_str(buffer, "%Y-%m-%d %H:%M:%S") {
597 return Ok(Some(Literal::new_date_time_with_datatype(
598 chrono::DateTime::from_naive_utc_and_offset(date_time, chrono::Utc),
599 DataType::DateTime,
600 )?));
601 }
602 if let Ok(date_time) = chrono::NaiveDateTime::parse_from_str(buffer, "%Y-%m-%d %H:%M") {
603 return Ok(Some(Literal::new_date_time_with_datatype(
604 chrono::DateTime::from_naive_utc_and_offset(date_time, chrono::Utc),
605 DataType::DateTime,
606 )?));
607 }
608 if let Ok(date) = chrono::NaiveDate::parse_from_str(buffer, "%Y-%m-%d") {
609 return Ok(Some(Literal::new_date_with_datatype(
610 date,
611 DataType::Date,
612 )?));
613 }
614 if let Ok(date) = chrono::NaiveDate::parse_from_str(buffer, "%Y/%m/%d") {
615 return Ok(Some(Literal::new_date_with_datatype(
616 date,
617 DataType::Date,
618 )?));
619 }
620 if let Ok(date) = chrono::NaiveDate::parse_from_str(buffer, "%m/%d/%Y") {
621 return Ok(Some(Literal::new_date_with_datatype(
622 date,
623 DataType::Date,
624 )?));
625 }
626
627 #[cfg(feature = "serde")]
628 match serde_json::from_str::<chrono::DateTime<chrono::Utc>>(buffer) {
629 Ok(date_time) => {
630 Ok(Some(Literal::new_date_time_with_datatype(
631 date_time,
632 DataType::DateTime,
633 )?))
634 },
635 Err(error) => {
636 tracing::error!(
637 target: crate::consts::LOG_TARGET_DATABASE,
638 "Could not convert [{buffer}] to a DateTime Literal"
639 );
640 Err(ekg_error::Error::SerdeJsonError(error))
641 },
642 }
643 #[cfg(not(feature = "serde"))]
644 Err(ekg_error::Error::Unknown) }
646
647 pub fn from_iri(iri: &fluent_uri::Uri<&str>) -> Result<Self, ekg_error::Error> {
648 Ok(Literal {
649 data_type: DataType::IriReference,
650 literal_value: LiteralValue { iri: ManuallyDrop::new(iri.to_owned()) },
651 })
652 }
653
654 pub fn new_plain_literal_string(str: &str) -> Result<Self, ekg_error::Error> {
655 Self::new_string_with_datatype(str, DataType::PlainLiteral)
656 }
657
658 pub fn new_plain_literal_boolean(boolean: bool) -> Result<Self, ekg_error::Error> {
659 Self::new_string_with_datatype(
660 boolean.to_string().as_str(),
661 DataType::PlainLiteral,
662 )
663 }
664
665 pub fn new_string_with_datatype(
666 str: &str,
667 data_type: DataType,
668 ) -> Result<Self, ekg_error::Error> {
669 assert!(
670 &data_type.is_string(),
671 "{data_type:?} is not a string type"
672 );
673 Ok(Literal {
674 data_type,
675 literal_value: LiteralValue::new_string(str),
676 })
677 }
678
679 pub fn new_date_with_datatype(
682 date: chrono::NaiveDate,
683 data_type: DataType,
684 ) -> Result<Self, ekg_error::Error> {
685 assert!(
686 &data_type.is_date(),
687 "{data_type:?} is not a Date"
688 );
689 Ok(Literal {
690 data_type,
691 literal_value: LiteralValue::new_date(date),
692 })
693 }
694
695 pub fn new_date_time_with_datatype(
696 date_time: chrono::DateTime<chrono::Utc>,
697 data_type: DataType,
698 ) -> Result<Self, ekg_error::Error> {
699 assert!(
700 &data_type.is_date_time(),
701 "{data_type:?} is not a dateTime"
702 );
703 Ok(Literal {
704 data_type,
705 literal_value: LiteralValue::new_date_time(date_time),
706 })
707 }
708
709 pub fn new_decimal_with_datatype(
710 str: &str,
711 data_type: DataType,
712 ) -> Result<Self, ekg_error::Error> {
713 assert!(
714 &data_type.is_decimal(),
715 "{data_type:?} is not a decimal"
716 );
717 Ok(Literal {
718 data_type,
719 literal_value: LiteralValue::new_string(str),
720 })
721 }
722
723 pub fn new_duration_with_datatype(
724 str: &str,
725 data_type: DataType,
726 ) -> Result<Self, ekg_error::Error> {
727 assert!(
728 &data_type.is_duration(),
729 "{data_type:?} is not a duration"
730 );
731 Ok(Literal {
732 data_type,
733 literal_value: LiteralValue::new_string(str),
734 })
735 }
736
737 pub fn new_iri_from_string_with_datatype(
738 iri_string: &str,
739 data_type: DataType,
740 id_base_iri: Option<&fluent_uri::Uri<&str>>,
741 ) -> Result<Self, ekg_error::Error> {
742 match fluent_uri::Uri::parse(iri_string) {
743 Ok(ref iri) => Self::new_iri_with_datatype(iri, data_type),
744 Err(error) => {
745 if let Some(id_base_iri) = id_base_iri {
746 let iri_str =
749 fluent_uri::Uri::parse_from(format!("{}/{}", id_base_iri, iri_string))
750 .map_err(|(_s, e)| e)?;
751 return Self::from_iri(iri_str.borrow());
752 }
753 Err(ekg_error::Error::from(error))
754 },
755 }
756 }
757
758 pub fn new_iri_reference_from_str(iri: &str) -> Result<Self, ekg_error::Error> {
759 let iri = fluent_uri::Uri::parse(iri)?;
760 Self::new_iri_with_datatype(&iri, DataType::IriReference)
761 }
762
763 pub fn new_iref_iri_with_datatype(
764 iri: &iref::Iri,
765 data_type: DataType,
766 ) -> Result<Self, ekg_error::Error> {
767 assert!(
768 &data_type.is_iri(),
769 "{data_type:?} is not an IRI type"
770 );
771 Ok(Literal {
772 data_type,
773 literal_value: LiteralValue::new_iref_iri(iri)?,
774 })
775 }
776
777 pub fn new_iri_with_datatype(
778 iri: &fluent_uri::Uri<&str>,
779 data_type: DataType,
780 ) -> Result<Self, ekg_error::Error> {
781 assert!(
782 &data_type.is_iri(),
783 "{data_type:?} is not an IRI type"
784 );
785 Ok(Literal {
786 data_type,
787 literal_value: LiteralValue::new_iri(iri),
788 })
789 }
790
791 pub fn new_blank_node_with_datatype(
792 id: &str,
793 data_type: DataType,
794 ) -> Result<Self, ekg_error::Error> {
795 assert!(
796 &data_type.is_blank_node(),
797 "{data_type:?} is not a blank node type"
798 );
799 Ok(Literal {
800 data_type,
801 literal_value: LiteralValue::new_blank_node(id),
802 })
803 }
804
805 pub fn new_boolean(boolean: bool) -> Result<Self, ekg_error::Error> {
806 Self::new_boolean_with_datatype(boolean, DataType::Boolean)
807 }
808
809 pub fn new_boolean_from_string(boolean_string: &str) -> Result<Self, ekg_error::Error> {
810 Self::new_boolean_from_string_with_datatype(boolean_string, DataType::Boolean)
811 }
812
813 pub fn new_boolean_from_string_with_datatype(
814 boolean_string: &str,
815 data_type: DataType,
816 ) -> Result<Self, ekg_error::Error> {
817 match boolean_string {
818 "true" => Self::new_boolean_with_datatype(true, data_type),
819 "false" => Self::new_boolean_with_datatype(false, data_type),
820 &_ => {
821 Err(ekg_error::Error::UnknownValueForDataType {
822 data_type_xsd_iri: data_type.as_xsd_iri_str().to_string(),
823 value: boolean_string.to_string(),
824 })
825 },
826 }
827 }
828
829 pub fn new_boolean_with_datatype(
830 boolean: bool,
831 data_type: DataType,
832 ) -> Result<Self, ekg_error::Error> {
833 assert!(
834 &data_type.is_boolean(),
835 "{data_type:?} is not a boolean type"
836 );
837 Ok(Literal {
838 data_type,
839 literal_value: LiteralValue::new_boolean(boolean),
840 })
841 }
842
843 pub fn new_signed_integer(signed_integer: i64) -> Result<Self, ekg_error::Error> {
844 if signed_integer >= 0 {
845 Self::new_unsigned_integer(signed_integer as u64)
846 } else {
847 Self::new_signed_integer_with_datatype(signed_integer, DataType::NegativeInteger)
848 }
849 }
850
851 pub fn new_signed_integer_with_datatype(
852 signed_integer: i64,
853 data_type: DataType,
854 ) -> Result<Self, ekg_error::Error> {
855 assert!(
856 &data_type.is_signed_integer(),
857 "{data_type:?} is not an signed integer type"
858 );
859 Ok(Literal {
860 data_type,
861 literal_value: LiteralValue::new_signed_integer(signed_integer),
862 })
863 }
864
865 pub fn new_unsigned_integer(unsigned_integer: u64) -> Result<Self, ekg_error::Error> {
866 Self::new_unsigned_integer_with_datatype(unsigned_integer, DataType::PositiveInteger)
867 }
868
869 pub fn new_unsigned_integer_with_datatype(
870 unsigned_integer: u64,
871 data_type: DataType,
872 ) -> Result<Self, ekg_error::Error> {
873 assert!(
874 &data_type.is_unsigned_integer(),
875 "{data_type:?} is not an unsigned integer type"
876 );
877 Ok(Literal {
878 data_type,
879 literal_value: LiteralValue::new_unsigned_integer(unsigned_integer),
880 })
881 }
882
883 pub fn display_turtle<'a, 'b>(&'a self) -> impl Display + 'a + 'b
884 where 'a: 'b {
885 struct TurtleLexVal<'b>(&'b Literal);
886 impl<'b> Display for TurtleLexVal<'b> {
887 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
888 let data_type = self.0.data_type;
889 unsafe {
890 if data_type.is_iri() {
891 write!(f, "<{}>", self.0.literal_value.iri.as_str())?
892 } else if data_type.is_string() {
893 write!(f, "\"{}\"", self.0.literal_value.string.as_str())?
894 } else if data_type.is_blank_node() {
895 write!(
896 f,
897 "_:{}",
898 self.0.literal_value.blank_node.as_str()
899 )?
900 } else if data_type.is_boolean() {
901 write!(f, "{}", self.0.literal_value.boolean)?
902 } else if data_type.is_signed_integer() {
903 write!(f, "{}", self.0.literal_value.signed_integer)?
904 } else if data_type.is_unsigned_integer() {
905 write!(f, "{}", self.0.literal_value.unsigned_integer)?
906 } else if data_type.is_date_time() {
907 write!(
908 f,
909 "\"{}\"^^xsd:dateTime",
910 self.0.literal_value.string.as_str()
911 )?
912 } else if data_type.is_decimal() {
913 write!(f, "{}", self.0.literal_value.string.as_str())?
914 } else if data_type.is_duration() {
915 write!(
916 f,
917 "\"{}\"^^xsd:duration",
918 self.0.literal_value.string.as_str()
919 )?
920 } else {
921 panic!("Cannot format for turtle, unimplemented datatype {data_type:?}")
922 }
923 }
924 Ok(())
925 }
926 }
927 TurtleLexVal(self)
928 }
929
930 pub fn display_json<'a, 'b>(&'a self) -> impl Display + 'a + 'b
931 where 'a: 'b {
932 struct JsonLexVal<'b>(&'b Literal);
933 impl<'b> Display for JsonLexVal<'b> {
934 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
935 let data_type = self.0.data_type;
936 unsafe {
937 if data_type.is_iri() {
938 write!(f, "\"{}\"", *self.0.literal_value.iri)?
939 } else if data_type.is_string() {
940 write!(
941 f,
942 "\"{}\"",
943 self.0.literal_value.string.replace('\"', "\\\"").as_str()
944 )?
945 } else if data_type.is_blank_node() {
946 write!(
947 f,
948 "\"_:{}\"",
949 self.0.literal_value.blank_node.as_str()
950 )?
951 } else if data_type.is_boolean() {
952 write!(f, "{}", self.0.literal_value.boolean)?
953 } else if data_type.is_signed_integer() {
954 write!(f, "{}", self.0.literal_value.signed_integer)?
955 } else if data_type.is_unsigned_integer() {
956 write!(f, "{}", self.0.literal_value.unsigned_integer)?
957 } else if data_type.is_date_time() {
958 write!(f, "\"{}\"", self.0.literal_value.string.as_str())?
959 } else if data_type.is_decimal() {
960 write!(f, "{}", self.0.literal_value.string.as_str())?
961 } else if data_type.is_duration() {
962 write!(f, "\"{}\"", self.0.literal_value.string.as_str())?
963 } else {
964 panic!("Cannot format for JSON, unimplemented datatype {data_type:?}")
965 }
966 }
967 Ok(())
968 }
969 }
970 JsonLexVal(self)
971 }
972
973 pub fn as_url_display(&self) -> LiteralUrlDisplay { LiteralUrlDisplay { literal: self } }
974
975 pub fn as_id_url_display<'a>(
976 &'a self,
977 id_base_iri: &'a fluent_uri::Uri<&'a str>,
978 ) -> LiteralIdUrlDisplay {
979 LiteralIdUrlDisplay { literal: self, id_base_iri }
980 }
981
982 pub fn is_id_iri(&self, id_base_iri: &fluent_uri::Uri<&str>) -> bool {
984 match self.data_type {
985 DataType::AnyUri | DataType::IriReference => unsafe {
986 self.literal_value
987 .iri
988 .to_string()
989 .starts_with(id_base_iri.to_string().as_str())
990 },
991 _ => false,
992 }
993 }
994
995 pub fn as_id(&self, id_base_iri: &fluent_uri::Uri<&str>) -> Result<String, ekg_error::Error> {
996 match self.data_type {
997 DataType::AnyUri | DataType::IriReference => unsafe {
998 let len = id_base_iri.to_string().len();
999 let str = self.literal_value.iri.to_string();
1000 let (_first, last) = str.split_at(len);
1001 Ok(last.to_string())
1002 },
1003 _ => Err(ekg_error::Error::UnknownDataType { data_type_id: self.data_type as u8 }),
1004 }
1005 }
1006}
1007
1008#[cfg(feature = "serde")]
1009struct LiteralDeserializeVisitor;
1010
1011#[cfg(feature = "serde")]
1012impl<'de> serde::de::Visitor<'de> for LiteralDeserializeVisitor {
1013 type Value = Literal;
1014
1015 fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
1016 formatter.write_str("a correct literal value")
1017 }
1018
1019 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
1020 where E: serde::de::Error {
1021 if let Ok(Some(iri)) = Literal::from_type_and_buffer(DataType::AnyUri, v, None) {
1022 return Ok(iri);
1023 }
1024 if let Ok(Some(integer)) = Literal::from_type_and_buffer(DataType::Integer, v, None) {
1025 return Ok(integer);
1026 }
1027 if let Ok(Some(date_time)) = Literal::from_type_and_buffer(DataType::DateTime, v, None) {
1028 return Ok(date_time);
1029 }
1030 if let Ok(Some(decimal)) = Literal::from_type_and_buffer(DataType::Decimal, v, None) {
1031 return Ok(decimal);
1032 }
1033 match Literal::from_str(v) {
1034 Ok(literal) => Ok(literal),
1035 Err(rdf_store_error) => Err(E::custom(rdf_store_error.to_string())),
1036 }
1037 }
1038}