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}