toon_core/keywords.rs
1//! JSON-LD keyword constants for TOON-LD.
2//!
3//! This module defines all JSON-LD 1.0 and 1.1 keywords used in TOON-LD serialization
4//! and parsing. Keywords are organized into core keywords (JSON-LD 1.0) and extended
5//! keywords (JSON-LD 1.1).
6
7// =============================================================================
8// JSON-LD Keywords (Core - JSON-LD 1.0)
9// =============================================================================
10
11/// The `@context` keyword defines the vocabulary mapping for terms
12pub const JSONLD_CONTEXT: &str = "@context";
13
14/// The `@id` keyword identifies a node with an IRI
15pub const JSONLD_ID: &str = "@id";
16
17/// The `@type` keyword specifies the type of a node or value
18pub const JSONLD_TYPE: &str = "@type";
19
20/// The `@graph` keyword contains a named graph
21pub const JSONLD_GRAPH: &str = "@graph";
22
23/// The `@value` keyword specifies the value of a typed or language-tagged literal
24pub const JSONLD_VALUE: &str = "@value";
25
26/// The `@language` keyword specifies the language of a string value
27pub const JSONLD_LANGUAGE: &str = "@language";
28
29/// The `@list` keyword specifies an ordered list
30pub const JSONLD_LIST: &str = "@list";
31
32/// The `@set` keyword specifies an unordered set
33pub const JSONLD_SET: &str = "@set";
34
35/// The `@reverse` keyword specifies reverse properties
36pub const JSONLD_REVERSE: &str = "@reverse";
37
38/// The `@base` keyword sets the base IRI for relative IRIs
39pub const JSONLD_BASE: &str = "@base";
40
41/// The `@vocab` keyword sets the default vocabulary for terms
42pub const JSONLD_VOCAB: &str = "@vocab";
43
44// =============================================================================
45// JSON-LD 1.1 Keywords (Extended)
46// =============================================================================
47
48/// The `@container` keyword specifies how values are organized
49pub const JSONLD_CONTAINER: &str = "@container";
50
51/// The `@direction` keyword specifies text direction (ltr/rtl)
52pub const JSONLD_DIRECTION: &str = "@direction";
53
54/// The `@import` keyword imports an external context
55pub const JSONLD_IMPORT: &str = "@import";
56
57/// The `@included` keyword specifies included nodes
58pub const JSONLD_INCLUDED: &str = "@included";
59
60/// The `@index` keyword specifies an index value for a node
61pub const JSONLD_INDEX: &str = "@index";
62
63/// The `@json` keyword marks a JSON literal value
64pub const JSONLD_JSON: &str = "@json";
65
66/// The `@nest` keyword specifies nested properties
67pub const JSONLD_NEST: &str = "@nest";
68
69/// The `@none` keyword represents the default index value
70pub const JSONLD_NONE: &str = "@none";
71
72/// The `@prefix` keyword indicates a term is a prefix
73pub const JSONLD_PREFIX: &str = "@prefix";
74
75/// The `@propagate` keyword controls context propagation
76pub const JSONLD_PROPAGATE: &str = "@propagate";
77
78/// The `@protected` keyword prevents term redefinition
79pub const JSONLD_PROTECTED: &str = "@protected";
80
81/// The `@version` keyword specifies the JSON-LD version
82pub const JSONLD_VERSION: &str = "@version";
83
84// =============================================================================
85// TOON-LD Shorthand Keywords
86// =============================================================================
87// These are the same as JSON-LD keywords but defined separately for clarity
88// in the TOON-LD serialization format. We preserve the @ prefix for clarity.
89
90/// TOON-LD shorthand for `@id`
91pub const TOON_ID: &str = "@id";
92
93/// TOON-LD shorthand for `@type`
94pub const TOON_TYPE: &str = "@type";
95
96/// TOON-LD shorthand for `@graph`
97pub const TOON_GRAPH: &str = "@graph";
98
99/// TOON-LD shorthand for `@value`
100pub const TOON_VALUE: &str = "@value";
101
102/// TOON-LD shorthand for `@language`
103pub const TOON_LANGUAGE: &str = "@language";
104
105/// TOON-LD shorthand for `@list`
106pub const TOON_LIST: &str = "@list";
107
108/// TOON-LD shorthand for `@set`
109pub const TOON_SET: &str = "@set";
110
111/// TOON-LD shorthand for `@reverse`
112pub const TOON_REVERSE: &str = "@reverse";
113
114/// TOON-LD shorthand for `@base`
115pub const TOON_BASE: &str = "@base";
116
117/// TOON-LD shorthand for `@vocab`
118pub const TOON_VOCAB: &str = "@vocab";
119
120/// TOON-LD shorthand for `@container`
121pub const TOON_CONTAINER: &str = "@container";
122
123/// TOON-LD shorthand for `@direction`
124pub const TOON_DIRECTION: &str = "@direction";
125
126/// TOON-LD shorthand for `@import`
127pub const TOON_IMPORT: &str = "@import";
128
129/// TOON-LD shorthand for `@included`
130pub const TOON_INCLUDED: &str = "@included";
131
132/// TOON-LD shorthand for `@index`
133pub const TOON_INDEX: &str = "@index";
134
135/// TOON-LD shorthand for `@json`
136pub const TOON_JSON: &str = "@json";
137
138/// TOON-LD shorthand for `@nest`
139pub const TOON_NEST: &str = "@nest";
140
141/// TOON-LD shorthand for `@none`
142pub const TOON_NONE: &str = "@none";
143
144/// TOON-LD shorthand for `@prefix`
145pub const TOON_PREFIX: &str = "@prefix";
146
147/// TOON-LD shorthand for `@propagate`
148pub const TOON_PROPAGATE: &str = "@propagate";
149
150/// TOON-LD shorthand for `@protected`
151pub const TOON_PROTECTED: &str = "@protected";
152
153/// TOON-LD shorthand for `@version`
154pub const TOON_VERSION: &str = "@version";
155
156// =============================================================================
157// Keyword Ordering
158// =============================================================================
159
160/// Returns the serialization order priority for a JSON-LD keyword.
161///
162/// Lower values appear first in the output. This ensures consistent ordering
163/// with `@context` first, followed by metadata keywords, then content keywords.
164///
165/// # Arguments
166///
167/// * `keyword` - The JSON-LD keyword to get the order for
168///
169/// # Returns
170///
171/// An integer representing the sort order (lower = earlier)
172pub fn keyword_order(keyword: &str) -> i32 {
173 match keyword {
174 // Context and metadata come first
175 JSONLD_CONTEXT => 0,
176 JSONLD_VERSION => 1,
177 JSONLD_BASE => 2,
178 JSONLD_VOCAB => 3,
179 JSONLD_IMPORT => 4,
180 JSONLD_PROPAGATE => 5,
181 JSONLD_DIRECTION => 6,
182
183 // Node identification
184 JSONLD_ID => 10,
185 JSONLD_TYPE => 11,
186 JSONLD_INDEX => 12,
187
188 // Content keywords
189 JSONLD_GRAPH => 13,
190 JSONLD_INCLUDED => 14,
191 JSONLD_REVERSE => 15,
192 JSONLD_NEST => 16,
193
194 // Container and type keywords
195 JSONLD_CONTAINER => 20,
196 JSONLD_JSON => 21,
197 JSONLD_NONE => 22,
198 JSONLD_PREFIX => 23,
199 JSONLD_PROTECTED => 24,
200
201 // Value keywords (typically handled specially)
202 JSONLD_VALUE => 30,
203 JSONLD_LANGUAGE => 31,
204 JSONLD_LIST => 32,
205 JSONLD_SET => 33,
206
207 // Non-keywords come last
208 _ => 100,
209 }
210}
211
212/// Checks if a string is a JSON-LD keyword (starts with @)
213///
214/// # Arguments
215///
216/// * `s` - The string to check
217///
218/// # Returns
219///
220/// `true` if the string starts with `@`, `false` otherwise
221#[inline]
222pub fn is_keyword(s: &str) -> bool {
223 s.starts_with('@')
224}
225
226/// Returns the TOON-LD display key for a JSON-LD keyword.
227///
228/// For most keywords, this is the same as the input. This function
229/// provides a central place to handle any keyword transformations
230/// if needed in the future.
231///
232/// # Arguments
233///
234/// * `keyword` - The JSON-LD keyword
235///
236/// # Returns
237///
238/// The corresponding TOON-LD display key, or `None` if not a known keyword.
239pub fn get_toon_keyword(keyword: &str) -> Option<&'static str> {
240 match keyword {
241 JSONLD_CONTEXT => Some(JSONLD_CONTEXT),
242 JSONLD_ID => Some(TOON_ID),
243 JSONLD_TYPE => Some(TOON_TYPE),
244 JSONLD_GRAPH => Some(TOON_GRAPH),
245 JSONLD_VALUE => Some(TOON_VALUE),
246 JSONLD_LANGUAGE => Some(TOON_LANGUAGE),
247 JSONLD_LIST => Some(TOON_LIST),
248 JSONLD_SET => Some(TOON_SET),
249 JSONLD_REVERSE => Some(TOON_REVERSE),
250 JSONLD_BASE => Some(TOON_BASE),
251 JSONLD_VOCAB => Some(TOON_VOCAB),
252 JSONLD_CONTAINER => Some(TOON_CONTAINER),
253 JSONLD_DIRECTION => Some(TOON_DIRECTION),
254 JSONLD_IMPORT => Some(TOON_IMPORT),
255 JSONLD_INCLUDED => Some(TOON_INCLUDED),
256 JSONLD_INDEX => Some(TOON_INDEX),
257 JSONLD_JSON => Some(TOON_JSON),
258 JSONLD_NEST => Some(TOON_NEST),
259 JSONLD_NONE => Some(TOON_NONE),
260 JSONLD_PREFIX => Some(TOON_PREFIX),
261 JSONLD_PROPAGATE => Some(TOON_PROPAGATE),
262 JSONLD_PROTECTED => Some(TOON_PROTECTED),
263 JSONLD_VERSION => Some(TOON_VERSION),
264 _ => None,
265 }
266}
267
268#[cfg(test)]
269mod tests {
270 use super::*;
271
272 #[test]
273 fn test_keyword_order() {
274 assert!(keyword_order(JSONLD_CONTEXT) < keyword_order(JSONLD_ID));
275 assert!(keyword_order(JSONLD_ID) < keyword_order(JSONLD_GRAPH));
276 assert!(keyword_order(JSONLD_GRAPH) < keyword_order("custom_property"));
277 }
278
279 #[test]
280 fn test_is_keyword() {
281 assert!(is_keyword("@context"));
282 assert!(is_keyword("@id"));
283 assert!(is_keyword("@type"));
284 assert!(is_keyword("@custom"));
285 assert!(!is_keyword("name"));
286 assert!(!is_keyword("foaf:name"));
287 assert!(!is_keyword(""));
288 }
289
290 #[test]
291 fn test_get_toon_keyword() {
292 assert_eq!(get_toon_keyword(JSONLD_CONTEXT), Some("@context"));
293 assert_eq!(get_toon_keyword(JSONLD_ID), Some("@id"));
294 assert_eq!(get_toon_keyword(JSONLD_TYPE), Some("@type"));
295 assert_eq!(get_toon_keyword(JSONLD_VERSION), Some("@version"));
296 }
297
298 #[test]
299 fn test_unknown_keyword_returns_none() {
300 // Unknown keywords return None
301 assert_eq!(get_toon_keyword("@unknown"), None);
302 assert_eq!(get_toon_keyword("name"), None);
303 }
304}