json_ld_core/
container.rs

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	// Empty container
9	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}