1use crate::object::{JsonLdObjectMut, JsonLdObjectRef};
2use crate::syntax::JsonLdKeyword;
3use crate::{JsonLdDirection, JsonLdLangString, JsonLdLenient, JsonLdType, JsonLdVisit, object};
4use educe::Educe;
5use json_syntax::{JsonNumber, JsonNumberBuf, JsonValue, ryu_js};
6use langtag::LangTag;
7use rdf_syntax::{IdRef, Iri, IriBuf};
8use rdf_syntax::{Literal, RDF_JSON};
9use std::hash::Hash;
10use xsd_types::{XSD_BOOLEAN, XSD_FLOAT, XSD_INTEGER};
11
12pub enum JsonLdValueType {
14 Json,
15 Id(IriBuf),
16}
17
18impl JsonLdValueType {
19 pub fn as_id(&self) -> Option<IdRef<'_>> {
20 match self {
21 Self::Json => None,
22 Self::Id(t) => Some(IdRef::Iri(t)),
23 }
24 }
25}
26
27#[derive(Educe)]
29#[educe(Clone, Copy)]
30pub enum JsonLdValueTypeRef<'a> {
31 Json,
32 Id(&'a Iri),
33}
34
35impl<'a> JsonLdValueTypeRef<'a> {
36 pub fn into_object_type(self) -> JsonLdType {
37 match self {
38 Self::Json => JsonLdType::Json,
39 Self::Id(id) => JsonLdType::Iri(id.to_owned()),
40 }
41 }
42
43 pub fn into_id_ref(self) -> Option<IdRef<'a>> {
44 match self {
45 Self::Json => None,
46 Self::Id(t) => Some(IdRef::Iri(t)),
47 }
48 }
49}
50
51#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
53pub enum JsonLdLiteralType {
54 Json,
56
57 Iri(IriBuf),
59}
60
61impl JsonLdLiteralType {
62 pub fn iri(&self) -> &Iri {
66 match self {
67 Self::Json => RDF_JSON,
68 Self::Iri(iri) => iri,
69 }
70 }
71
72 pub fn is_json(&self) -> bool {
76 match self {
77 Self::Json => true,
78 Self::Iri(iri) => iri == RDF_JSON,
79 }
80 }
81}
82
83#[cfg(feature = "serde")]
84impl serde::Serialize for JsonLdLiteralType {
85 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
86 match self {
87 Self::Json => serializer.serialize_str("@json"),
88 Self::Iri(iri) => serializer.serialize_str(iri.as_str()),
89 }
90 }
91}
92
93#[cfg(feature = "serde")]
94impl<'de> serde::Deserialize<'de> for JsonLdLiteralType {
95 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
96 let s = String::deserialize(deserializer)?;
97 if s == "@json" {
98 Ok(Self::Json)
99 } else {
100 IriBuf::new(s)
101 .map(Self::Iri)
102 .map_err(serde::de::Error::custom)
103 }
104 }
105}
106
107#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
111#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
112pub struct JsonLdLiteralValue {
113 #[cfg_attr(feature = "serde", serde(rename = "@value"))]
115 pub value: JsonValue,
116
117 #[cfg_attr(
119 feature = "serde",
120 serde(rename = "@type", default, skip_serializing_if = "Option::is_none")
121 )]
122 pub type_: Option<JsonLdLiteralType>,
123}
124
125impl JsonLdLiteralValue {
126 pub fn new(value: JsonValue, type_: Option<JsonLdLiteralType>) -> Self {
128 Self { value, type_ }
129 }
130
131 pub fn null() -> Self {
133 Self::new(JsonValue::Null, None)
134 }
135
136 pub fn json(value: JsonValue) -> Self {
138 Self::new(value, Some(JsonLdLiteralType::Json))
139 }
140
141 #[inline(always)]
143 pub fn as_str(&self) -> Option<&str> {
144 self.value.as_str().map(AsRef::as_ref)
145 }
146
147 #[inline(always)]
149 pub fn as_bool(&self) -> Option<bool> {
150 self.value.as_boolean()
151 }
152
153 #[inline(always)]
155 pub fn as_number(&self) -> Option<&JsonNumber> {
156 self.value.as_number()
157 }
158
159 pub fn type_iri(&self) -> Option<&Iri> {
161 match &self.type_ {
162 Some(JsonLdLiteralType::Iri(iri)) => Some(iri),
163 _ => None,
164 }
165 }
166
167 pub fn is_json(&self) -> bool {
169 self.type_.as_ref().is_some_and(JsonLdLiteralType::is_json)
170 }
171
172 pub fn canonicalize_with(&mut self, buffer: &mut ryu_js::Buffer) {
176 if let JsonValue::Number(n) = &mut self.value {
177 *n = JsonNumberBuf::from_number(n.canonicalized_with(buffer))
178 }
179 }
180
181 pub fn canonicalize(&mut self) {
183 let mut buffer = ryu_js::Buffer::new();
184 self.canonicalize_with(&mut buffer)
185 }
186}
187
188#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
192#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
193#[cfg_attr(feature = "serde", serde(untagged))]
194pub enum JsonLdValue {
195 LangString(JsonLdLangString),
197
198 Literal(JsonLdLiteralValue),
200}
201
202impl JsonLdValue {
203 #[inline(always)]
205 pub fn null() -> Self {
206 Self::Literal(JsonLdLiteralValue::null())
207 }
208
209 #[inline(always)]
210 pub fn as_str(&self) -> Option<&str> {
211 match self {
212 JsonLdValue::Literal(lit) => lit.as_str(),
213 JsonLdValue::LangString(s) => Some(s.as_str()),
214 }
215 }
216
217 #[inline(always)]
218 pub fn as_literal(&self) -> Option<&JsonLdLiteralValue> {
219 match self {
220 Self::Literal(lit) => Some(lit),
221 _ => None,
222 }
223 }
224
225 pub fn literal_type(&self) -> Option<&JsonLdLiteralType> {
226 match self {
227 Self::Literal(lit) => lit.type_.as_ref(),
228 _ => None,
229 }
230 }
231
232 pub fn literal_type_iri(&self) -> Option<&Iri> {
233 match self {
234 Self::Literal(lit) => lit.type_iri(),
235 _ => None,
236 }
237 }
238
239 pub fn set_literal_type(&mut self, ty: Option<JsonLdLiteralType>) -> Option<JsonLdLiteralType> {
243 match self {
244 Self::Literal(lit) => std::mem::replace(&mut lit.type_, ty),
245 _ => None,
246 }
247 }
248
249 #[inline(always)]
250 pub fn as_bool(&self) -> Option<bool> {
251 match self {
252 JsonLdValue::Literal(lit) => lit.as_bool(),
253 _ => None,
254 }
255 }
256
257 #[inline(always)]
258 pub fn as_number(&self) -> Option<&JsonNumber> {
259 match self {
260 JsonLdValue::Literal(lit) => lit.as_number(),
261 _ => None,
262 }
263 }
264
265 pub fn typ(&self) -> Option<JsonLdValueTypeRef<'_>> {
267 match self {
268 JsonLdValue::Literal(lit) => match &lit.type_ {
269 Some(JsonLdLiteralType::Json) => Some(JsonLdValueTypeRef::Json),
270 Some(JsonLdLiteralType::Iri(iri)) => Some(JsonLdValueTypeRef::Id(iri)),
271 None => None,
272 },
273 _ => None,
274 }
275 }
276
277 #[inline(always)]
281 pub fn language(&self) -> Option<JsonLdLenient<&LangTag>> {
282 match self {
283 JsonLdValue::LangString(tag) => tag.language(),
284 _ => None,
285 }
286 }
287
288 #[inline(always)]
292 pub fn direction(&self) -> Option<JsonLdDirection> {
293 match self {
294 JsonLdValue::LangString(s) => s.direction(),
295 _ => None,
296 }
297 }
298
299 pub fn is_json(&self) -> bool {
301 matches!(self, Self::Literal(lit) if lit.is_json())
302 }
303
304 pub fn as_json(&self) -> Option<&JsonValue> {
306 match self {
307 Self::Literal(lit) if lit.is_json() => Some(&lit.value),
308 _ => None,
309 }
310 }
311
312 pub fn canonicalize_with(&mut self, buffer: &mut ryu_js::Buffer) {
317 match self {
318 Self::Literal(l) => l.canonicalize_with(buffer),
319 Self::LangString(_) => (),
320 }
321 }
322
323 pub fn canonicalize(&mut self) {
325 let mut buffer = ryu_js::Buffer::new();
326 self.canonicalize_with(&mut buffer)
327 }
328
329 #[inline(always)]
330 pub fn entries(&self) -> JsonLdValueEntries<'_> {
331 match self {
332 Self::Literal(lit) => JsonLdValueEntries {
333 value: Some(JsonLdValueValueEntryRef::Value(&lit.value)),
334 type_: match &lit.type_ {
335 Some(JsonLdLiteralType::Json) => Some(JsonLdValueTypeRef::Json),
336 Some(JsonLdLiteralType::Iri(iri)) => Some(JsonLdValueTypeRef::Id(iri)),
337 None => None,
338 },
339 language: None,
340 direction: None,
341 },
342 Self::LangString(l) => JsonLdValueEntries {
343 value: Some(JsonLdValueValueEntryRef::LangString(l.as_str())),
344 type_: None,
345 language: l.language(),
346 direction: l.direction(),
347 },
348 }
349 }
350}
351
352impl JsonLdVisit for JsonLdValue {
353 fn visit_with(&self, f: &mut impl FnMut(JsonLdObjectRef)) {
354 f(JsonLdObjectRef::Value(self))
355 }
356
357 fn visit_mut_with(&mut self, f: &mut impl FnMut(JsonLdObjectMut)) {
358 f(JsonLdObjectMut::Value(self))
359 }
360}
361
362impl object::AnyJsonLdObject for JsonLdValue {
363 #[inline(always)]
364 fn as_ref(&self) -> object::JsonLdObjectRef<'_> {
365 object::JsonLdObjectRef::Value(self)
366 }
367}
368
369impl From<Literal> for JsonLdValue {
370 fn from(literal: Literal) -> Self {
371 match literal.r#type {
372 rdf_syntax::LiteralType::Any(ty) => {
373 if ty == XSD_BOOLEAN {
374 match literal.value.as_str() {
375 "true" => {
376 return Self::Literal(JsonLdLiteralValue::new(
377 JsonValue::Boolean(true),
378 Some(JsonLdLiteralType::Iri(ty)),
379 ));
380 }
381 "false" => {
382 return Self::Literal(JsonLdLiteralValue::new(
383 JsonValue::Boolean(false),
384 Some(JsonLdLiteralType::Iri(ty)),
385 ));
386 }
387 _ => (),
388 }
389 } else if ty == XSD_INTEGER || ty == XSD_FLOAT {
390 if let Ok(number) = literal.value.parse::<JsonNumberBuf>() {
391 return Self::Literal(JsonLdLiteralValue::new(
392 JsonValue::Number(number),
393 Some(JsonLdLiteralType::Iri(ty)),
394 ));
395 }
396 } else if ty == RDF_JSON
397 && let Ok(json) = json_syntax::from_str(&literal.value)
398 {
399 return Self::Literal(JsonLdLiteralValue::json(json));
400 }
401
402 Self::Literal(JsonLdLiteralValue::new(
403 JsonValue::String(literal.value.into()),
404 Some(JsonLdLiteralType::Iri(ty)),
405 ))
406 }
407 rdf_syntax::LiteralType::LangString(langtag) => {
408 Self::LangString(JsonLdLangString::from_language(literal.value, langtag))
409 }
410 }
411 }
412}
413
414#[derive(Educe)]
415#[educe(Clone, Copy)]
416pub enum JsonLdValueEntryRef<'a> {
417 Value(JsonLdValueValueEntryRef<'a>),
418 Type(JsonLdValueTypeRef<'a>),
419 Language(JsonLdLenient<&'a LangTag>),
420 Direction(JsonLdDirection),
421}
422
423impl<'a> JsonLdValueEntryRef<'a> {
424 pub fn into_key(self) -> JsonLdValueEntryKey {
425 match self {
426 Self::Value(_) => JsonLdValueEntryKey::Value,
427 Self::Type(_) => JsonLdValueEntryKey::Type,
428 Self::Language(_) => JsonLdValueEntryKey::Language,
429 Self::Direction(_) => JsonLdValueEntryKey::Direction,
430 }
431 }
432
433 pub fn key(&self) -> JsonLdValueEntryKey {
434 self.into_key()
435 }
436
437 pub fn into_value(self) -> JsonLdValueEntryValueRef<'a> {
438 match self {
439 Self::Value(v) => JsonLdValueEntryValueRef::Value(v),
440 Self::Type(v) => JsonLdValueEntryValueRef::Type(v),
441 Self::Language(v) => JsonLdValueEntryValueRef::Language(v),
442 Self::Direction(v) => JsonLdValueEntryValueRef::Direction(v),
443 }
444 }
445
446 pub fn value(&self) -> JsonLdValueEntryValueRef<'a> {
447 match self {
448 Self::Value(v) => JsonLdValueEntryValueRef::Value(*v),
449 Self::Type(v) => JsonLdValueEntryValueRef::Type(*v),
450 Self::Language(v) => JsonLdValueEntryValueRef::Language(*v),
451 Self::Direction(v) => JsonLdValueEntryValueRef::Direction(*v),
452 }
453 }
454}
455
456#[derive(Educe)]
457#[educe(Clone, Copy)]
458pub enum JsonLdValueEntryValueRef<'a> {
459 Value(JsonLdValueValueEntryRef<'a>),
460 Type(JsonLdValueTypeRef<'a>),
461 Language(JsonLdLenient<&'a LangTag>),
462 Direction(JsonLdDirection),
463}
464
465pub enum JsonLdValueValueEntryRef<'a> {
466 Value(&'a JsonValue),
467 LangString(&'a str),
468}
469
470impl<'a> Clone for JsonLdValueValueEntryRef<'a> {
471 fn clone(&self) -> Self {
472 *self
473 }
474}
475
476impl<'a> Copy for JsonLdValueValueEntryRef<'a> {}
477
478#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
479pub enum JsonLdValueEntryKey {
480 Value,
481 Type,
482 Language,
483 Direction,
484}
485
486impl JsonLdValueEntryKey {
487 pub fn into_keyword(self) -> JsonLdKeyword {
488 match self {
489 Self::Value => JsonLdKeyword::Value,
490 Self::Type => JsonLdKeyword::Type,
491 Self::Language => JsonLdKeyword::Language,
492 Self::Direction => JsonLdKeyword::Direction,
493 }
494 }
495
496 pub fn as_keyword(&self) -> JsonLdKeyword {
497 self.into_keyword()
498 }
499
500 pub fn into_str(&self) -> &'static str {
501 match self {
502 Self::Value => "@value",
503 Self::Type => "@type",
504 Self::Language => "@language",
505 Self::Direction => "@direction",
506 }
507 }
508
509 pub fn as_str(&self) -> &'static str {
510 self.into_str()
511 }
512}
513
514#[derive(Educe)]
515#[educe(Clone)]
516pub struct JsonLdValueEntries<'a> {
517 value: Option<JsonLdValueValueEntryRef<'a>>,
518 type_: Option<JsonLdValueTypeRef<'a>>,
519 language: Option<JsonLdLenient<&'a LangTag>>,
520 direction: Option<JsonLdDirection>,
521}
522
523impl<'a> Iterator for JsonLdValueEntries<'a> {
524 type Item = JsonLdValueEntryRef<'a>;
525
526 fn size_hint(&self) -> (usize, Option<usize>) {
527 let mut len = 0;
528
529 if self.value.is_some() {
530 len += 1
531 }
532
533 if self.type_.is_some() {
534 len += 1
535 }
536
537 if self.language.is_some() {
538 len += 1
539 }
540
541 if self.direction.is_some() {
542 len += 1
543 }
544
545 (len, Some(len))
546 }
547
548 fn next(&mut self) -> Option<Self::Item> {
549 self.value
550 .take()
551 .map(JsonLdValueEntryRef::Value)
552 .or_else(|| {
553 self.type_
554 .take()
555 .map(JsonLdValueEntryRef::Type)
556 .or_else(|| {
557 self.language
558 .take()
559 .map(JsonLdValueEntryRef::Language)
560 .or_else(|| self.direction.take().map(JsonLdValueEntryRef::Direction))
561 })
562 })
563 }
564}
565
566impl<'a> ExactSizeIterator for JsonLdValueEntries<'a> {}
567
568impl<'a> DoubleEndedIterator for JsonLdValueEntries<'a> {
569 fn next_back(&mut self) -> Option<Self::Item> {
570 self.direction
571 .take()
572 .map(JsonLdValueEntryRef::Direction)
573 .or_else(|| {
574 self.language
575 .take()
576 .map(JsonLdValueEntryRef::Language)
577 .or_else(|| {
578 self.type_
579 .take()
580 .map(JsonLdValueEntryRef::Type)
581 .or_else(|| self.value.take().map(JsonLdValueEntryRef::Value))
582 })
583 })
584 }
585}