Skip to main content

rudof_rdf/rdf_core/
rdf_format.rs

1use crate::rdf_core::RDFError;
2use iri_s::MimeType;
3use serde::{Deserialize, Serialize};
4use std::fmt::Display;
5use std::str::FromStr;
6
7/// Represents RDF serialization formats
8#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Default, Serialize, Deserialize)]
9pub enum RDFFormat {
10    /// Turtle (Terse RDF Triple Language) format.
11    #[default]
12    Turtle,
13    /// N-Triples format.
14    NTriples,
15    Rdfxml,
16    TriG,
17    /// N3 (Notation3) format.
18    N3,
19    /// N-Quads format.
20    NQuads,
21    /// JSON-LD (JSON for Linking Data) format.
22    JsonLd,
23}
24
25impl RDFFormat {
26    /// Returns the file extensions associated with this format.
27    ///
28    /// # Extensions by Format
29    ///
30    /// - **Turtle**: `["ttl", "turtle"]`
31    /// - **N-Triples**: `["nt"]`
32    /// - **RDF/XML**: `["rdf", "xml"]`
33    /// - **TriG**: `["trig"]`
34    /// - **N3**: `["n3"]`
35    /// - **NQuads**: `["nq", "nquads"]`
36    /// - **JSON-LD**: `["jsonld", "json-ld", "json"]`
37    pub fn extensions(&self) -> Vec<&'static str> {
38        match self {
39            RDFFormat::Turtle => vec!["ttl", "turtle"],
40            RDFFormat::NTriples => vec!["nt"],
41            RDFFormat::Rdfxml => vec!["rdf", "xml"],
42            RDFFormat::TriG => vec!["trig"],
43            RDFFormat::N3 => vec!["n3"],
44            RDFFormat::NQuads => vec!["nq", "nquads"],
45            RDFFormat::JsonLd => vec!["jsonld", "json-ld", "json"],
46        }
47    }
48}
49
50impl MimeType for RDFFormat {
51    /// Returns the IANA-registered MIME type for this RDF format.
52    ///
53    /// # MIME Types by Format
54    ///
55    /// - **Turtle**: `text/turtle`
56    /// - **N-Triples**: `application/n-triples`
57    /// - **RDF/XML**: `application/rdf+xml`
58    /// - **TriG**: `application/trig`
59    /// - **N3**: `text/n3`
60    /// - **NQuads**: `application/n-quads`
61    /// - **JSON-LD**: `application/ld+json`
62    fn mime_type(&self) -> &'static str {
63        match self {
64            RDFFormat::Turtle => "text/turtle",
65            RDFFormat::NTriples => "application/n-triples",
66            RDFFormat::Rdfxml => "application/rdf+xml",
67            RDFFormat::TriG => "application/trig",
68            RDFFormat::N3 => "text/n3",
69            RDFFormat::NQuads => "application/n-quads",
70            RDFFormat::JsonLd => "application/ld+json",
71        }
72    }
73}
74
75impl FromStr for RDFFormat {
76    /// Error type returned when parsing fails.
77    type Err = RDFError;
78
79    /// Parses a string into an RDF format.
80    ///
81    /// This implementation is case-insensitive and accepts multiple variations
82    /// for each format, including format names and common abbreviations.
83    ///
84    /// # Accepted Strings (case-insensitive)
85    ///
86    /// - **Turtle**: "ttl", "turtle"
87    /// - **N-Triples**: "ntriples", "nt"
88    /// - **RDF/XML**: "rdf/xml", "rdf"
89    /// - **TriG**: "trig"
90    /// - **N3**: "n3"
91    /// - **NQuads**: "nquads", "nq"
92    /// - **JSON-LD**: "jsonld", "json"
93    ///
94    /// # Arguments
95    ///
96    /// * `s` - The string to parse (case-insensitive)
97    ///
98    /// # Errors
99    ///
100    /// Returns [`RDFError::NotSupportedRDFFormatError`] if the input string doesn't match any known format.
101    fn from_str(s: &str) -> Result<RDFFormat, RDFError> {
102        match s.to_lowercase().as_str() {
103            "ttl" => Ok(RDFFormat::Turtle),
104            "turtle" => Ok(RDFFormat::Turtle),
105            "ntriples" => Ok(RDFFormat::NTriples),
106            "nt" => Ok(RDFFormat::NTriples),
107            "rdf/xml" => Ok(RDFFormat::Rdfxml),
108            "rdf" => Ok(RDFFormat::Rdfxml),
109            "trig" => Ok(RDFFormat::TriG),
110            "n3" => Ok(RDFFormat::N3),
111            "nquads" => Ok(RDFFormat::NQuads),
112            "nq" => Ok(RDFFormat::NQuads),
113            "jsonld" => Ok(RDFFormat::JsonLd),
114            "json" => Ok(RDFFormat::JsonLd),
115            _ => Err(RDFError::NotSupportedRDFFormatError {
116                format: format!("Format {s} not supported").to_string(),
117            }),
118        }
119    }
120}
121
122impl Display for RDFFormat {
123    /// Formats the RDF format as its canonical name.
124    ///
125    /// # Format Names
126    ///
127    /// - Turtle → "Turtle"
128    /// - N-Triples → "N-Triples"
129    /// - RDF/XML → "RDF/XML"
130    /// - TriG → "TriG"
131    /// - N3 → "N3"
132    /// - NQuads → "NQuads"
133    /// - JSON-LD → "JSONLD"
134    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
135        match self {
136            RDFFormat::Turtle => write!(f, "Turtle"),
137            RDFFormat::NTriples => write!(f, "N-Triples"),
138            RDFFormat::Rdfxml => write!(f, "RDF/XML"),
139            RDFFormat::TriG => write!(f, "TriG"),
140            RDFFormat::N3 => write!(f, "N3"),
141            RDFFormat::NQuads => write!(f, "NQuads"),
142            RDFFormat::JsonLd => write!(f, "JSONLD"),
143        }
144    }
145}