oxihuman_export/
turtle_export.rs1#![allow(dead_code)]
4
5#[allow(dead_code)]
9#[derive(Debug, Clone)]
10pub struct RdfTriple {
11 pub subject: String,
12 pub predicate: String,
13 pub object: String,
14}
15
16#[allow(dead_code)]
18#[derive(Debug, Clone, Default)]
19pub struct TurtleDoc {
20 pub prefixes: Vec<(String, String)>,
21 pub triples: Vec<RdfTriple>,
22}
23
24impl TurtleDoc {
25 #[allow(dead_code)]
26 pub fn new() -> Self {
27 TurtleDoc::default()
28 }
29
30 #[allow(dead_code)]
31 pub fn add_prefix(&mut self, prefix: &str, iri: &str) {
32 self.prefixes.push((prefix.to_string(), iri.to_string()));
33 }
34
35 #[allow(dead_code)]
36 pub fn add_triple(&mut self, s: &str, p: &str, o: &str) {
37 self.triples.push(RdfTriple {
38 subject: s.to_string(),
39 predicate: p.to_string(),
40 object: o.to_string(),
41 });
42 }
43}
44
45#[allow(dead_code)]
47pub fn export_turtle(doc: &TurtleDoc) -> String {
48 let mut out = String::new();
49 for (prefix, iri) in &doc.prefixes {
50 out.push_str(&format!("@prefix {}: <{}> .\n", prefix, iri));
51 }
52 if !doc.prefixes.is_empty() && !doc.triples.is_empty() {
53 out.push('\n');
54 }
55 for t in &doc.triples {
56 out.push_str(&format!("{} {} {} .\n", t.subject, t.predicate, t.object));
57 }
58 out
59}
60
61#[allow(dead_code)]
63pub fn triple_count(doc: &TurtleDoc) -> usize {
64 doc.triples.len()
65}
66
67#[allow(dead_code)]
69pub fn prefix_count(doc: &TurtleDoc) -> usize {
70 doc.prefixes.len()
71}
72
73#[allow(dead_code)]
75pub fn contains_triple(doc: &TurtleDoc, s: &str, p: &str) -> bool {
76 doc.triples
77 .iter()
78 .any(|t| t.subject == s && t.predicate == p)
79}
80
81#[cfg(test)]
82mod tests {
83 use super::*;
84
85 #[test]
86 fn new_doc_empty() {
87 let doc = TurtleDoc::new();
88 assert_eq!(triple_count(&doc), 0);
89 }
90
91 #[test]
92 fn add_triple_count() {
93 let mut doc = TurtleDoc::new();
94 doc.add_triple("<http://a>", "<http://b>", "<http://c>");
95 assert_eq!(triple_count(&doc), 1);
96 }
97
98 #[test]
99 fn add_prefix_count() {
100 let mut doc = TurtleDoc::new();
101 doc.add_prefix("schema", "http://schema.org/");
102 assert_eq!(prefix_count(&doc), 1);
103 }
104
105 #[test]
106 fn export_contains_prefix() {
107 let mut doc = TurtleDoc::new();
108 doc.add_prefix("rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#");
109 let s = export_turtle(&doc);
110 assert!(s.contains("@prefix rdf:"));
111 }
112
113 #[test]
114 fn export_contains_triple() {
115 let mut doc = TurtleDoc::new();
116 doc.add_triple("<http://a>", "<http://b>", "<http://c>");
117 let s = export_turtle(&doc);
118 assert!(s.contains("<http://a>"));
119 }
120
121 #[test]
122 fn triple_ends_with_dot() {
123 let mut doc = TurtleDoc::new();
124 doc.add_triple("<http://a>", "<http://b>", "\"value\"");
125 let s = export_turtle(&doc);
126 assert!(s.contains(" ."));
127 }
128
129 #[test]
130 fn contains_triple_helper() {
131 let mut doc = TurtleDoc::new();
132 doc.add_triple("<http://a>", "rdf:type", "<http://Person>");
133 assert!(contains_triple(&doc, "<http://a>", "rdf:type"));
134 }
135
136 #[test]
137 fn not_contains_nonexistent_triple() {
138 let doc = TurtleDoc::new();
139 assert!(!contains_triple(&doc, "<http://x>", "rdf:type"));
140 }
141
142 #[test]
143 fn empty_doc_empty_string() {
144 let doc = TurtleDoc::new();
145 assert!(export_turtle(&doc).is_empty());
146 }
147
148 #[test]
149 fn multiple_triples() {
150 let mut doc = TurtleDoc::new();
151 doc.add_triple("a", "b", "c");
152 doc.add_triple("d", "e", "f");
153 let s = export_turtle(&doc);
154 assert!(s.contains("a b c ."));
155 assert!(s.contains("d e f ."));
156 }
157}