rdf_dynsyn/serializer/
mod.rs1use std::io::{self, Write};
5
6use gdp_rs::predicate::impl_::all_of::IntoPL;
7use sophia_api::{
8    quad::Quad,
9    serializer::{QuadSerializer, TripleSerializer},
10    source::{QuadSource, StreamResult},
11};
12
13use self::{quads::DynSynQuadSerializerFactory, triples::DynSynTripleSerializerFactory};
14use crate::syntax::{
15    invariant::serializable::DynSynSerializableSyntax,
16    predicate::{IsDatasetEncoding, IsGraphEncoding},
17};
18
19pub mod quads;
20pub mod triples;
21
22#[derive(Debug, Clone, Default)]
24pub struct DynSynSerializerFactorySet {
25    pub quads_serializing: DynSynQuadSerializerFactory,
27
28    pub triples_serializing: DynSynTripleSerializerFactory,
30}
31
32impl DynSynSerializerFactorySet {
33    pub fn wrapping_serialize_quads<QS, W>(
39        &self,
40        quads: QS,
41        write: W,
42        syntax: DynSynSerializableSyntax,
43    ) -> StreamResult<(), QS::Error, io::Error>
44    where
45        QS: QuadSource,
46        W: Write,
47    {
48        let syntax = syntax.infer::<IntoPL<_, _>>(Default::default());
49
50        if let Ok(qs_syntax) = syntax.try_extend_predicate::<IsDatasetEncoding>() {
52            self.quads_serializing
53                .new_serializer(qs_syntax, write)
54                .serialize_quads(quads)?;
55            Ok(())
56        }
57        else if let Ok(ts_syntax) = syntax.try_extend_predicate::<IsGraphEncoding>() {
59            self.triples_serializing
60                .new_serializer(ts_syntax, write)
61                .serialize_triples(quads.filter_quads(|q| q.g().is_none()).to_triples())?;
62            Ok(())
63        } else {
64            unreachable!()
66        }
67    }
68}
69
70#[cfg(feature = "async")]
71mod async_ {
72    use std::io;
73
74    use futures::AsyncWrite;
75    use gdp_rs::predicate::impl_::all_of::IntoPL;
76    use sophia_api::{dataset::Dataset, source::StreamResult};
77
78    use super::DynSynSerializerFactorySet;
79    use crate::syntax::{
80        invariant::serializable::DynSynSerializableSyntax,
81        predicate::{IsDatasetEncoding, IsGraphEncoding},
82    };
83
84    impl DynSynSerializerFactorySet {
85        pub async fn wrapping_serialize_dataset_async<D, W>(
89            &self,
90            dataset: D,
91            write: W,
92            syntax: DynSynSerializableSyntax,
93        ) -> StreamResult<(), D::Error, io::Error>
94        where
95            D: Dataset + Send + Sync + 'static + Unpin,
96            D::Error: Send + Sync + 'static,
97            W: Send + 'static + AsyncWrite + Unpin,
98        {
99            let syntax = syntax.infer::<IntoPL<_, _>>(Default::default());
101
102            if let Ok(qs_syntax) = syntax.try_extend_predicate::<IsDatasetEncoding>() {
104                self.quads_serializing
105                    .new_async_serializer(qs_syntax, write)
106                    .serialize_dataset(dataset)
107                    .await?;
108                Ok(())
109            }
110            else if let Ok(ts_syntax) = syntax.try_extend_predicate::<IsGraphEncoding>() {
112                self.triples_serializing
113                    .new_async_serializer(ts_syntax, write)
114                    .wrapping_serialize_dataset(dataset)
115                    .await?;
116                Ok(())
117            } else {
118                unreachable!()
120            }
121        }
122    }
123}
124
125#[cfg(test)]
126mod test_data {
127    pub static TESTS_NQUADS: &[&str] = &[
131        r#"<http://champin.net/#pa> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://schema.org/Person>.
132<http://champin.net/#pa> <http://schema.org/name> "Pierre-Antoine" <http://champin.net/>.
133"#,
134    ];
135
136    pub static TESTS_NTRIPLES: &[&str] = &[
137        r#"<http://champin.net/#pa> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://schema.org/Person>.
138<http://champin.net/#pa> <http://schema.org/name> "Pierre-Antoine".
139"#,
140    ];
141
142    pub static TESTS_RDF_XML: &[&str] = &[r#"<?xml version="1.0" encoding="utf-8"?>
143    <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
144                xmlns="http://example.org/ns/">
145        <rdf:Description rdf:about="http://localhost/ex#me">
146        <knows>
147            <Person>
148            <name>Alice</name>
149            </Person>
150        </knows>
151        </rdf:Description>
152    </rdf:RDF>
153    "#];
154
155    pub static TESTS_TRIG: &[&str] = &[
156        "#empty trig",
157        r#"# simple quads
158            PREFIX : <http://example.org/ns/>
159            :alice a :Person; :name "Alice"; :age 42.
160            GRAPH :g {
161                :bob a :Person, :Man; :nick "bob"@fr, "bobby"@en; :admin true.
162            }
163        "#,
164        r#"# lists
165            GRAPH <tag:g> { <tag:alice> <tag:likes> ( 1 2 ( 3 4 ) 5 6 ), ("a" "b"). }
166        "#,
167        r#"# subject lists
168            GRAPH <tag:g> { (1 2 3) a <tag:List>. }
169        "#,
170        r#"# blank node graph name
171            PREFIX : <http://example.org/ns/>
172            #:lois :belives _:b.
173            #GRAPH _:b1 { :clark a :Human }
174        "#,
175        r#"# list split over different graphs
176            PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
177            _:a rdf:first 42; rdf:rest _:b.
178            GRAPH [] {
179                _:b rdf:first 43; rdf:rest ().
180            }
181        "#,
182    ];
183
184    pub static TESTS_TURTLE: &[&str] = &[
185        "#empty ttl",
186        r#"# simple triple
187            PREFIX : <http://example.org/ns/>
188            :alice a :Person; :name "Alice"; :age 42.
189            :bob a :Person, :Man; :nick "bob"@fr, "bobby"@en; :admin true.
190        "#,
191        r#"# lists
192            <tag:alice> <tag:likes> ( 1 2 ( 3 4 ) 5 6 ), ("a" "b").
193        "#,
194        r#"# subject lists
195            (1 2 3) a <tag:List>.
196        "#,
197        r#"# malformed list
198            PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
199            _:a rdf:first 42, 43; rdf:rest (44 45).
200            _:b rdf:first 42; rdf:rest (43), (44).
201        "#,
202        r#"# bnode cycles
203        PREFIX : <http://example.org/ns/>
204        _:a :n "a"; :p [ :q [ :r _:a ]].
205        _:b :n "b"; :s [ :s _:b ].
206        "#,
207    ];
208}