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
use std::fmt;

pub trait RdfDisplay {
	fn rdf_fmt(&self, f: &mut fmt::Formatter) -> fmt::Result;

	#[inline(always)]
	fn rdf_display(&self) -> RdfDisplayed<&Self> {
		RdfDisplayed(self)
	}
}

impl RdfDisplay for String {
	fn rdf_fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		use fmt::Display;
		write!(f, "\"")?;

		for c in self.chars() {
			match c {
				'"' => write!(f, "\\\""),
				'\\' => write!(f, "\\\\"),
				'\n' => write!(f, "\\n"),
				'\r' => write!(f, "\\r"),
				c => c.fmt(f),
			}?
		}

		write!(f, "\"")
	}
}

impl<'a> RdfDisplay for iref::IriRef<'a> {
	fn rdf_fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		write!(f, "<")?;

		for c in self.as_str().chars() {
			match c {
				'\x00'..='\x20' | '<' | '>' | '"' | '{' | '}' | '|' | '^' | '`' | '\\' => {
					let bytes: u32 = c.into();
					write!(f, "\\u{bytes:#04x}")
				}
				_ => fmt::Display::fmt(&c, f),
			}?;
		}

		write!(f, ">")
	}
}

impl<'a> RdfDisplay for iref::Iri<'a> {
	#[inline(always)]
	fn rdf_fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		self.as_iri_ref().rdf_fmt(f)
	}
}

impl RdfDisplay for iref::IriBuf {
	#[inline(always)]
	fn rdf_fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		self.as_iri_ref().rdf_fmt(f)
	}
}

impl RdfDisplay for iref::IriRefBuf {
	#[inline(always)]
	fn rdf_fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		self.as_iri_ref().rdf_fmt(f)
	}
}

impl<'a, T: RdfDisplay + ?Sized> RdfDisplay for &'a T {
	#[inline(always)]
	fn rdf_fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		T::rdf_fmt(*self, f)
	}
}

pub struct RdfDisplayed<T>(T);

impl<T: RdfDisplay> fmt::Display for RdfDisplayed<T> {
	#[inline(always)]
	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
		self.0.rdf_fmt(f)
	}
}

#[cfg(feature = "contextual")]
pub trait RdfDisplayWithContext<C: ?Sized> {
	fn rdf_fmt_with(&self, context: &C, f: &mut fmt::Formatter) -> fmt::Result;
}

#[cfg(feature = "contextual")]
impl<'a, T: RdfDisplayWithContext<C> + ?Sized, C: ?Sized> RdfDisplayWithContext<C> for &'a T {
	#[inline(always)]
	fn rdf_fmt_with(&self, context: &C, f: &mut fmt::Formatter) -> fmt::Result {
		T::rdf_fmt_with(*self, context, f)
	}
}

#[cfg(feature = "contextual")]
impl<'c, T: RdfDisplayWithContext<C>, C: ?Sized> RdfDisplay for contextual::Contextual<T, &'c C> {
	#[inline(always)]
	fn rdf_fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		self.0.rdf_fmt_with(self.1, f)
	}
}

#[cfg(feature = "contextual")]
impl<'c, T: RdfDisplayWithContext<C>, C: ?Sized> RdfDisplay
	for contextual::Contextual<T, &'c mut C>
{
	#[inline(always)]
	fn rdf_fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		self.0.rdf_fmt_with(self.1, f)
	}
}