1use std::fmt;
2
3use langtag::{LangTag, LangTagBuf};
4use rdf_types::{
5 BTreeDataset, BTreeGraph, IndexedBTreeDataset, IndexedBTreeGraph,
6 diff::{ColoredRdfDiff, RdfDiff},
7};
8
9pub trait RdfDisplay {
11 fn rdf_fmt(&self, f: &mut fmt::Formatter) -> fmt::Result;
13
14 #[inline(always)]
16 fn rdf_display(&self) -> RdfDisplayed<&Self> {
17 RdfDisplayed(self)
18 }
19}
20
21impl RdfDisplay for str {
22 fn rdf_fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
23 use fmt::Display;
24 write!(f, "\"")?;
25
26 for c in self.chars() {
27 match c {
28 '\u{8}' => write!(f, "\\b"), '\t' => write!(f, "\\t"),
32 '\n' => write!(f, "\\n"),
33 '\u{c}' => write!(f, "\\f"), '\r' => write!(f, "\\r"),
35 '"' => write!(f, "\\\""),
36 '\\' => write!(f, "\\\\"),
37 '\u{0}'..='\u{7}'
40 | '\u{b}' | '\u{e}'..='\u{1f}'
42 | '\u{7f}' | '\u{fffe}'
44 | '\u{ffff}' => write!(f, "\\u{:04X}", c as u32),
45 c => c.fmt(f),
46 }?
47 }
48
49 write!(f, "\"")
50 }
51}
52
53impl RdfDisplay for String {
54 fn rdf_fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
55 self.as_str().rdf_fmt(f)
56 }
57}
58
59impl RdfDisplay for iref::IriRef {
60 fn rdf_fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
61 write!(f, "<")?;
62
63 for c in self.as_str().chars() {
64 match c {
65 '\x00'..='\x20' | '<' | '>' | '"' | '{' | '}' | '|' | '^' | '`' | '\\' => {
66 write!(f, "\\u{:04X}", c as u32)
67 }
68 _ => fmt::Display::fmt(&c, f),
69 }?;
70 }
71
72 write!(f, ">")
73 }
74}
75
76impl RdfDisplay for iref::Iri {
77 #[inline(always)]
78 fn rdf_fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
79 self.as_iri_ref().rdf_fmt(f)
80 }
81}
82
83impl RdfDisplay for iref::IriBuf {
84 #[inline(always)]
85 fn rdf_fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
86 self.as_iri_ref().rdf_fmt(f)
87 }
88}
89
90impl RdfDisplay for iref::IriRefBuf {
91 #[inline(always)]
92 fn rdf_fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
93 self.as_iri_ref().rdf_fmt(f)
94 }
95}
96
97impl RdfDisplay for LangTag {
98 fn rdf_fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
99 use fmt::Display;
100 self.as_str().fmt(f)
101 }
102}
103
104impl RdfDisplay for LangTagBuf {
105 fn rdf_fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
106 use fmt::Display;
107 self.as_str().fmt(f)
108 }
109}
110
111impl<T: RdfDisplay + ?Sized> RdfDisplay for &T {
112 #[inline(always)]
113 fn rdf_fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
114 T::rdf_fmt(*self, f)
115 }
116}
117
118pub struct RdfDisplayed<T>(T);
120
121impl<T: RdfDisplay> fmt::Display for RdfDisplayed<T> {
122 #[inline(always)]
123 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
124 self.0.rdf_fmt(f)
125 }
126}
127
128impl<R: RdfDisplay> RdfDisplay for BTreeGraph<R> {
129 fn rdf_fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
130 for t in self {
131 writeln!(f, "{} .", t.rdf_display())?;
132 }
133
134 Ok(())
135 }
136}
137
138impl<R: RdfDisplay> RdfDisplay for IndexedBTreeGraph<R> {
139 fn rdf_fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
140 for t in self {
141 writeln!(f, "{} .", t.rdf_display())?;
142 }
143
144 Ok(())
145 }
146}
147
148impl<R: RdfDisplay> RdfDisplay for BTreeDataset<R> {
149 fn rdf_fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
150 for t in self {
151 writeln!(f, "{} .", t.rdf_display())?;
152 }
153
154 Ok(())
155 }
156}
157
158impl<R: RdfDisplay> RdfDisplay for IndexedBTreeDataset<R> {
159 fn rdf_fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
160 for t in self {
161 writeln!(f, "{} .", t.rdf_display())?;
162 }
163
164 Ok(())
165 }
166}
167
168impl<R: RdfDisplay> RdfDisplay for RdfDiff<R> {
169 fn rdf_fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
170 for quad in &self.added {
171 writeln!(f, "+ {} .", quad.rdf_display())?;
172 }
173
174 for quad in &self.removed {
175 writeln!(f, "- {} .", quad.rdf_display())?;
176 }
177
178 Ok(())
179 }
180}
181
182impl<'a, R: RdfDisplay> RdfDisplay for ColoredRdfDiff<'a, R> {
183 fn rdf_fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
184 for quad in &self.0.added {
185 writeln!(f, "\x1b[32m+ {} .\x1b[0m", quad.rdf_display())?;
186 }
187
188 for quad in &self.0.removed {
189 writeln!(f, "\x1b[31m- {} .\x1b[0m", quad.rdf_display())?;
190 }
191
192 Ok(())
193 }
194}