Skip to main content

qualia_core_db/sparql_library/serialisers/
rdf_dispatch.rs

1//! Unified zero-heap RDF / RDF-Star serialization dispatch.
2
3use crate::rdf_star::RdfStarSerializer;
4use crate::resolver;
5use crate::sparql_library::parsers::turtle_star::{
6    JsonLdStarSerializer, N3StarSerializer, NQuadsStarSerializer, TrigStarSerializer,
7    TurtleStarSerializer,
8};
9use crate::sparql_library::rdf_formats::{RdfFormat, RdfStarMode};
10use crate::NQuin;
11use std::io::Write;
12
13#[derive(Debug, Clone, PartialEq, Eq)]
14pub enum RdfDispatchError {
15    Unsupported,
16    Io(String),
17}
18
19pub fn serialize_quins<W: Write>(
20    format: RdfFormat,
21    mode: RdfStarMode,
22    quins: &[NQuin],
23    out: &mut W,
24) -> Result<(), RdfDispatchError> {
25    match mode {
26        RdfStarMode::Plain => serialize_plain(format, quins, out),
27        RdfStarMode::Star => serialize_star(format, quins, out),
28    }
29}
30
31fn serialize_plain<W: Write>(
32    format: RdfFormat,
33    quins: &[NQuin],
34    out: &mut W,
35) -> Result<(), RdfDispatchError> {
36    use crate::sparql_library::serialisers::rdf_serializers as ser;
37    // Each format routes to its own serializer. Previously Turtle/N3/JSON-LD/
38    // CBOR-LD all silently emitted N-Triples — a format lie (asking for JSON-LD
39    // yielded N-Triples text). N-Triples/N-Quads keep the zero-heap resolver
40    // fast path; the grouped/structured formats use their real serializers.
41    match format {
42        RdfFormat::NTriples => resolver::format_ntriples_to(quins, out)
43            .map_err(|e| RdfDispatchError::Io(e.to_string())),
44        RdfFormat::NQuads => {
45            resolver::format_nquads_to(quins, out).map_err(|e| RdfDispatchError::Io(e.to_string()))
46        }
47        RdfFormat::Turtle => ser::serialize_to_turtle(out, quins).map_err(RdfDispatchError::Io),
48        RdfFormat::TriG => ser::serialize_to_trig(out, quins).map_err(RdfDispatchError::Io),
49        RdfFormat::N3 => ser::serialize_to_n3(out, quins).map_err(RdfDispatchError::Io),
50        RdfFormat::JsonLd => ser::serialize_to_jsonld(out, quins).map_err(RdfDispatchError::Io),
51        RdfFormat::CborLd => ser::serialize_to_cborld(out, quins).map_err(RdfDispatchError::Io),
52    }
53}
54
55fn serialize_star<W: Write>(
56    format: RdfFormat,
57    quins: &[NQuin],
58    out: &mut W,
59) -> Result<(), RdfDispatchError> {
60    match format {
61        RdfFormat::NTriples => resolver::format_ntriples_star_to(quins, out)
62            .map_err(|e| RdfDispatchError::Io(e.to_string())),
63        RdfFormat::NQuads => {
64            for q in quins {
65                let ser = NQuadsStarSerializer::new();
66                let bytes = if q.context != 0 {
67                    ser.serialize_quad(q.subject, q.predicate, q.object, q.context)
68                } else {
69                    ser.serialize_triple(q.subject, q.predicate, q.object)
70                }
71                .map_err(|e| RdfDispatchError::Io(format!("{e:?}")))?;
72                out.write_all(&bytes)
73                    .map_err(|e| RdfDispatchError::Io(e.to_string()))?;
74                out.write_all(b"\n")
75                    .map_err(|e| RdfDispatchError::Io(e.to_string()))?;
76            }
77            Ok(())
78        }
79        RdfFormat::Turtle => write_with_serializer(quins, out, &TurtleStarSerializer::new()),
80        RdfFormat::TriG => {
81            let ser = TrigStarSerializer::new();
82            write_with_serializer(quins, out, &ser)
83        }
84        RdfFormat::N3 => {
85            let ser = N3StarSerializer::new();
86            write_with_serializer(quins, out, &ser)
87        }
88        RdfFormat::JsonLd => {
89            let ser = JsonLdStarSerializer::new();
90            write_with_serializer(quins, out, &ser)
91        }
92        RdfFormat::CborLd => Err(RdfDispatchError::Unsupported),
93    }
94}
95
96fn write_with_serializer<W: Write, S: RdfStarSerializer>(
97    quins: &[NQuin],
98    out: &mut W,
99    ser: &S,
100) -> Result<(), RdfDispatchError> {
101    for q in quins {
102        let bytes = if q.context != 0 && ser.supports_quads() {
103            ser.serialize_quad(q.subject, q.predicate, q.object, q.context)
104        } else {
105            ser.serialize_triple(q.subject, q.predicate, q.object)
106        }
107        .map_err(|e| RdfDispatchError::Io(format!("{e:?}")))?;
108        out.write_all(&bytes)
109            .map_err(|e| RdfDispatchError::Io(e.to_string()))?;
110        out.write_all(b"\n")
111            .map_err(|e| RdfDispatchError::Io(e.to_string()))?;
112    }
113    Ok(())
114}