1use std::borrow::Borrow;
2use std::convert::TryFrom;
3use std::fmt;
4
5#[derive(Clone, Copy, Debug)]
6pub struct NotAKeyword<T>(pub T);
7
8#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
10#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
11pub enum Keyword {
12 #[cfg_attr(feature = "serde", serde(rename = "@base"))]
16 Base,
17
18 #[cfg_attr(feature = "serde", serde(rename = "@container"))]
21 Container,
22
23 #[cfg_attr(feature = "serde", serde(rename = "@context"))]
26 Context,
27
28 #[cfg_attr(feature = "serde", serde(rename = "@direction"))]
32 Direction,
33
34 #[cfg_attr(feature = "serde", serde(rename = "@graph"))]
37 Graph,
38
39 #[cfg_attr(feature = "serde", serde(rename = "@id"))]
43 Id,
44
45 #[cfg_attr(feature = "serde", serde(rename = "@import"))]
49 Import,
50
51 #[cfg_attr(feature = "serde", serde(rename = "@included"))]
55 Included,
56
57 #[cfg_attr(feature = "serde", serde(rename = "@index"))]
61 Index,
62
63 #[cfg_attr(feature = "serde", serde(rename = "@json"))]
66 Json,
67
68 #[cfg_attr(feature = "serde", serde(rename = "@language"))]
72 Language,
73
74 #[cfg_attr(feature = "serde", serde(rename = "@list"))]
77 List,
78
79 #[cfg_attr(feature = "serde", serde(rename = "@nest"))]
83 Nest,
84
85 #[cfg_attr(feature = "serde", serde(rename = "@none"))]
90 None,
91
92 #[cfg_attr(feature = "serde", serde(rename = "@prefix"))]
96 Prefix,
97
98 #[cfg_attr(feature = "serde", serde(rename = "@propagate"))]
106 Propagate,
107
108 #[cfg_attr(feature = "serde", serde(rename = "@protected"))]
111 Protected,
112
113 #[cfg_attr(feature = "serde", serde(rename = "@reverse"))]
116 Reverse,
117
118 #[cfg_attr(feature = "serde", serde(rename = "@set"))]
122 Set,
123
124 #[cfg_attr(feature = "serde", serde(rename = "@type"))]
127 Type,
128
129 #[cfg_attr(feature = "serde", serde(rename = "@value"))]
132 Value,
133
134 #[cfg_attr(feature = "serde", serde(rename = "@version"))]
137 Version,
138
139 #[cfg_attr(feature = "serde", serde(rename = "@vocab"))]
142 Vocab,
143}
144
145impl Keyword {
146 pub fn into_str(self) -> &'static str {
147 use Keyword::*;
148 match self {
149 Base => "@base",
150 Container => "@container",
151 Context => "@context",
152 Direction => "@direction",
153 Graph => "@graph",
154 Id => "@id",
155 Import => "@import",
156 Included => "@included",
157 Index => "@index",
158 Json => "@json",
159 Language => "@language",
160 List => "@list",
161 Nest => "@nest",
162 None => "@none",
163 Prefix => "@prefix",
164 Propagate => "@propagate",
165 Protected => "@protected",
166 Reverse => "@reverse",
167 Set => "@set",
168 Type => "@type",
169 Value => "@value",
170 Version => "@version",
171 Vocab => "@vocab",
172 }
173 }
174}
175
176impl<'a> TryFrom<&'a str> for Keyword {
177 type Error = NotAKeyword<&'a str>;
178
179 fn try_from(s: &'a str) -> Result<Keyword, NotAKeyword<&'a str>> {
180 use Keyword::*;
181 match s {
182 "@base" => Ok(Base),
183 "@container" => Ok(Container),
184 "@context" => Ok(Context),
185 "@direction" => Ok(Direction),
186 "@graph" => Ok(Graph),
187 "@id" => Ok(Id),
188 "@import" => Ok(Import),
189 "@included" => Ok(Included),
190 "@index" => Ok(Index),
191 "@json" => Ok(Json),
192 "@language" => Ok(Language),
193 "@list" => Ok(List),
194 "@nest" => Ok(Nest),
195 "@none" => Ok(None),
196 "@prefix" => Ok(Prefix),
197 "@propagate" => Ok(Propagate),
198 "@protected" => Ok(Protected),
199 "@reverse" => Ok(Reverse),
200 "@set" => Ok(Set),
201 "@type" => Ok(Type),
202 "@value" => Ok(Value),
203 "@version" => Ok(Version),
204 "@vocab" => Ok(Vocab),
205 _ => Err(NotAKeyword(s)),
206 }
207 }
208}
209
210impl From<Keyword> for &'static str {
211 fn from(k: Keyword) -> &'static str {
212 k.into_str()
213 }
214}
215
216impl fmt::Display for Keyword {
217 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
218 self.into_str().fmt(f)
219 }
220}
221
222pub fn is_keyword(str: &str) -> bool {
229 Keyword::try_from(str).is_ok()
230}
231
232fn is_alpha(c: char) -> bool {
233 let c = c as u32;
234 (0x41..=0x5a).contains(&c) || (0x61..=0x7a).contains(&c)
235}
236
237pub fn is_keyword_like(s: &str) -> bool {
238 if s.len() > 1 {
239 for (i, c) in s.chars().enumerate() {
240 if (i == 0 && c != '@') || (i > 0 && !is_alpha(c)) {
241 return false;
242 }
243 }
244
245 true
246 } else {
247 false
248 }
249}
250
251#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
252pub struct KeywordType;
253
254impl KeywordType {
255 pub fn as_str(&self) -> &'static str {
256 "@type"
257 }
258}
259
260impl Borrow<str> for KeywordType {
261 fn borrow(&self) -> &str {
262 self.as_str()
263 }
264}