json_ld_syntax_next/
keyword.rs

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/// JSON-LD keywords.
9#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
10#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
11pub enum Keyword {
12	/// `@base`.
13	/// Used to set the base IRI against which to resolve those relative IRI references
14	/// which are otherwise interpreted relative to the document.
15	#[cfg_attr(feature = "serde", serde(rename = "@base"))]
16	Base,
17
18	/// `@container`.
19	/// Used to set the default container type for a term.
20	#[cfg_attr(feature = "serde", serde(rename = "@container"))]
21	Container,
22
23	/// `@context`.
24	/// Used to define the short-hand names that are used throughout a JSON-LD document.
25	#[cfg_attr(feature = "serde", serde(rename = "@context"))]
26	Context,
27
28	/// `@direction`.
29	/// Used to set the base direction of a JSON-LD value, which are not typed values.
30	/// (e.g. strings, or language-tagged strings).
31	#[cfg_attr(feature = "serde", serde(rename = "@direction"))]
32	Direction,
33
34	/// `@graph`.
35	/// Used to express a graph.
36	#[cfg_attr(feature = "serde", serde(rename = "@graph"))]
37	Graph,
38
39	/// `@id`.
40	/// Used to uniquely identify node objects that are being described in the document with IRIs
41	/// or blank node identifiers.
42	#[cfg_attr(feature = "serde", serde(rename = "@id"))]
43	Id,
44
45	/// `@import`.
46	/// Used in a context definition to load an external context within which the containing
47	/// context definition is merged.
48	#[cfg_attr(feature = "serde", serde(rename = "@import"))]
49	Import,
50
51	/// `@included`.
52	/// Used in a top-level node object to define an included block, for including secondary node
53	/// objects within another node object.
54	#[cfg_attr(feature = "serde", serde(rename = "@included"))]
55	Included,
56
57	/// `@index`.
58	/// Used to specify that a container is used to index information and that processing should
59	/// continue deeper into a JSON data structure.
60	#[cfg_attr(feature = "serde", serde(rename = "@index"))]
61	Index,
62
63	/// `@json`.
64	/// Used as the @type value of a JSON literal.
65	#[cfg_attr(feature = "serde", serde(rename = "@json"))]
66	Json,
67
68	/// `@language`.
69	/// Used to specify the language for a particular string value or the default language of a
70	/// JSON-LD document.
71	#[cfg_attr(feature = "serde", serde(rename = "@language"))]
72	Language,
73
74	/// `@list`.
75	/// Used to express an ordered set of data.
76	#[cfg_attr(feature = "serde", serde(rename = "@list"))]
77	List,
78
79	/// `@nest`.
80	/// Used to define a property of a node object that groups together properties of that node,
81	/// but is not an edge in the graph.
82	#[cfg_attr(feature = "serde", serde(rename = "@nest"))]
83	Nest,
84
85	/// `@none`.
86	/// Used as an index value in an index map, id map, language map, type map, or elsewhere where
87	/// a map is used to index into other values, when the indexed node does not have the feature
88	/// being indexed.
89	#[cfg_attr(feature = "serde", serde(rename = "@none"))]
90	None,
91
92	/// `@prefix`.
93	/// With the value true, allows this term to be used to construct a compact IRI when
94	/// compacting.
95	#[cfg_attr(feature = "serde", serde(rename = "@prefix"))]
96	Prefix,
97
98	/// `@propagate`.
99	/// Used in a context definition to change the scope of that context.
100	///
101	/// By default, it is true, meaning that contexts propagate across node objects
102	/// (other than for type-scoped contexts, which default to false).
103	/// Setting this to false causes term definitions created within that context to be removed
104	/// when entering a new node object.
105	#[cfg_attr(feature = "serde", serde(rename = "@propagate"))]
106	Propagate,
107
108	/// `@protected`.
109	/// Used to prevent term definitions of a context to be overridden by other contexts.
110	#[cfg_attr(feature = "serde", serde(rename = "@protected"))]
111	Protected,
112
113	/// `@reverse`.
114	/// Used to express reverse properties.
115	#[cfg_attr(feature = "serde", serde(rename = "@reverse"))]
116	Reverse,
117
118	/// `@set`.
119	/// Used to express an unordered set of data and to ensure that values are always represented
120	/// as arrays.
121	#[cfg_attr(feature = "serde", serde(rename = "@set"))]
122	Set,
123
124	/// `@type`.
125	/// Used to set the type of a node or the datatype of a typed value.
126	#[cfg_attr(feature = "serde", serde(rename = "@type"))]
127	Type,
128
129	/// `@value`.
130	/// Used to specify the data that is associated with a particular property in the graph.
131	#[cfg_attr(feature = "serde", serde(rename = "@value"))]
132	Value,
133
134	/// `@version`.
135	/// Used in a context definition to set the processing mode.
136	#[cfg_attr(feature = "serde", serde(rename = "@version"))]
137	Version,
138
139	/// `@vocab`.
140	/// Used to expand properties and values in @type with a common prefix IRI.
141	#[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
222// impl<K: JsonBuild> utils::AsAnyJson<K> for Keyword {
223// 	fn as_json_with(&self, meta: K::MetaData) -> K {
224// 		self.into_str().as_json_with(meta)
225// 	}
226// }
227
228pub 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}