Skip to main content

rudof_rdf/rdf_core/term/literal/
literal.rs

1use crate::rdf_core::{
2    RDFError,
3    term::literal::{Lang, NumericLiteral, XsdDateTime},
4};
5use rust_decimal::Decimal;
6use std::{
7    fmt::{self, Debug, Display},
8    hash::Hash,
9    result,
10};
11
12use crate::rdf_core::vocabs::{RdfVocab, XsdVocab};
13use iri_s::IriS;
14use prefixmap::{DerefError, DerefIri, IriRef, PrefixMap};
15use serde::{Deserialize, Serialize, Serializer};
16
17/// Types that implement this trait can be used as RDF Literals.
18///
19/// This trait provides methods for accessing literal properties and converting
20/// literals to specific Rust types based on their XSD datatype.
21pub trait Literal: Debug + Clone + Display + PartialEq + Eq + Hash {
22    /// Returns the lexical form of the literal as a string slice.
23    fn lexical_form(&self) -> &str;
24
25    /// Returns the language tag if this is a language-tagged literal.
26    fn lang(&self) -> Option<Lang>;
27
28    /// Returns the datatype IRI of this literal.
29    fn datatype(&self) -> IriRef;
30
31    /// Converts this literal to an `ConcreteLiteral` if possible.
32    fn to_concrete_literal(&self) -> Option<ConcreteLiteral>;
33
34    /// Attempts to convert this literal to a boolean value.
35    ///
36    /// Returns `Some(bool)` if the literal has datatype `xsd:boolean` and
37    /// a valid lexical form ("true" or "false").
38    fn to_bool(&self) -> Option<bool> {
39        let datatype = self.datatype();
40        let iri = datatype.get_iri().ok()?;
41
42        if iri.as_str() != "http://www.w3.org/2001/XMLSchema#boolean" {
43            return None;
44        }
45
46        match self.lexical_form() {
47            "true" => Some(true),
48            "false" => Some(false),
49            _ => None,
50        }
51    }
52
53    /// Attempts to convert this literal to an integer value.
54    ///
55    /// Returns `Some(isize)` if the literal has datatype `xsd:integer` and
56    /// a valid parseable lexical form.
57    fn to_integer(&self) -> Option<isize> {
58        let datatype = self.datatype();
59        let iri = datatype.get_iri().ok()?;
60
61        if iri.as_str() != "http://www.w3.org/2001/XMLSchema#integer" {
62            return None;
63        }
64
65        self.lexical_form().parse().ok()
66    }
67
68    /// Attempts to convert this literal to a datetime value.
69    ///
70    /// Returns `Some(XsdDateTime)` if the literal has datatype `xsd:dateTime` and
71    /// a valid parseable lexical form.
72    fn to_date_time(&self) -> Option<XsdDateTime> {
73        let datatype = self.datatype();
74        let iri = datatype.get_iri().ok()?;
75
76        if iri.as_str() != "http://www.w3.org/2001/XMLSchema#dateTime" {
77            return None;
78        }
79
80        XsdDateTime::new(self.lexical_form()).ok()
81    }
82
83    /// Attempts to convert this literal to a double-precision float value.
84    ///
85    /// Returns `Some(f64)` if the literal has datatype `xsd:double` and
86    /// a valid parseable lexical form.
87    fn to_double(&self) -> Option<f64> {
88        let datatype = self.datatype();
89        let iri = datatype.get_iri().ok()?;
90
91        if iri.as_str() != "http://www.w3.org/2001/XMLSchema#double" {
92            return None;
93        }
94
95        self.lexical_form().parse().ok()
96    }
97
98    /// Attempts to convert this literal to a decimal value.
99    ///
100    /// Returns `Some(Decimal)` if the literal has datatype `xsd:decimal` and
101    /// a valid parseable lexical form.
102    fn to_decimal(&self) -> Option<Decimal> {
103        let datatype = self.datatype();
104        let iri = datatype.get_iri().ok()?;
105
106        if iri.as_str() != "http://www.w3.org/2001/XMLSchema#decimal" {
107            return None;
108        }
109
110        self.lexical_form().parse().ok()
111    }
112}
113
114/// Concrete representation of RDF literals with type-safe internal representations.
115///
116/// This enum provides a strongly-typed representation of RDF literals, using native
117/// Rust types (integers, floats, booleans, etc.) internally for efficiency. It also
118/// supports literals with incorrect datatypes to enable parsing and validation of
119/// potentially malformed RDF data.
120///
121/// # Type Safety
122///
123/// The enum uses native Rust types internally, providing type safety and efficient
124/// operations on numeric values. For example, `NumericLiteral` stores actual numeric
125/// values rather than strings, enabling direct mathematical operations.
126///
127/// # Error Handling
128///
129/// The [`WrongDatatypeLiteral`](Self::WrongDatatypeLiteral) variant allows parsing
130/// and representing malformed RDF data (e.g., `"hello"^^xsd:integer`) without losing
131/// information. This enables validation workflows that need to report specific errors
132/// while continuing to process other data.
133///
134/// # Comparison and Ordering
135///
136/// Literals implement [`PartialOrd`] and [`Ord`] following SPARQL ordering rules:
137/// - String literals are compared lexicographically
138/// - Numeric literals are compared by numeric value
139/// - Boolean literals follow `false < true`
140/// - Datetime literals are compared chronologically
141///
142/// # Panics
143///
144/// The [`Ord`] implementation panics when comparing incomparable literals (e.g., NaN
145/// floating-point values or literals with different datatypes). Use [`PartialOrd`]
146/// when comparing arbitrary literals to avoid panics.
147#[derive(PartialEq, Eq, Hash, Debug, Serialize, Deserialize, Clone)]
148#[allow(clippy::enum_variant_names)]
149pub enum ConcreteLiteral {
150    /// A plain string literal, optionally with a language tag.
151    StringLiteral {
152        lexical_form: String,
153        #[serde(skip_serializing_if = "Option::is_none")]
154        lang: Option<Lang>,
155    },
156
157    /// A literal with an explicit datatype IRI.
158    DatatypeLiteral { lexical_form: String, datatype: IriRef },
159
160    /// A numeric literal (integer, float, decimal, etc.).
161    NumericLiteral(NumericLiteral),
162
163    /// An XSD datetime literal.
164    DatetimeLiteral(XsdDateTime),
165
166    /// A boolean literal (true or false).
167    #[serde(serialize_with = "serialize_boolean_literal")]
168    BooleanLiteral(bool),
169
170    /// Represents a literal with an invalid datatype.
171    ///
172    /// For example, a value like `"hello"^^xsd:integer` would be represented as a
173    /// `WrongDatatypeLiteral`. This is useful for parsing RDF data that may contain
174    /// malformed literals while still enabling validation.
175    WrongDatatypeLiteral {
176        lexical_form: String,
177        datatype: IriRef,
178        error: String,
179    },
180}
181
182/// ## Display and formatting
183impl ConcreteLiteral {
184    /// Returns a string representation using the given prefix map to qualify IRIs.
185    ///
186    /// This method formats the literal using shortened IRI prefixes from the provided
187    /// prefix map, making the output more readable.
188    ///
189    /// # Arguments
190    ///
191    /// * `prefixmap` - The prefix map used to shorten IRIs
192    ///
193    /// # Examples
194    ///
195    /// ```
196    /// use rudof_rdf::rdf_core::term::literal::ConcreteLiteral;
197    /// use prefixmap::PrefixMap;
198    ///
199    /// let lit = ConcreteLiteral::integer(42);
200    /// let prefixmap = PrefixMap::basic();
201    /// println!("{}", lit.show_qualified(&prefixmap));
202    /// ```
203    pub fn show_qualified(&self, prefixmap: &PrefixMap) -> String {
204        let mut s = String::new();
205        let _ = self.display_qualified(&mut s, prefixmap);
206        s
207    }
208
209    /// Formats this literal using the given prefix map and writes the result
210    /// into the provided formatter.
211    ///
212    /// The output follows RDF/Turtle-style literal syntax:
213    /// - String literals are quoted, with an optional language tag
214    /// - Numeric and boolean literals are written as-is
215    /// - Datatype literals are written using `^^` and qualified IRIs
216    /// - Datatypes are shortened using the provided prefix map when possible
217    ///
218    /// This method is intended for internal use by [`show_qualified`] and
219    /// `Display` implementations rather than being called directly.
220    ///
221    /// # Arguments
222    ///
223    /// * `f` - The output writer to which the literal representation is written
224    /// * `prefixmap` - The prefix map used to qualify datatype IRIs
225    ///
226    /// # Errors
227    ///
228    /// Returns any formatting error encountered while writing to the formatter.
229    pub fn display_qualified<W: fmt::Write>(&self, f: &mut W, prefixmap: &PrefixMap) -> fmt::Result {
230        match self {
231            Self::StringLiteral { lexical_form, lang } => {
232                write!(f, "\"{lexical_form}\"")?;
233                if let Some(lang) = lang {
234                    write!(f, "{lang}")?;
235                }
236                Ok(())
237            },
238            Self::DatatypeLiteral { lexical_form, datatype } => {
239                self.format_datatype_literal(f, lexical_form, datatype, prefixmap)
240            },
241            Self::NumericLiteral(n) => write!(f, "{n}"),
242            Self::BooleanLiteral(b) => write!(f, "{b}"),
243            Self::DatetimeLiteral(dt) => write!(f, "{}", dt.value()),
244            Self::WrongDatatypeLiteral {
245                lexical_form, datatype, ..
246            } => self.format_datatype_literal(f, lexical_form, datatype, prefixmap),
247        }
248    }
249
250    /// Helper method to format datatype literals in a consistent way.
251    ///
252    /// This method writes a typed literal using RDF/Turtle syntax:
253    /// "lexical_form"^^datatype
254    ///
255    /// If the datatype IRI can be qualified using the provided prefix map,
256    /// the shortened prefixed form is used (e.g. `xsd:string`). Otherwise,
257    /// the full IRI is written.
258    ///
259    /// # Arguments
260    ///
261    /// * `f` - The output writer to which the literal representation is written
262    /// * `lexical_form` - The lexical form of the literal
263    /// * `datatype` - The datatype IRI or prefixed name
264    /// * `prefixmap` - The prefix map used to qualify IRIs
265    ///
266    /// # Errors
267    ///
268    /// Returns any formatting error encountered while writing to the formatter.
269    fn format_datatype_literal<W: fmt::Write>(
270        &self,
271        f: &mut W,
272        lexical_form: &str,
273        datatype: &IriRef,
274        prefixmap: &PrefixMap,
275    ) -> fmt::Result {
276        match datatype {
277            IriRef::Iri(iri) => {
278                write!(f, "\"{lexical_form}\"^^{}", prefixmap.qualify(iri))
279            },
280            IriRef::Prefixed { prefix, local } => {
281                write!(f, "\"{lexical_form}\"^^{prefix}:{local}")
282            },
283        }
284    }
285}
286
287/// ## Validation and Conversion
288impl ConcreteLiteral {
289    /// Validates that the lexical form matches the declared datatype,
290    /// consuming the literal and returning a validated version.
291    ///
292    /// This method checks whether the lexical form of a datatype literal
293    /// is compatible with its declared datatype. If the validation succeeds,
294    /// a properly typed literal is returned. If the validation fails,
295    /// a `WrongDatatypeLiteral` is returned instead.
296    ///
297    /// For non-datatype literals, the value is returned unchanged.
298    ///
299    /// # Errors
300    ///
301    /// Returns an `LiteralError` if datatype validation fails.
302    ///
303    /// # Examples
304    ///
305    /// ```
306    /// use rudof_rdf::rdf_core::term::literal::ConcreteLiteral;
307    /// use iri_s::IriS;
308    /// use prefixmap::IriRef;
309    ///
310    /// // Create a datatype literal with an integer value
311    /// let dt_iri = IriRef::iri(IriS::new_unchecked("http://www.w3.org/2001/XMLSchema#integer"));
312    /// let lit = ConcreteLiteral::lit_datatype("42", &dt_iri);
313    ///
314    /// // Validate the literal
315    /// let checked = lit.into_checked_literal().unwrap();
316    /// ```
317    pub fn into_checked_literal(self) -> Result<Self, RDFError> {
318        if let Self::DatatypeLiteral { lexical_form, datatype } = self {
319            check_literal_datatype(lexical_form.as_ref(), &datatype)
320        } else {
321            Ok(self)
322        }
323    }
324
325    /// Compares this literal with another for equality.
326    ///
327    /// This method performs type-aware comparison, ensuring that literals of
328    /// different types are not considered equal even if their lexical forms match.
329    ///
330    /// # Arguments
331    ///
332    /// * `literal_expected` - The literal to compare against
333    ///
334    /// # Returns
335    ///
336    /// `true` if the literals are equal, `false` otherwise.
337    ///
338    /// # Examples
339    ///
340    /// ```
341    /// use rudof_rdf::rdf_core::term::literal::ConcreteLiteral;
342    /// use rudof_rdf::rdf_core::term::literal::Lang;
343    ///
344    /// let lit1 = ConcreteLiteral::str("hello");
345    /// let lit2 = ConcreteLiteral::str("hello");
346    /// let lit3 = ConcreteLiteral::lang_str("hello", Lang::new("en").unwrap());
347    /// let lit4 = ConcreteLiteral::integer(42);
348    ///
349    /// // Plain string literals with the same content are equal
350    /// assert!(lit1.match_literal(&lit2));
351    ///
352    /// // Language-tagged string literals must match both lexical form and lang
353    /// assert!(!lit1.match_literal(&lit3));
354    ///
355    /// // Numeric and string literals are not equal even if lexical forms match
356    /// let lit5 = ConcreteLiteral::lit_datatype("42", &lit4.datatype());
357    /// assert!(!lit5.match_literal(&lit4));
358    ///
359    /// // Comparing numeric literals of the same value returns true
360    /// let lit6 = ConcreteLiteral::integer(42);
361    /// assert!(lit4.match_literal(&lit6));
362    /// ```
363    pub fn match_literal(&self, literal_expected: &Self) -> bool {
364        match (self, literal_expected) {
365            (
366                Self::StringLiteral { lexical_form, lang },
367                Self::StringLiteral {
368                    lexical_form: expected_lexical_form,
369                    lang: expected_lang,
370                },
371            ) => lexical_form == expected_lexical_form && lang == expected_lang,
372            (
373                Self::DatatypeLiteral { lexical_form, datatype },
374                Self::DatatypeLiteral {
375                    lexical_form: expected_lexical_form,
376                    datatype: expected_datatype,
377                },
378            ) => lexical_form == expected_lexical_form && datatype == expected_datatype,
379            (Self::NumericLiteral(n1), Self::NumericLiteral(n2)) => n1 == n2,
380            (Self::DatetimeLiteral(dt1), Self::DatetimeLiteral(dt2)) => dt1 == dt2,
381            (Self::BooleanLiteral(b1), Self::BooleanLiteral(b2)) => b1 == b2,
382            (
383                Self::WrongDatatypeLiteral {
384                    lexical_form, datatype, ..
385                },
386                Self::WrongDatatypeLiteral {
387                    lexical_form: expected_lexical_form,
388                    datatype: expected_datatype,
389                    ..
390                },
391            ) => lexical_form == expected_lexical_form && datatype == expected_datatype,
392            _ => false,
393        }
394    }
395}
396
397/// ## Constructor Methods - Numeric Types
398impl ConcreteLiteral {
399    /// Creates a literal representing an unbounded integer (`i128`).
400    ///
401    /// This corresponds to XSD's `xsd:integer` type, which is unbounded.
402    #[inline]
403    pub fn integer(n: i128) -> Self {
404        Self::NumericLiteral(NumericLiteral::integer(n))
405    }
406
407    /// Creates a literal representing a non-negative integer (`u128` ≥ 0).
408    ///
409    /// This corresponds to XSD's `xsd:nonNegativeInteger` type.
410    #[inline]
411    pub fn non_negative_integer(n: u128) -> Self {
412        Self::NumericLiteral(NumericLiteral::non_negative_integer(n))
413    }
414
415    /// Creates a literal representing a non-positive integer (`i128` ≤ 0).
416    ///
417    /// This corresponds to XSD's `xsd:nonPositiveInteger` type.
418    ///
419    /// # Errors
420    /// Returns `RDFError::NumericOutOfRange` if `n` is greater than 0.
421    #[inline]
422    pub fn non_positive_integer(n: i128) -> Result<Self, RDFError> {
423        Ok(Self::NumericLiteral(NumericLiteral::non_positive_integer(n)?))
424    }
425
426    /// Creates a literal representing a strictly positive integer (`u128` > 0).
427    ///
428    /// This corresponds to XSD's `xsd:positiveInteger` type.
429    ///
430    /// # Errors
431    /// Returns `RDFError::NumericOutOfRange` if `n` is 0.
432    #[inline]
433    pub fn positive_integer(n: u128) -> Result<Self, RDFError> {
434        Ok(Self::NumericLiteral(NumericLiteral::positive_integer(n)?))
435    }
436
437    /// Creates a literal representing a strictly negative integer (`i128` < 0).
438    ///
439    /// This corresponds to XSD's `xsd:negativeInteger` type.
440    ///
441    /// # Errors
442    /// Returns `RDFError::NumericOutOfRange` if `n` is greater than or equal to 0.
443    #[inline]
444    pub fn negative_integer(n: i128) -> Result<Self, RDFError> {
445        Ok(Self::NumericLiteral(NumericLiteral::negative_integer(n)?))
446    }
447
448    /// Creates a literal representing a double-precision floating-point number (`f64`).
449    ///
450    /// This corresponds to XSD's `xsd:double` type (64-bit IEEE 754).
451    #[inline]
452    pub fn double(d: f64) -> Self {
453        Self::NumericLiteral(NumericLiteral::double(d))
454    }
455
456    /// Creates a literal representing a decimal number (`Decimal` type for precise arithmetic).
457    ///
458    /// This corresponds to XSD's `xsd:decimal` type for exact decimal arithmetic.
459    #[inline]
460    pub fn decimal(d: Decimal) -> Self {
461        Self::NumericLiteral(NumericLiteral::decimal(d))
462    }
463
464    /// Creates a literal representing a 64-bit signed long integer (`i64`).
465    ///
466    /// This corresponds to XSD's `xsd:long` type (-9,223,372,036,854,775,808 to 9,223,372,036,854,775,807).
467    #[inline]
468    pub fn long(n: i64) -> Self {
469        Self::NumericLiteral(NumericLiteral::long(n))
470    }
471
472    /// Creates a literal representing a signed byte (`i8`), values -128 to 127.
473    ///
474    /// This corresponds to XSD's `xsd:byte` type.
475    #[inline]
476    pub fn byte(n: i8) -> Self {
477        Self::NumericLiteral(NumericLiteral::byte(n))
478    }
479
480    /// Creates a literal representing a signed short (`i16`), values -32,768 to 32,767.
481    ///
482    /// This corresponds to XSD's `xsd:short` type.
483    #[inline]
484    pub fn short(n: i16) -> Self {
485        Self::NumericLiteral(NumericLiteral::short(n))
486    }
487
488    /// Creates a literal representing an unsigned byte (`u8`), values 0–255.
489    ///
490    /// This corresponds to XSD's `xsd:unsignedByte` type.
491    #[inline]
492    pub fn unsigned_byte(n: u8) -> Self {
493        Self::NumericLiteral(NumericLiteral::unsigned_byte(n))
494    }
495
496    /// Creates a literal representing an unsigned short (`u16`), values 0–65,535.
497    ///
498    /// This corresponds to XSD's `xsd:unsignedShort` type.
499    #[inline]
500    pub fn unsigned_short(n: u16) -> Self {
501        Self::NumericLiteral(NumericLiteral::unsigned_short(n))
502    }
503
504    /// Creates a literal representing an unsigned integer (`u32`).
505    ///
506    /// This corresponds to XSD's `xsd:unsignedInt` type.
507    #[inline]
508    pub fn unsigned_int(n: u32) -> Self {
509        Self::NumericLiteral(NumericLiteral::unsigned_int(n))
510    }
511
512    /// Creates a literal representing an unsigned long integer (`u64`).
513    ///
514    /// This corresponds to XSD's `xsd:unsignedLong` type.
515    #[inline]
516    pub fn unsigned_long(n: u64) -> Self {
517        Self::NumericLiteral(NumericLiteral::unsigned_long(n))
518    }
519
520    /// Creates a literal representing a single-precision floating-point number (`f32`).
521    ///
522    /// This corresponds to XSD's `xsd:float` type (32-bit IEEE 754).
523    #[inline]
524    pub fn float(n: f32) -> Self {
525        Self::NumericLiteral(NumericLiteral::float(n))
526    }
527
528    /// Creates a DatetimeLiteral
529    pub fn datetime(dt: XsdDateTime) -> Self {
530        Self::DatetimeLiteral(dt)
531    }
532}
533
534/// ## Constructor Methods - Other Types
535impl ConcreteLiteral {
536    /// Creates a literal with a custom datatype.
537    ///
538    /// # Parameters
539    /// - `lexical_form`: The string representation of the literal's value.
540    /// - `datatype`: The IRI that identifies the literal's datatype.
541    pub fn lit_datatype(lexical_form: &str, datatype: &IriRef) -> Self {
542        Self::DatatypeLiteral {
543            lexical_form: lexical_form.to_owned(),
544            datatype: datatype.clone(),
545        }
546    }
547
548    /// Creates a boolean literal (`true` or `false`).
549    #[inline]
550    pub fn boolean(b: bool) -> Self {
551        Self::BooleanLiteral(b)
552    }
553
554    /// Creates a plain string literal without a language tag.
555    ///
556    /// # Parameters
557    /// - `lexical_form`: The text content of the literal.
558    pub fn str(lexical_form: &str) -> Self {
559        Self::StringLiteral {
560            lexical_form: lexical_form.to_owned(),
561            lang: None,
562        }
563    }
564
565    /// Creates a string literal with a language tag.
566    ///
567    /// # Parameters
568    /// - `lexical_form`: The text content of the literal.
569    /// - `lang`: The language of the literal, e.g., `"en"` for English.
570    pub fn lang_str(lexical_form: &str, lang: Lang) -> Self {
571        Self::StringLiteral {
572            lexical_form: lexical_form.to_owned(),
573            lang: Some(lang),
574        }
575    }
576}
577
578/// ## Accessor Methods
579impl ConcreteLiteral {
580    /// Returns the language tag of the literal, if it is a language-tagged string.
581    pub fn lang(&self) -> Option<Lang> {
582        match self {
583            Self::StringLiteral { lang, .. } => lang.clone(),
584            _ => None,
585        }
586    }
587
588    /// Returns the lexical form (string representation) of the literal.
589    ///
590    /// # Returns
591    /// A `String` representing the literal's value:
592    /// - For string or datatype literals, returns the literal text.
593    /// - For numeric literals, returns the numeric value as a string.
594    /// - For boolean literals, returns `"true"` or `"false"`.
595    /// - For datetime literals, returns a standard string representation.
596    ///
597    pub fn lexical_form(&self) -> String {
598        match self {
599            Self::StringLiteral { lexical_form, .. }
600            | Self::DatatypeLiteral { lexical_form, .. }
601            | Self::WrongDatatypeLiteral { lexical_form, .. } => lexical_form.clone(),
602            Self::NumericLiteral(nl) => nl.lexical_form(),
603            Self::BooleanLiteral(b) => b.to_string(),
604            Self::DatetimeLiteral(dt) => dt.to_string(),
605        }
606    }
607
608    /// Returns the datatype IRI of the literal.
609    ///
610    /// # Returns
611    /// - For explicitly typed literals (`DatatypeLiteral` or `WrongDatatypeLiteral`), returns the stored datatype IRI.
612    /// - For plain string literals without a language tag, returns `xsd:string`.
613    /// - For language-tagged string literals, returns `rdf:langString`.
614    /// - For numeric literals, returns the appropriate XML Schema datatype (e.g., `xsd:integer`, `xsd:double`).
615    /// - For boolean literals, returns `xsd:boolean`.
616    /// - For datetime literals, returns `xsd:dateTime`.
617    pub fn datatype(&self) -> IriRef {
618        match self {
619            Self::DatatypeLiteral { datatype, .. } | Self::WrongDatatypeLiteral { datatype, .. } => datatype.clone(),
620
621            Self::StringLiteral { lang: None, .. } => IriRef::iri(IriS::new_unchecked(XsdVocab::XSD_STRING)),
622
623            Self::StringLiteral { lang: Some(_), .. } => IriRef::iri(IriS::new_unchecked(RdfVocab::RDF_LANG_STRING)),
624
625            Self::NumericLiteral(nl) => IriRef::iri(IriS::new_unchecked(nl.datatype())),
626
627            Self::BooleanLiteral(_) => IriRef::iri(IriS::new_unchecked(XsdVocab::XSD_BOOLEAN)),
628            Self::DatetimeLiteral(_) => IriRef::iri(IriS::new_unchecked(XsdVocab::XSD_DATE_TIME)),
629        }
630    }
631
632    /// Returns the numeric literal value, if this literal is numeric.
633    pub fn numeric_value(&self) -> Option<NumericLiteral> {
634        match self {
635            Self::NumericLiteral(nl) => Some(nl.clone()),
636            _ => None,
637        }
638    }
639}
640
641/// ## Parsing Methods
642impl ConcreteLiteral {
643    /// Parses a boolean from its XSD lexical representation.
644    ///
645    /// Valid values are: "true", "false", "1" (true), "0" (false).
646    /// Parsing is case-sensitive.
647    ///
648    /// # Errors
649    ///
650    /// Returns an error if the input string is not a valid boolean representation.
651    ///
652    /// # Examples
653    ///
654    /// ```
655    /// use rudof_rdf::rdf_core::term::literal::ConcreteLiteral;
656    /// assert_eq!(ConcreteLiteral::parse_bool("true").unwrap(), true);
657    /// assert_eq!(ConcreteLiteral::parse_bool("0").unwrap(), false);
658    /// assert!(ConcreteLiteral::parse_bool("yes").is_err());
659    /// ```
660    pub fn parse_bool(s: &str) -> Result<bool, String> {
661        match s {
662            "true" | "1" => Ok(true),
663            "false" | "0" => Ok(false),
664            _ => Err(format!("Cannot convert {s} to boolean")),
665        }
666    }
667
668    /// Parses an integer from its string representation.
669    ///
670    /// XSD integer is unbounded, so this returns `i128`.
671    ///
672    /// # Errors
673    ///
674    /// Returns an error if the string cannot be parsed as an integer.
675    ///
676    /// # Examples
677    ///
678    /// ```
679    /// use rudof_rdf::rdf_core::term::literal::ConcreteLiteral;
680    /// assert_eq!(ConcreteLiteral::parse_integer("-7").unwrap(), -7);
681    /// assert_eq!(ConcreteLiteral::parse_integer("2").unwrap(), 2);
682    /// assert!(ConcreteLiteral::parse_integer("x").is_err());
683    /// ```
684    pub fn parse_integer(s: &str) -> Result<i128, String> {
685        s.parse::<i128>()
686            .map_err(|e| format!("Cannot convert {s} to integer: {e}"))
687    }
688
689    /// Parses a negative integer from its string representation.
690    ///
691    /// # Errors
692    ///
693    /// Returns an error if the value is not negative or cannot be parsed.
694    ///
695    /// # Examples
696    ///
697    /// ```
698    /// use rudof_rdf::rdf_core::term::literal::ConcreteLiteral;
699    /// assert_eq!(ConcreteLiteral::parse_negative_integer("-3").unwrap(), -3);
700    /// assert!(ConcreteLiteral::parse_negative_integer("0").is_err());
701    /// ```
702    pub fn parse_negative_integer(s: &str) -> Result<i128, String> {
703        let value = s
704            .parse::<i128>()
705            .map_err(|e| format!("Cannot convert {s} to negative integer: {e}"))?;
706
707        if value < 0 {
708            Ok(value)
709        } else {
710            Err(format!("Cannot convert {s} to negative integer: value is not negative"))
711        }
712    }
713
714    /// Parses a non-positive integer from its string representation.
715    ///
716    /// # Errors
717    ///
718    /// Returns an error if the value is positive or cannot be parsed.
719    pub fn parse_non_positive_integer(s: &str) -> Result<i128, String> {
720        let value = s
721            .parse::<i128>()
722            .map_err(|e| format!("Cannot convert {s} to non-positive integer: {e}"))?;
723
724        if value <= 0 {
725            Ok(value)
726        } else {
727            Err(format!("Cannot convert {s} to non-positive integer: value is positive"))
728        }
729    }
730
731    /// Parses a positive integer from its string representation.
732    ///
733    /// # Errors
734    ///
735    /// Returns an error if the value is not positive or cannot be parsed.
736    pub fn parse_positive_integer(s: &str) -> Result<u128, String> {
737        let value = s
738            .parse::<u128>()
739            .map_err(|e| format!("Cannot convert {s} to positive integer: {e}"))?;
740
741        if value > 0 {
742            Ok(value)
743        } else {
744            Err(format!("Cannot convert {s} to positive integer: value is not positive"))
745        }
746    }
747
748    /// Parses a non-negative integer from its string representation.
749    ///
750    /// # Errors
751    ///
752    /// Returns an error if the string cannot be parsed as a non-negative integer.
753    pub fn parse_non_negative_integer(s: &str) -> Result<u128, String> {
754        s.parse::<u128>()
755            .map_err(|e| format!("Cannot convert {s} to non-negative integer: {e}"))
756    }
757
758    /// Parses an unsigned byte (0–255) from its string representation.
759    ///
760    /// # Errors
761    ///
762    /// Returns an error if the string cannot be parsed as a `u8`.
763    pub fn parse_unsigned_byte(s: &str) -> Result<u8, String> {
764        s.parse::<u8>()
765            .map_err(|e| format!("Cannot convert {s} to unsignedByte: {e}"))
766    }
767
768    /// Parses an unsigned short (0–65535) from its string representation.
769    ///
770    /// # Errors
771    ///
772    /// Returns an error if the string cannot be parsed as a `u16`.
773    pub fn parse_unsigned_short(s: &str) -> Result<u16, String> {
774        s.parse::<u16>()
775            .map_err(|e| format!("Cannot convert {s} to unsignedShort: {e}"))
776    }
777
778    /// Parses an unsigned integer from its string representation.
779    ///
780    /// # Errors
781    ///
782    /// Returns an error if the string cannot be parsed as a `u32`.
783    pub fn parse_unsigned_int(s: &str) -> Result<u32, String> {
784        s.parse::<u32>()
785            .map_err(|e| format!("Cannot convert {s} to unsignedInt: {e}"))
786    }
787
788    /// Parses an unsigned long (0–u64::MAX) from its string representation.
789    ///
790    /// # Errors
791    ///
792    /// Returns an error if the string cannot be parsed as a `u64`.
793    pub fn parse_unsigned_long(s: &str) -> Result<u64, String> {
794        s.parse::<u64>()
795            .map_err(|e| format!("Cannot convert {s} to unsignedLong: {e}"))
796    }
797
798    /// Parses a double (64-bit float) from its string representation.
799    ///
800    /// # Errors
801    ///
802    /// Returns an error if the string cannot be parsed as a `f64`.
803    pub fn parse_double(s: &str) -> Result<f64, String> {
804        s.parse::<f64>()
805            .map_err(|e| format!("Cannot convert {s} to double: {e}"))
806    }
807
808    /// Parses a long integer (64-bit signed) from its string representation.
809    ///
810    /// # Errors
811    ///
812    /// Returns an error if the string cannot be parsed as an `i64`.
813    pub fn parse_long(s: &str) -> Result<i64, String> {
814        s.parse::<i64>().map_err(|e| format!("Cannot convert {s} to long: {e}"))
815    }
816
817    /// Parses a decimal from its string representation using `rust_decimal::Decimal`.
818    ///
819    /// # Errors
820    ///
821    /// Returns an error if the string cannot be parsed as a `Decimal`.
822    pub fn parse_decimal(s: &str) -> Result<Decimal, String> {
823        s.parse::<Decimal>()
824            .map_err(|e| format!("Cannot convert {s} to decimal: {e}"))
825    }
826
827    /// Parses a float (32-bit) from its string representation.
828    ///
829    /// # Errors
830    ///
831    /// Returns an error if the string cannot be parsed as a float.
832    pub fn parse_float(s: &str) -> Result<f32, String> {
833        s.parse::<f32>()
834            .map_err(|e| format!("Cannot convert {s} to float: {e}"))
835    }
836
837    /// Parses a signed byte (-128 to 127) from its string representation.
838    ///
839    /// # Errors
840    ///
841    /// Returns an error if the string cannot be parsed as an `i8`.
842    pub fn parse_byte(s: &str) -> Result<i8, String> {
843        s.parse::<i8>().map_err(|e| format!("Cannot convert {s} to byte: {e}"))
844    }
845
846    /// Parses a signed short (-32768 to 32767) from its string representation.
847    ///
848    /// # Errors
849    ///
850    /// Returns an error if the string cannot be parsed as an `i16`.
851    pub fn parse_short(s: &str) -> Result<i16, String> {
852        s.parse::<i16>()
853            .map_err(|e| format!("Cannot convert {s} to short: {e}"))
854    }
855
856    /// Parses a datetime string using XsdDateTime
857    pub fn parse_datetime(s: &str) -> Result<XsdDateTime, String> {
858        XsdDateTime::new(s).map_err(|e| e.to_string())
859    }
860}
861
862// ============================================================================
863// Trait Implementations
864// ============================================================================
865
866impl Default for ConcreteLiteral {
867    /// Returns an empty string literal without a language tag.
868    ///
869    /// This is used as a neutral default value when a literal is required
870    /// but no concrete value is available.
871    fn default() -> Self {
872        Self::StringLiteral {
873            lexical_form: String::default(),
874            lang: None,
875        }
876    }
877}
878
879/// Partial ordering for literals following SPARQL comparison semantics.
880///
881/// Comparison rules:
882/// - String literals are compared lexicographically by their lexical form.
883/// - Datatype literals are comparable **only if** they share the same datatype,
884///   and are then compared by lexical form.
885/// - Numeric literals are compared by numeric value.
886/// - Boolean literals follow `true > false`.
887/// - Datetime literals are compared chronologically.
888///
889/// If two literals are not comparable under these rules, `None` is returned.
890///
891/// See: <https://www.w3.org/TR/sparql11-query/#OperatorMapping>
892#[allow(clippy::non_canonical_partial_ord_impl)]
893impl PartialOrd for ConcreteLiteral {
894    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
895        match (self, other) {
896            // Chronological comparison for datetime literals
897            (Self::DatetimeLiteral(dt1), Self::DatetimeLiteral(dt2)) => dt1.partial_cmp(dt2),
898            // Lexicographic comparison for plain string literals
899            (Self::StringLiteral { lexical_form: lf1, .. }, Self::StringLiteral { lexical_form: lf2, .. }) => {
900                Some(lf1.cmp(lf2))
901            },
902            // Datatype literals are only comparable if their datatypes match
903            (
904                Self::DatatypeLiteral {
905                    lexical_form: lf1,
906                    datatype: dt1,
907                },
908                Self::DatatypeLiteral {
909                    lexical_form: lf2,
910                    datatype: dt2,
911                },
912            ) if dt1 == dt2 => Some(lf1.cmp(lf2)),
913            // Numeric comparison (may return None for NaN)
914            (Self::NumericLiteral(n1), Self::NumericLiteral(n2)) => n1.partial_cmp(n2),
915            // Boolean ordering: false < true
916            (Self::BooleanLiteral(b1), Self::BooleanLiteral(b2)) => Some(b1.cmp(b2)),
917            // Wrong-datatype literals can still be compared lexically if the expected datatype matches
918            (
919                Self::WrongDatatypeLiteral {
920                    lexical_form: lf1,
921                    datatype: dt1,
922                    ..
923                },
924                Self::DatatypeLiteral {
925                    lexical_form: lf2,
926                    datatype: dt2,
927                },
928            ) if dt1 == dt2 => Some(lf1.cmp(lf2)),
929            // All other combinations are considered incomparable
930            _ => None,
931        }
932    }
933}
934
935/// Total ordering for literals.
936///
937/// # Panics
938///
939/// This implementation **panics** if two literals are not comparable, such as:
940/// - Literals with different datatypes
941/// - Numeric literals involving `NaN`
942///
943/// This is intended as a temporary solution to support sorting in validation
944/// workflows where such cases are not expected.
945///
946/// # TODO
947///
948/// Define a total ordering that is well-defined for *all* literals.
949impl Ord for ConcreteLiteral {
950    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
951        self.partial_cmp(other)
952            .unwrap_or_else(|| panic!("Cannot compare literals {self} and {other}"))
953    }
954}
955
956impl Display for ConcreteLiteral {
957    /// Formats the literal using a basic prefix map for qualified display.
958    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
959        self.display_qualified(f, &PrefixMap::basic())
960    }
961}
962
963impl DerefIri for ConcreteLiteral {
964    /// Resolves IRIs and prefixes contained in the literal.
965    ///
966    /// - Value-based literals (`NumericLiteral`, `BooleanLiteral`, `DatetimeLiteral`, `StringLiteral`) are cloned directly.
967    /// - Datatype literals have their datatype IRIs dereferenced using `base` and `prefixmap`.
968    /// - Wrong datatype literals are converted into properly typed literals.
969    ///
970    /// # Errors
971    ///
972    /// Returns `DerefError` if datatype resolution fails.
973    fn deref_iri(self, base: Option<&IriS>, prefixmap: Option<&PrefixMap>) -> Result<Self, DerefError> {
974        match self {
975            Self::NumericLiteral(_) | Self::BooleanLiteral(_) | Self::DatetimeLiteral(_) => Ok(self.clone()),
976            Self::StringLiteral { .. } => Ok(self.clone()),
977
978            Self::DatatypeLiteral { lexical_form, datatype }
979            | Self::WrongDatatypeLiteral {
980                lexical_form, datatype, ..
981            } => {
982                let dt = datatype.deref_iri(base, prefixmap)?;
983                Ok(Self::DatatypeLiteral {
984                    lexical_form: lexical_form.clone(),
985                    datatype: dt,
986                })
987            },
988        }
989    }
990}
991
992// ============================================================================
993// Conversions
994// ============================================================================
995
996impl TryFrom<oxrdf::Literal> for ConcreteLiteral {
997    type Error = RDFError;
998
999    /// Attempts to convert an oxrdf literal into an `SLiteral`.
1000    ///
1001    /// Supported cases:
1002    /// - Plain string literals
1003    /// - Language-tagged string literals
1004    /// - Typed literals (with datatype parsing)
1005    ///
1006    /// # Errors
1007    ///
1008    /// Returns an `LiteralError` if:
1009    /// - The language tag is invalid
1010    /// - The datatype is unsupported or malformed
1011    /// - The literal structure is unknown
1012    fn try_from(value: oxrdf::Literal) -> Result<Self, Self::Error> {
1013        let literal_str = value.to_string();
1014
1015        let (lexical, datatype_opt, lang_opt, _) = value.destruct();
1016
1017        match (lexical, datatype_opt, lang_opt) {
1018            (s, None, None) => Ok(Self::str(&s)),
1019
1020            (s, None, Some(lang_tag)) => Lang::new(lang_tag.clone())
1021                .map(|lang| Self::lang_str(&s, lang))
1022                .map_err(|e| RDFError::LanguageTagError {
1023                    literal: literal_str,
1024                    language: lang_tag,
1025                    error: e.to_string(),
1026                }),
1027
1028            (s, Some(dtype), None) => {
1029                // Use safe IRI creation if possible
1030                let datatype_iri = IriRef::iri(IriS::new_unchecked(dtype.as_str()));
1031                check_literal_datatype(s.as_ref(), &datatype_iri)
1032            },
1033
1034            _ => Err(RDFError::ConversionError {
1035                msg: format!("Unknown literal structure: {literal_str}"),
1036            }),
1037        }
1038    }
1039}
1040
1041impl From<ConcreteLiteral> for oxrdf::Literal {
1042    /// Converts an `SLiteral` into an `oxrdf::Literal`
1043    fn from(value: ConcreteLiteral) -> Self {
1044        // Helper for datatype literals to reduce repetition
1045        fn typed_literal(lexical: String, datatype: &IriRef) -> oxrdf::Literal {
1046            datatype
1047                .get_iri()
1048                .map(|dt: &IriS| oxrdf::Literal::new_typed_literal(lexical.clone(), oxrdf::NamedNode::from(dt.clone())))
1049                .unwrap_or_else(|_| lexical.into())
1050        }
1051
1052        match value {
1053            ConcreteLiteral::StringLiteral { lexical_form, lang } => match lang {
1054                Some(l) => oxrdf::Literal::new_language_tagged_literal_unchecked(lexical_form, l.to_string()),
1055                None => lexical_form.into(),
1056            },
1057
1058            ConcreteLiteral::DatatypeLiteral { lexical_form, datatype }
1059            | ConcreteLiteral::WrongDatatypeLiteral {
1060                lexical_form, datatype, ..
1061            } => typed_literal(lexical_form, &datatype),
1062
1063            ConcreteLiteral::NumericLiteral(number) => number.into(),
1064            ConcreteLiteral::BooleanLiteral(b) => b.into(),
1065            ConcreteLiteral::DatetimeLiteral(dt) => (*dt.value()).into(),
1066        }
1067    }
1068}
1069
1070impl From<&ConcreteLiteral> for oxrdf::Literal {
1071    // Converts a reference to an `SLiteral` into an `oxrdf::Literal`
1072    fn from(value: &ConcreteLiteral) -> Self {
1073        oxrdf::Literal::from(value.clone())
1074    }
1075}
1076
1077// ============================================================================
1078// Helper Functions
1079// ============================================================================
1080
1081/// Serializes a boolean literal as a string ("true" or "false").
1082///
1083/// # Parameters
1084/// - `value`: A reference to the boolean value to serialize.
1085/// - `serializer`: The serializer to use (implements the `Serializer` trait).
1086fn serialize_boolean_literal<S>(value: &bool, serializer: S) -> result::Result<S::Ok, S::Error>
1087where
1088    S: Serializer,
1089{
1090    serializer.serialize_str(if *value { "true" } else { "false" })
1091}
1092
1093/// Validates a literal's lexical form against its declared datatype.
1094///
1095/// Returns a properly typed literal if validation succeeds, or a
1096/// `WrongDatatypeLiteral` if the lexical form doesn't match the datatype.
1097///
1098/// For unknown or custom datatypes, returns a `DatatypeLiteral` without validating.
1099///
1100/// # Arguments
1101///
1102/// * `lexical_form` - The string value of the literal
1103/// * `datatype` - The declared datatype as an owned `IriRef`
1104///
1105/// # Errors
1106///
1107/// Returns `RDFError` if the datatype IRI itself is invalid.
1108fn check_literal_datatype(lexical_form: &str, datatype: &IriRef) -> Result<ConcreteLiteral, RDFError> {
1109    // Resolve the IRI
1110    let iri = datatype.get_iri().map_err(|_| RDFError::IriRefError {
1111        iri_ref: datatype.to_string(),
1112    })?;
1113
1114    let iri_str = iri.as_str();
1115
1116    // Macro for constructors that return ConcreteLiteral directly
1117    macro_rules! check_xsd_type {
1118        ($xsd_const:expr, $parse_fn:expr, $construct_fn:expr) => {
1119            if iri_str == $xsd_const {
1120                return Ok(validate(lexical_form, datatype, $parse_fn, $construct_fn));
1121            }
1122        };
1123    }
1124
1125    // Macro for constructors that return Result<ConcreteLiteral, RDFError>
1126    macro_rules! check_xsd_type_result {
1127        ($xsd_const:expr, $parse_fn:expr, $construct_fn:expr) => {
1128            if iri_str == $xsd_const {
1129                return Ok(validate_with_result(
1130                    lexical_form,
1131                    datatype,
1132                    $parse_fn,
1133                    $construct_fn,
1134                ));
1135            }
1136        };
1137    }
1138
1139    // Check all XSD types using appropriate macro
1140    check_xsd_type!(
1141        XsdVocab::XSD_INTEGER,
1142        ConcreteLiteral::parse_integer,
1143        ConcreteLiteral::integer
1144    );
1145    check_xsd_type!(XsdVocab::XSD_LONG, ConcreteLiteral::parse_long, ConcreteLiteral::long);
1146    check_xsd_type!(
1147        XsdVocab::XSD_DOUBLE,
1148        ConcreteLiteral::parse_double,
1149        ConcreteLiteral::double
1150    );
1151    check_xsd_type!(
1152        XsdVocab::XSD_BOOLEAN,
1153        ConcreteLiteral::parse_bool,
1154        ConcreteLiteral::boolean
1155    );
1156    check_xsd_type!(
1157        XsdVocab::XSD_FLOAT,
1158        ConcreteLiteral::parse_float,
1159        ConcreteLiteral::float
1160    );
1161    check_xsd_type!(
1162        XsdVocab::XSD_DECIMAL,
1163        ConcreteLiteral::parse_decimal,
1164        ConcreteLiteral::decimal
1165    );
1166    check_xsd_type!(XsdVocab::XSD_BYTE, ConcreteLiteral::parse_byte, ConcreteLiteral::byte);
1167    check_xsd_type!(
1168        XsdVocab::XSD_SHORT,
1169        ConcreteLiteral::parse_short,
1170        ConcreteLiteral::short
1171    );
1172    check_xsd_type!(
1173        XsdVocab::XSD_UNSIGNED_INT,
1174        ConcreteLiteral::parse_unsigned_int,
1175        ConcreteLiteral::unsigned_int
1176    );
1177    check_xsd_type!(
1178        XsdVocab::XSD_UNSIGNED_LONG,
1179        ConcreteLiteral::parse_unsigned_long,
1180        ConcreteLiteral::unsigned_long
1181    );
1182    check_xsd_type!(
1183        XsdVocab::XSD_UNSIGNED_BYTE,
1184        ConcreteLiteral::parse_unsigned_byte,
1185        ConcreteLiteral::unsigned_byte
1186    );
1187    check_xsd_type!(
1188        XsdVocab::XSD_UNSIGNED_SHORT,
1189        ConcreteLiteral::parse_unsigned_short,
1190        ConcreteLiteral::unsigned_short
1191    );
1192    check_xsd_type!(
1193        XsdVocab::XSD_NON_NEGATIVE_INTEGER,
1194        ConcreteLiteral::parse_non_negative_integer,
1195        ConcreteLiteral::non_negative_integer
1196    );
1197
1198    // These constructors return Result and need special handling
1199    check_xsd_type_result!(
1200        XsdVocab::XSD_NEGATIVE_INTEGER,
1201        ConcreteLiteral::parse_negative_integer,
1202        ConcreteLiteral::negative_integer
1203    );
1204    check_xsd_type_result!(
1205        XsdVocab::XSD_POSITIVE_INTEGER,
1206        ConcreteLiteral::parse_positive_integer,
1207        ConcreteLiteral::positive_integer
1208    );
1209    check_xsd_type_result!(
1210        XsdVocab::XSD_NON_POSITIVE_INTEGER,
1211        ConcreteLiteral::parse_non_positive_integer,
1212        ConcreteLiteral::non_positive_integer
1213    );
1214    check_xsd_type!(
1215        XsdVocab::XSD_DATE_TIME,
1216        ConcreteLiteral::parse_datetime,
1217        ConcreteLiteral::datetime
1218    );
1219
1220    // Unknown or custom datatype: do not validate lexical form
1221    Ok(ConcreteLiteral::DatatypeLiteral {
1222        lexical_form: lexical_form.to_string(),
1223        datatype: datatype.clone(),
1224    })
1225}
1226
1227/// Validates a lexical form against a specified datatype using a parser and constructor.
1228///
1229/// # Parameters
1230/// - `lexical_form`: The literal value as a string that needs to be validated.
1231/// - `datatype`: The IRI of the expected datatype.
1232/// - `parser`: A function that attempts to parse the `lexical_form` into a value of type `T`.
1233/// - `constructor`: A function that constructs a `ConcreteLiteral` from a successfully parsed value.
1234fn validate<T, P, C>(lexical_form: &str, datatype: &IriRef, parser: P, constructor: C) -> ConcreteLiteral
1235where
1236    P: Fn(&str) -> Result<T, String>,
1237    C: Fn(T) -> ConcreteLiteral,
1238{
1239    match parser(lexical_form) {
1240        Ok(value) => constructor(value),
1241        Err(err) => ConcreteLiteral::WrongDatatypeLiteral {
1242            lexical_form: lexical_form.to_string(),
1243            datatype: datatype.clone(),
1244            error: err.to_string(),
1245        },
1246    }
1247}
1248
1249/// Validates a lexical form with a constructor that returns `Result`.
1250///
1251/// This variant handles constructors that perform additional validation
1252/// (e.g., range checks for positiveInteger, negativeInteger).
1253///
1254/// # Parameters
1255/// - `lexical_form`: The literal value as a string that needs to be validated.
1256/// - `datatype`: The IRI of the expected datatype.
1257/// - `parser`: A function that attempts to parse the `lexical_form` into a value of type `T`.
1258/// - `constructor`: A function that constructs a `ConcreteLiteral` from a parsed value, returning `Result`.
1259fn validate_with_result<T, P, C>(lexical_form: &str, datatype: &IriRef, parser: P, constructor: C) -> ConcreteLiteral
1260where
1261    P: Fn(&str) -> Result<T, String>,
1262    C: Fn(T) -> Result<ConcreteLiteral, RDFError>,
1263{
1264    match parser(lexical_form) {
1265        Ok(value) => match constructor(value) {
1266            Ok(literal) => literal,
1267            Err(err) => ConcreteLiteral::WrongDatatypeLiteral {
1268                lexical_form: lexical_form.to_string(),
1269                datatype: datatype.clone(),
1270                error: err.to_string(),
1271            },
1272        },
1273        Err(err) => ConcreteLiteral::WrongDatatypeLiteral {
1274            lexical_form: lexical_form.to_string(),
1275            datatype: datatype.clone(),
1276            error: err.to_string(),
1277        },
1278    }
1279}