json_ld/syntax/
container.rs1use std::str::FromStr;
2
3use crate::context::JsonLdContainer;
4use crate::syntax::context::JsonLdContextTypeContainer;
5
6use super::JsonLdKeyword;
7
8#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
9#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
10pub enum JsonLdContainerItem {
11 #[cfg_attr(feature = "serde", serde(rename = "@graph"))]
12 Graph,
13
14 #[cfg_attr(feature = "serde", serde(rename = "@id"))]
15 Id,
16
17 #[cfg_attr(feature = "serde", serde(rename = "@index"))]
18 Index,
19
20 #[cfg_attr(feature = "serde", serde(rename = "@language"))]
21 Language,
22
23 #[cfg_attr(feature = "serde", serde(rename = "@list"))]
24 List,
25
26 #[cfg_attr(feature = "serde", serde(rename = "@set"))]
27 Set,
28
29 #[cfg_attr(feature = "serde", serde(rename = "@type"))]
30 Type,
31}
32
33impl JsonLdContainerItem {
34 pub fn into_keyword(self) -> JsonLdKeyword {
35 self.into()
36 }
37
38 pub fn keyword(&self) -> JsonLdKeyword {
39 self.into_keyword()
40 }
41
42 pub fn as_str(&self) -> &'static str {
43 self.into_keyword().into_str()
44 }
45}
46
47impl std::fmt::Display for JsonLdContainerItem {
48 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
49 f.write_str(self.as_str())
50 }
51}
52
53#[derive(Debug, Clone, Copy, thiserror::Error)]
54#[error("Invalid `@container` item: `{0}`")]
55pub struct InvalidJsonLdContainerItem<T = String>(pub T);
56
57impl<T: ?Sized + ToOwned> InvalidJsonLdContainerItem<&T> {
58 pub fn into_owned(self) -> InvalidJsonLdContainerItem<T::Owned> {
59 InvalidJsonLdContainerItem(self.0.to_owned())
60 }
61}
62
63impl FromStr for JsonLdContainerItem {
64 type Err = InvalidJsonLdContainerItem;
65
66 fn from_str(s: &str) -> Result<Self, Self::Err> {
67 s.try_into().map_err(InvalidJsonLdContainerItem::into_owned)
68 }
69}
70
71impl<'a> TryFrom<&'a str> for JsonLdContainerItem {
72 type Error = InvalidJsonLdContainerItem<&'a str>;
73
74 fn try_from(str: &'a str) -> Result<JsonLdContainerItem, InvalidJsonLdContainerItem<&'a str>> {
75 use JsonLdContainerItem::*;
76 match str {
77 "@graph" => Ok(Graph),
78 "@id" => Ok(Id),
79 "@index" => Ok(Index),
80 "@language" => Ok(Language),
81 "@list" => Ok(List),
82 "@set" => Ok(Set),
83 "@type" => Ok(Type),
84 _ => Err(InvalidJsonLdContainerItem(str)),
85 }
86 }
87}
88
89impl TryFrom<JsonLdKeyword> for JsonLdContainerItem {
90 type Error = JsonLdKeyword;
91
92 fn try_from(k: JsonLdKeyword) -> Result<JsonLdContainerItem, JsonLdKeyword> {
93 use JsonLdContainerItem::*;
94 match k {
95 JsonLdKeyword::Graph => Ok(Graph),
96 JsonLdKeyword::Id => Ok(Id),
97 JsonLdKeyword::Index => Ok(Index),
98 JsonLdKeyword::Language => Ok(Language),
99 JsonLdKeyword::List => Ok(List),
100 JsonLdKeyword::Set => Ok(Set),
101 JsonLdKeyword::Type => Ok(Type),
102 k => Err(k),
103 }
104 }
105}
106
107impl From<JsonLdContainerItem> for JsonLdKeyword {
108 fn from(c: JsonLdContainerItem) -> JsonLdKeyword {
109 use JsonLdContainerItem::*;
110 match c {
111 Graph => JsonLdKeyword::Graph,
112 Id => JsonLdKeyword::Id,
113 Index => JsonLdKeyword::Index,
114 Language => JsonLdKeyword::Language,
115 List => JsonLdKeyword::List,
116 Set => JsonLdKeyword::Set,
117 Type => JsonLdKeyword::Type,
118 }
119 }
120}
121
122#[derive(Clone, PartialEq, Eq, Hash, Debug)]
127#[cfg_attr(
128 feature = "serde",
129 derive(serde::Serialize, serde::Deserialize),
130 serde(untagged)
131)]
132pub enum JsonLdContainerValue {
133 Null,
135
136 Item(JsonLdContainerItem),
138
139 Array(Vec<JsonLdContainerItem>),
141}
142
143impl JsonLdContainerValue {
144 pub fn is_array(&self) -> bool {
146 matches!(self, Self::Array(_))
147 }
148
149 pub fn to_container(&self) -> Result<JsonLdContainer, UnexpectedJsonLdContainerItem> {
151 match self {
152 Self::Null => Ok(JsonLdContainer::Null),
153 Self::Item(item) => Ok((*item).into()),
154 Self::Array(items) => {
155 JsonLdContainer::from(items.iter()).map_err(UnexpectedJsonLdContainerItem)
156 }
157 }
158 }
159}
160
161#[derive(Debug, Clone, Copy, thiserror::Error)]
164#[error("unexpected `@container` item: `{0}`")]
165pub struct UnexpectedJsonLdContainerItem(pub JsonLdContainerItem);
166
167impl From<JsonLdContextTypeContainer> for JsonLdContainerValue {
168 fn from(c: JsonLdContextTypeContainer) -> Self {
169 match c {
170 JsonLdContextTypeContainer::Set => JsonLdContainerValue::Item(JsonLdContainerItem::Set),
171 }
172 }
173}