json_ld/syntax/
keyword.rs1use std::borrow::Borrow;
2use std::convert::TryFrom;
3use std::fmt;
4use std::str::FromStr;
5
6#[derive(Clone, Copy, Debug)]
7pub struct NotAJsonLdKeyword<T = String>(pub T);
8
9impl<T: ?Sized + ToOwned> NotAJsonLdKeyword<&T> {
10 pub fn into_owned(self) -> NotAJsonLdKeyword<T::Owned> {
11 NotAJsonLdKeyword(self.0.to_owned())
12 }
13}
14
15macro_rules! keyword {
16 {
17 $(
18 $(#[$meta:meta])*
19 $ident:ident : $lit:literal
20 ),*
21 } => {
22 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
24 #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
25 pub enum JsonLdKeyword {
26 $(
27 $(#[$meta])*
28 #[cfg_attr(feature = "serde", serde(rename = $lit))]
29 $ident
30 ),*
31 }
32
33 impl JsonLdKeyword {
34 pub fn into_str(self) -> &'static str {
35 match self {
36 $(
37 Self::$ident => $lit
38 ),*
39 }
40 }
41 }
42
43 impl<'a> TryFrom<&'a str> for JsonLdKeyword {
44 type Error = NotAJsonLdKeyword<&'a str>;
45
46 fn try_from(input: &'a str) -> Result<JsonLdKeyword, NotAJsonLdKeyword<&'a str>> {
47 match input {
48 $(
49 $lit => Ok(Self::$ident),
50 )*
51 _ => Err(NotAJsonLdKeyword(input))
52 }
53 }
54 }
55 };
56}
57
58keyword! {
59 Base : "@base",
63
64 Container : "@container",
67
68 Context : "@context",
71
72 Direction : "@direction",
76
77 Graph : "@graph",
80
81 Id : "@id",
85
86 Import : "@import",
90
91 Included : "@included",
95
96 Index : "@index",
100
101 Json : "@json",
104
105 Language : "@language",
109
110 List : "@list",
113
114 Nest : "@nest",
118
119 None : "@none",
124
125 Prefix : "@prefix",
129
130 Propagate : "@propagate",
138
139 Protected : "@protected",
142
143 Reverse : "@reverse",
146
147 Set : "@set",
151
152 Type : "@type",
155
156 Value : "@value",
159
160 Version : "@version",
163
164 Vocab : "@vocab"
167}
168
169impl JsonLdKeyword {
170 pub fn as_str(&self) -> &'static str {
171 self.into_str()
172 }
173}
174
175impl FromStr for JsonLdKeyword {
176 type Err = NotAJsonLdKeyword;
177
178 fn from_str(s: &str) -> Result<Self, Self::Err> {
179 Self::try_from(s).map_err(NotAJsonLdKeyword::into_owned)
180 }
181}
182
183impl<'a> From<JsonLdKeyword> for &'a str {
184 fn from(k: JsonLdKeyword) -> &'a str {
185 k.into_str()
186 }
187}
188
189impl fmt::Display for JsonLdKeyword {
190 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
191 self.into_str().fmt(f)
192 }
193}
194
195impl PartialEq<str> for JsonLdKeyword {
196 fn eq(&self, other: &str) -> bool {
197 self.as_str() == other
198 }
199}
200
201impl PartialEq<&str> for JsonLdKeyword {
202 fn eq(&self, other: &&str) -> bool {
203 self.as_str() == *other
204 }
205}
206
207impl PartialEq<JsonLdKeyword> for str {
208 fn eq(&self, other: &JsonLdKeyword) -> bool {
209 self == other.as_str()
210 }
211}
212
213impl PartialEq<JsonLdKeyword> for &str {
214 fn eq(&self, other: &JsonLdKeyword) -> bool {
215 *self == other.as_str()
216 }
217}
218
219pub fn is_keyword(str: &str) -> bool {
220 JsonLdKeyword::try_from(str).is_ok()
221}
222
223fn is_alpha(c: char) -> bool {
224 let c = c as u32;
225 (0x41..=0x5a).contains(&c) || (0x61..=0x7a).contains(&c)
226}
227
228pub fn is_keyword_like(s: &str) -> bool {
229 if s.len() > 1 {
230 for (i, c) in s.chars().enumerate() {
231 if (i == 0 && c != '@') || (i > 0 && !is_alpha(c)) {
232 return false;
233 }
234 }
235
236 true
237 } else {
238 false
239 }
240}
241
242#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
243pub struct JsonLdKeywordType;
244
245impl JsonLdKeywordType {
246 pub fn as_str(&self) -> &'static str {
247 "@type"
248 }
249}
250
251impl Borrow<str> for JsonLdKeywordType {
252 fn borrow(&self) -> &str {
253 self.as_str()
254 }
255}