1pub use jsonld_syntax::ContainerKind;
2use jsonld_syntax::{Nullable, context::definition::TypeContainer};
3
4#[derive(Debug, Clone, Copy, thiserror::Error)]
10#[error("invalid container")]
11pub struct InvalidContainer;
12
13#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
14pub enum Container {
17 None,
19
20 Graph,
22 Id,
24 Index,
27 Language,
30 List,
32 Set,
34 Type,
36
37 GraphSet,
39 GraphId,
41 GraphIndex,
43 IdSet,
45 IndexSet,
47 LanguageSet,
49 SetType,
51
52 GraphIdSet,
54 GraphIndexSet,
56}
57
58impl Default for Container {
59 fn default() -> Self {
60 Self::new()
61 }
62}
63
64impl Container {
65 #[must_use]
67 pub fn new() -> Container {
68 Container::None
69 }
70
71 pub fn from_syntax(r: Nullable<&jsonld_syntax::Container>) -> Result<Self, InvalidContainer> {
77 match r {
78 Nullable::Null => Ok(Self::None),
79 Nullable::Some(jsonld_syntax::Container::One(c)) => Ok((*c).into()),
80 Nullable::Some(jsonld_syntax::Container::Many(m)) => {
81 let mut container = Container::new();
82
83 for t in m {
84 if !container.add(*t) {
85 return Err(InvalidContainer);
86 }
87 }
88
89 Ok(container)
90 }
91 }
92 }
93
94 pub fn from<'a, I: IntoIterator<Item = &'a ContainerKind>>(iter: I) -> Result<Container, ContainerKind> {
100 let mut container = Container::new();
101 for item in iter {
102 if !container.add(*item) {
103 return Err(*item);
104 }
105 }
106
107 Ok(container)
108 }
109
110 #[must_use]
112 pub fn as_slice(&self) -> &[ContainerKind] {
113 use Container::{
114 Graph,
115 GraphId,
116 GraphIdSet,
117 GraphIndex,
118 GraphIndexSet,
119 GraphSet,
120 Id,
121 IdSet,
122 Index,
123 IndexSet,
124 Language,
125 LanguageSet,
126 List,
127 None,
128 Set,
129 SetType,
130 Type,
131 };
132 match self {
133 None => &[],
134 Graph => &[ContainerKind::Graph],
135 Id => &[ContainerKind::Id],
136 Index => &[ContainerKind::Index],
137 Language => &[ContainerKind::Language],
138 List => &[ContainerKind::List],
139 Set => &[ContainerKind::Set],
140 Type => &[ContainerKind::Type],
141 GraphSet => &[ContainerKind::Graph, ContainerKind::Set],
142 GraphId => &[ContainerKind::Graph, ContainerKind::Id],
143 GraphIndex => &[ContainerKind::Graph, ContainerKind::Index],
144 IdSet => &[ContainerKind::Id, ContainerKind::Set],
145 IndexSet => &[ContainerKind::Index, ContainerKind::Set],
146 LanguageSet => &[ContainerKind::Language, ContainerKind::Set],
147 SetType => &[ContainerKind::Type, ContainerKind::Set],
148 GraphIdSet => &[ContainerKind::Graph, ContainerKind::Id, ContainerKind::Set],
149 GraphIndexSet => &[ContainerKind::Graph, ContainerKind::Index, ContainerKind::Set],
150 }
151 }
152
153 pub fn iter(&self) -> impl Iterator<Item = &ContainerKind> {
155 self.as_slice().iter()
156 }
157
158 #[must_use]
160 pub fn len(&self) -> usize {
161 self.as_slice().len()
162 }
163
164 #[must_use]
166 pub fn is_empty(&self) -> bool {
167 matches!(self, Container::None)
168 }
169
170 #[must_use]
172 pub fn contains(&self, c: ContainerKind) -> bool {
173 self.as_slice().contains(&c)
174 }
175
176 #[must_use]
179 pub fn with(&self, c: ContainerKind) -> Option<Container> {
180 let new_container = match (self, c) {
181 (Container::None, c) => c.into(),
182 (Container::Graph, ContainerKind::Graph) => *self,
183 (Container::Graph, ContainerKind::Set) => Container::GraphSet,
184 (Container::Graph, ContainerKind::Id) => Container::GraphId,
185 (Container::Graph, ContainerKind::Index) => Container::GraphIndex,
186 (Container::Id, ContainerKind::Id) => *self,
187 (Container::Id, ContainerKind::Graph) => Container::GraphId,
188 (Container::Id, ContainerKind::Set) => Container::IdSet,
189 (Container::Index, ContainerKind::Index) => *self,
190 (Container::Index, ContainerKind::Graph) => Container::GraphIndex,
191 (Container::Index, ContainerKind::Set) => Container::IndexSet,
192 (Container::Language, ContainerKind::Language) => *self,
193 (Container::Language, ContainerKind::Set) => Container::LanguageSet,
194 (Container::List, ContainerKind::List) => *self,
195 (Container::Set, ContainerKind::Set) => *self,
196 (Container::Set, ContainerKind::Graph) => Container::GraphSet,
197 (Container::Set, ContainerKind::Id) => Container::IdSet,
198 (Container::Set, ContainerKind::Index) => Container::IndexSet,
199 (Container::Set, ContainerKind::Language) => Container::LanguageSet,
200 (Container::Set, ContainerKind::Type) => Container::SetType,
201 (Container::Type, ContainerKind::Type) => *self,
202 (Container::Type, ContainerKind::Set) => Container::SetType,
203 (Container::GraphSet, ContainerKind::Graph) => *self,
204 (Container::GraphSet, ContainerKind::Set) => *self,
205 (Container::GraphSet, ContainerKind::Id) => Container::GraphIdSet,
206 (Container::GraphSet, ContainerKind::Index) => Container::GraphIndexSet,
207 (Container::GraphId, ContainerKind::Graph) => *self,
208 (Container::GraphId, ContainerKind::Id) => *self,
209 (Container::GraphId, ContainerKind::Set) => Container::GraphIdSet,
210 (Container::GraphIndex, ContainerKind::Graph) => *self,
211 (Container::GraphIndex, ContainerKind::Index) => *self,
212 (Container::GraphIndex, ContainerKind::Set) => Container::GraphIndexSet,
213 (Container::IdSet, ContainerKind::Id) => *self,
214 (Container::IdSet, ContainerKind::Set) => *self,
215 (Container::IdSet, ContainerKind::Graph) => Container::GraphIdSet,
216 (Container::IndexSet, ContainerKind::Index) => *self,
217 (Container::IndexSet, ContainerKind::Set) => *self,
218 (Container::IndexSet, ContainerKind::Graph) => Container::GraphIndexSet,
219 (Container::LanguageSet, ContainerKind::Language) => *self,
220 (Container::LanguageSet, ContainerKind::Set) => *self,
221 (Container::SetType, ContainerKind::Set) => *self,
222 (Container::SetType, ContainerKind::Type) => *self,
223 (Container::GraphIdSet, ContainerKind::Graph) => *self,
224 (Container::GraphIdSet, ContainerKind::Id) => *self,
225 (Container::GraphIdSet, ContainerKind::Set) => *self,
226 (Container::GraphIndexSet, ContainerKind::Graph) => *self,
227 (Container::GraphIndexSet, ContainerKind::Index) => *self,
228 (Container::GraphIndexSet, ContainerKind::Set) => *self,
229 _ => return None,
230 };
231
232 Some(new_container)
233 }
234
235 pub fn add(&mut self, c: ContainerKind) -> bool {
239 match self.with(c) {
240 Some(container) => {
241 *self = container;
242 true
243 }
244 None => false,
245 }
246 }
247
248 #[must_use]
252 pub fn into_syntax(self) -> Option<jsonld_syntax::Container> {
253 let slice = self.as_slice();
254
255 match slice.len() {
256 0 => None,
257 1 => Some(jsonld_syntax::Container::One(slice[0])),
258 _ => Some(jsonld_syntax::Container::Many(slice.to_vec())),
259 }
260 }
261}
262
263impl From<ContainerKind> for Container {
264 fn from(c: ContainerKind) -> Self {
265 match c {
266 ContainerKind::Graph => Self::Graph,
267 ContainerKind::Id => Self::Id,
268 ContainerKind::Index => Self::Index,
269 ContainerKind::Language => Self::Language,
270 ContainerKind::List => Self::List,
271 ContainerKind::Set => Self::Set,
272 ContainerKind::Type => Self::Type,
273 }
274 }
275}
276
277impl From<TypeContainer> for Container {
278 fn from(c: TypeContainer) -> Self {
279 match c {
280 TypeContainer::Set => Container::Set,
281 }
282 }
283}