1pub use json_ld_syntax::ContainerKind;
2use json_ld_syntax::{context::definition::TypeContainer, Nullable};
3
4pub struct InvalidContainer;
5
6#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
7pub enum Container {
8 None,
10
11 Graph,
12 Id,
13 Index,
14 Language,
15 List,
16 Set,
17 Type,
18
19 GraphSet,
20 GraphId,
21 GraphIndex,
22 IdSet,
23 IndexSet,
24 LanguageSet,
25 SetType,
26
27 GraphIdSet,
28 GraphIndexSet,
29}
30
31impl Default for Container {
32 fn default() -> Self {
33 Self::new()
34 }
35}
36
37impl Container {
38 pub fn new() -> Container {
39 Container::None
40 }
41
42 pub fn from_syntax(r: Nullable<&json_ld_syntax::Container>) -> Result<Self, InvalidContainer> {
43 match r {
44 Nullable::Null => Ok(Self::None),
45 Nullable::Some(json_ld_syntax::Container::One(c)) => Ok((*c).into()),
46 Nullable::Some(json_ld_syntax::Container::Many(m)) => {
47 let mut container = Container::new();
48
49 for t in m {
50 if !container.add(*t) {
51 return Err(InvalidContainer);
52 }
53 }
54
55 Ok(container)
56 }
57 }
58 }
59
60 pub fn from<'a, I: IntoIterator<Item = &'a ContainerKind>>(
61 iter: I,
62 ) -> Result<Container, ContainerKind> {
63 let mut container = Container::new();
64 for item in iter {
65 if !container.add(*item) {
66 return Err(*item);
67 }
68 }
69
70 Ok(container)
71 }
72
73 pub fn as_slice(&self) -> &[ContainerKind] {
74 use Container::*;
75 match self {
76 None => &[],
77 Graph => &[ContainerKind::Graph],
78 Id => &[ContainerKind::Id],
79 Index => &[ContainerKind::Index],
80 Language => &[ContainerKind::Language],
81 List => &[ContainerKind::List],
82 Set => &[ContainerKind::Set],
83 Type => &[ContainerKind::Type],
84 GraphSet => &[ContainerKind::Graph, ContainerKind::Set],
85 GraphId => &[ContainerKind::Graph, ContainerKind::Id],
86 GraphIndex => &[ContainerKind::Graph, ContainerKind::Index],
87 IdSet => &[ContainerKind::Id, ContainerKind::Set],
88 IndexSet => &[ContainerKind::Index, ContainerKind::Set],
89 LanguageSet => &[ContainerKind::Language, ContainerKind::Set],
90 SetType => &[ContainerKind::Type, ContainerKind::Set],
91 GraphIdSet => &[ContainerKind::Graph, ContainerKind::Id, ContainerKind::Set],
92 GraphIndexSet => &[
93 ContainerKind::Graph,
94 ContainerKind::Index,
95 ContainerKind::Set,
96 ],
97 }
98 }
99
100 pub fn iter(&self) -> impl Iterator<Item = &ContainerKind> {
101 self.as_slice().iter()
102 }
103
104 pub fn len(&self) -> usize {
105 self.as_slice().len()
106 }
107
108 pub fn is_empty(&self) -> bool {
109 matches!(self, Container::None)
110 }
111
112 pub fn contains(&self, c: ContainerKind) -> bool {
113 self.as_slice().contains(&c)
114 }
115
116 pub fn with(&self, c: ContainerKind) -> Option<Container> {
117 let new_container = match (self, c) {
118 (Container::None, c) => c.into(),
119 (Container::Graph, ContainerKind::Graph) => *self,
120 (Container::Graph, ContainerKind::Set) => Container::GraphSet,
121 (Container::Graph, ContainerKind::Id) => Container::GraphId,
122 (Container::Graph, ContainerKind::Index) => Container::GraphIndex,
123 (Container::Id, ContainerKind::Id) => *self,
124 (Container::Id, ContainerKind::Graph) => Container::GraphId,
125 (Container::Id, ContainerKind::Set) => Container::IdSet,
126 (Container::Index, ContainerKind::Index) => *self,
127 (Container::Index, ContainerKind::Graph) => Container::GraphIndex,
128 (Container::Index, ContainerKind::Set) => Container::IndexSet,
129 (Container::Language, ContainerKind::Language) => *self,
130 (Container::Language, ContainerKind::Set) => Container::LanguageSet,
131 (Container::List, ContainerKind::List) => *self,
132 (Container::Set, ContainerKind::Set) => *self,
133 (Container::Set, ContainerKind::Graph) => Container::GraphSet,
134 (Container::Set, ContainerKind::Id) => Container::IdSet,
135 (Container::Set, ContainerKind::Index) => Container::IndexSet,
136 (Container::Set, ContainerKind::Language) => Container::LanguageSet,
137 (Container::Set, ContainerKind::Type) => Container::SetType,
138 (Container::Type, ContainerKind::Type) => *self,
139 (Container::Type, ContainerKind::Set) => Container::SetType,
140 (Container::GraphSet, ContainerKind::Graph) => *self,
141 (Container::GraphSet, ContainerKind::Set) => *self,
142 (Container::GraphSet, ContainerKind::Id) => Container::GraphIdSet,
143 (Container::GraphSet, ContainerKind::Index) => Container::GraphIdSet,
144 (Container::GraphId, ContainerKind::Graph) => *self,
145 (Container::GraphId, ContainerKind::Id) => *self,
146 (Container::GraphId, ContainerKind::Set) => Container::GraphIdSet,
147 (Container::GraphIndex, ContainerKind::Graph) => *self,
148 (Container::GraphIndex, ContainerKind::Index) => *self,
149 (Container::GraphIndex, ContainerKind::Set) => Container::GraphIndexSet,
150 (Container::IdSet, ContainerKind::Id) => *self,
151 (Container::IdSet, ContainerKind::Set) => *self,
152 (Container::IdSet, ContainerKind::Graph) => Container::GraphIdSet,
153 (Container::IndexSet, ContainerKind::Index) => *self,
154 (Container::IndexSet, ContainerKind::Set) => *self,
155 (Container::IndexSet, ContainerKind::Graph) => Container::GraphIndexSet,
156 (Container::LanguageSet, ContainerKind::Language) => *self,
157 (Container::LanguageSet, ContainerKind::Set) => *self,
158 (Container::SetType, ContainerKind::Set) => *self,
159 (Container::SetType, ContainerKind::Type) => *self,
160 (Container::GraphIdSet, ContainerKind::Graph) => *self,
161 (Container::GraphIdSet, ContainerKind::Id) => *self,
162 (Container::GraphIdSet, ContainerKind::Set) => *self,
163 (Container::GraphIndexSet, ContainerKind::Graph) => *self,
164 (Container::GraphIndexSet, ContainerKind::Index) => *self,
165 (Container::GraphIndexSet, ContainerKind::Set) => *self,
166 _ => return None,
167 };
168
169 Some(new_container)
170 }
171
172 pub fn add(&mut self, c: ContainerKind) -> bool {
173 match self.with(c) {
174 Some(container) => {
175 *self = container;
176 true
177 }
178 None => false,
179 }
180 }
181
182 pub fn into_syntax(self) -> Option<json_ld_syntax::Container> {
183 let slice = self.as_slice();
184
185 match slice.len() {
186 0 => None,
187 1 => Some(json_ld_syntax::Container::One(slice[0])),
188 _ => Some(json_ld_syntax::Container::Many(slice.to_vec())),
189 }
190 }
191}
192
193impl From<ContainerKind> for Container {
194 fn from(c: ContainerKind) -> Self {
195 match c {
196 ContainerKind::Graph => Self::Graph,
197 ContainerKind::Id => Self::Id,
198 ContainerKind::Index => Self::Index,
199 ContainerKind::Language => Self::Language,
200 ContainerKind::List => Self::List,
201 ContainerKind::Set => Self::Set,
202 ContainerKind::Type => Self::Type,
203 }
204 }
205}
206
207impl From<TypeContainer> for Container {
208 fn from(c: TypeContainer) -> Self {
209 match c {
210 TypeContainer::Set => Container::Set,
211 }
212 }
213}