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 '"' => write!(f, "\\\""),
29 '\\' => write!(f, "\\\\"),
30 '\n' => write!(f, "\\n"),
31 '\r' => write!(f, "\\r"),
32 c => c.fmt(f),
33 }?
34 }
35
36 write!(f, "\"")
37 }
38}
39
40impl RdfDisplay for String {
41 fn rdf_fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
42 self.as_str().rdf_fmt(f)
43 }
44}
45
46impl RdfDisplay for iref::IriRef {
47 fn rdf_fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
48 write!(f, "<")?;
49
50 for c in self.as_str().chars() {
51 match c {
52 '\x00'..='\x20' | '<' | '>' | '"' | '{' | '}' | '|' | '^' | '`' | '\\' => {
53 let bytes: u32 = c.into();
54 write!(f, "\\u{bytes:#04x}")
55 }
56 _ => fmt::Display::fmt(&c, f),
57 }?;
58 }
59
60 write!(f, ">")
61 }
62}
63
64impl RdfDisplay for iref::Iri {
65 #[inline(always)]
66 fn rdf_fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
67 self.as_iri_ref().rdf_fmt(f)
68 }
69}
70
71impl RdfDisplay for iref::IriBuf {
72 #[inline(always)]
73 fn rdf_fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
74 self.as_iri_ref().rdf_fmt(f)
75 }
76}
77
78impl RdfDisplay for iref::IriRefBuf {
79 #[inline(always)]
80 fn rdf_fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
81 self.as_iri_ref().rdf_fmt(f)
82 }
83}
84
85impl RdfDisplay for LangTag {
86 fn rdf_fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
87 use fmt::Display;
88 self.as_str().fmt(f)
89 }
90}
91
92impl RdfDisplay for LangTagBuf {
93 fn rdf_fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
94 use fmt::Display;
95 self.as_str().fmt(f)
96 }
97}
98
99impl<T: RdfDisplay + ?Sized> RdfDisplay for &T {
100 #[inline(always)]
101 fn rdf_fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
102 T::rdf_fmt(*self, f)
103 }
104}
105
106pub struct RdfDisplayed<T>(T);
108
109impl<T: RdfDisplay> fmt::Display for RdfDisplayed<T> {
110 #[inline(always)]
111 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
112 self.0.rdf_fmt(f)
113 }
114}
115
116impl<R: RdfDisplay> RdfDisplay for BTreeGraph<R> {
117 fn rdf_fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
118 for t in self {
119 writeln!(f, "{} .", t.rdf_display())?;
120 }
121
122 Ok(())
123 }
124}
125
126impl<R: RdfDisplay> RdfDisplay for IndexedBTreeGraph<R> {
127 fn rdf_fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
128 for t in self {
129 writeln!(f, "{} .", t.rdf_display())?;
130 }
131
132 Ok(())
133 }
134}
135
136impl<R: RdfDisplay> RdfDisplay for BTreeDataset<R> {
137 fn rdf_fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
138 for t in self {
139 writeln!(f, "{} .", t.rdf_display())?;
140 }
141
142 Ok(())
143 }
144}
145
146impl<R: RdfDisplay> RdfDisplay for IndexedBTreeDataset<R> {
147 fn rdf_fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
148 for t in self {
149 writeln!(f, "{} .", t.rdf_display())?;
150 }
151
152 Ok(())
153 }
154}
155
156impl<R: RdfDisplay> RdfDisplay for RdfDiff<R> {
157 fn rdf_fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
158 for quad in &self.added {
159 writeln!(f, "+ {} .", quad.rdf_display())?;
160 }
161
162 for quad in &self.removed {
163 writeln!(f, "- {} .", quad.rdf_display())?;
164 }
165
166 Ok(())
167 }
168}
169
170impl<'a, R: RdfDisplay> RdfDisplay for ColoredRdfDiff<'a, R> {
171 fn rdf_fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
172 for quad in &self.0.added {
173 writeln!(f, "\x1b[32m+ {} .\x1b[0m", quad.rdf_display())?;
174 }
175
176 for quad in &self.0.removed {
177 writeln!(f, "\x1b[31m- {} .\x1b[0m", quad.rdf_display())?;
178 }
179
180 Ok(())
181 }
182}