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