json_ld_core_next/
container.rs

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	// 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(
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}