1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
use constants;
use graph::*;
use std::fmt::Display;
use std::io::{Result, Write};
use std::marker::PhantomData;
struct NTriplesWriter<'a, 'g, W: 'a, G: 'g>
where
W: Write,
G: Graph<'g>,
{
buffer: Vec<u8>,
writer: &'a mut W,
xsd_string: Option<<<G as Graph<'g>>::LiteralPtr as LiteralPtr<'g>>::DatatypePtr>,
phantom: PhantomData<&'g u8>,
}
pub fn write_ntriples<'g, G: 'g, T: 'g, I, W>(
triples: I,
graph: &'g G,
writer: &mut W,
) -> Result<()>
where
T: Triple<'g, G::BlankNodePtr, G::IRIPtr, G::LiteralPtr>,
G: Graph<'g>,
<G as Graph<'g>>::BlankNodePtr: Display,
I: Iterator<Item = T>,
W: Write,
{
let mut writer = NTriplesWriter::<_, G> {
buffer: Vec::new(),
writer,
xsd_string: graph.find_datatype(constants::XSD_STRING),
phantom: PhantomData,
};
for triple in triples {
writer.write_ntriple(&triple)?;
}
Ok(())
}
impl<'a, 'g, W: 'a, G: 'g> NTriplesWriter<'a, 'g, W, G>
where
W: Write,
G: Graph<'g>,
<G as Graph<'g>>::BlankNodePtr: Display,
{
fn write_iri(&mut self, iri: &str) -> Result<()> {
self.writer.write_all(b"<")?;
self.buffer.clear();
for b in iri.as_bytes() {
if *b < 20 || b"<>\"{}|^`\\".contains(b) {
write!(&mut self.buffer, "\\u00{:X} ", *b).unwrap();
} else {
self.buffer.push(*b);
}
}
self.writer.write_all(&self.buffer[..])?;
self.writer.write_all(b">")
}
fn write_blank_node(&mut self, blank_node: G::BlankNodePtr) -> Result<()> {
self.writer.write_all(b"_:")?;
write!(self.writer, "{}", blank_node)?;
Ok(())
}
fn write_literal_value(&mut self, value: &str) -> Result<()> {
self.buffer.clear();
for b in value.as_bytes() {
if *b == 0x22 || *b == 0x5C || *b == 0x0A || *b == 0x0D {
self.buffer.push(b'\\');
}
self.buffer.push(*b);
}
self.writer.write_all(&self.buffer[..])
}
fn write_literal(&mut self, literal: &G::LiteralPtr) -> Result<()> {
self.writer.write_all(b"\"")?;
self.write_literal_value(literal.as_str())?;
self.writer.write_all(b"\"")?;
if let Some(langtag) = literal.language() {
self.writer.write_all(b"@")?;
self.writer.write_all(langtag.as_bytes())?;
} else if Some(literal.datatype()) != self.xsd_string {
self.writer.write_all(b"^^")?;
self.write_iri(literal.datatype_str())?;
}
Ok(())
}
fn write_subject(
&mut self,
subject: BlankNodeOrIRI<'g, G::BlankNodePtr, G::IRIPtr>,
) -> Result<()> {
match subject {
BlankNodeOrIRI::BlankNode(blank_node, _) => self.write_blank_node(blank_node),
BlankNodeOrIRI::IRI(iri) => self.write_iri(iri.as_str()),
}
}
fn write_predicate(&mut self, predicate: &str) -> Result<()> {
self.write_iri(predicate)
}
fn write_object(
&mut self,
object: Resource<'g, G::BlankNodePtr, G::IRIPtr, G::LiteralPtr>,
) -> Result<()> {
match object {
Resource::BlankNode(blank_node, _) => self.write_blank_node(blank_node),
Resource::IRI(iri) => self.write_iri(iri.as_str()),
Resource::Literal(literal) => self.write_literal(&literal),
}
}
fn write_ntriple<T: 'g>(&mut self, triple: &T) -> Result<()>
where
T: Triple<'g, G::BlankNodePtr, G::IRIPtr, G::LiteralPtr>,
{
self.write_subject(triple.subject())?;
self.writer.write_all(b" ")?;
self.write_predicate(triple.predicate().as_str())?;
self.writer.write_all(b" ")?;
self.write_object(triple.object())?;
self.writer.write_all(b" .\n")
}
}