oxjsonld/
profile.rs

1use std::ops::{BitOr, BitOrAssign};
2
3/// JSON-Ld profile.
4///
5/// This enumeration is non exhaustive. New profiles might be added in the future.
6///
7/// See [JSON-LD specification](https://www.w3.org/TR/json-ld11/#iana-considerations) for a list of profiles.
8#[derive(Eq, PartialEq, Debug, Clone, Copy, Hash)]
9#[non_exhaustive]
10pub enum JsonLdProfile {
11    /// [expanded JSON-LD document form](https://www.w3.org/TR/json-ld11/#dfn-expanded-document-form)
12    Expanded,
13    /// [compacted JSON-LD document form](https://www.w3.org/TR/json-ld11/#dfn-compacted-document-form)
14    Compacted,
15    /// [JSON-LD context document](https://www.w3.org/TR/json-ld11/#dfn-context-document)
16    Context,
17    /// [flattened JSON-LD document form](https://www.w3.org/TR/json-ld11/#dfn-flattened-document-form)
18    Flattened,
19    /// [JSON-LD frame document](https://www.w3.org/TR/json-ld11-framing/#dfn-frame)
20    Frame,
21    /// [framed JSON-LD document form](https://www.w3.org/TR/json-ld11/#dfn-framed-document-form)
22    Framed,
23    /// [streaming JSON-LD document form](https://www.w3.org/TR/json-ld11-streaming/#dfn-streaming-document)
24    Streaming,
25}
26
27impl JsonLdProfile {
28    /// The profile canonical IRI.
29    ///
30    /// ```
31    /// use oxjsonld::JsonLdProfile;
32    ///
33    /// assert_eq!(
34    ///     JsonLdProfile::Expanded.iri(),
35    ///     "http://www.w3.org/ns/json-ld#expanded"
36    /// )
37    /// ```
38    #[inline]
39    pub const fn iri(self) -> &'static str {
40        match self {
41            Self::Expanded => "http://www.w3.org/ns/json-ld#expanded",
42            Self::Compacted => "http://www.w3.org/ns/json-ld#compacted",
43            Self::Context => "http://www.w3.org/ns/json-ld#context",
44            Self::Flattened => "http://www.w3.org/ns/json-ld#flattened",
45            Self::Frame => "http://www.w3.org/ns/json-ld#frame",
46            Self::Framed => "http://www.w3.org/ns/json-ld#framed",
47            Self::Streaming => "http://www.w3.org/ns/json-ld#streaming",
48        }
49    }
50
51    /// Looks for a known profile from an IRI.
52    ///
53    /// Example:
54    /// ```
55    /// use oxjsonld::JsonLdProfile;
56    ///
57    /// assert_eq!(
58    ///     JsonLdProfile::from_iri("http://www.w3.org/ns/json-ld#expanded"),
59    ///     Some(JsonLdProfile::Expanded)
60    /// )
61    /// ```
62    #[inline]
63    pub fn from_iri(iri: &str) -> Option<Self> {
64        match iri {
65            "http://www.w3.org/ns/json-ld#expanded" => Some(Self::Expanded),
66            "http://www.w3.org/ns/json-ld#compacted" => Some(Self::Compacted),
67            "http://www.w3.org/ns/json-ld#context" => Some(Self::Context),
68            "http://www.w3.org/ns/json-ld#flattened" => Some(Self::Flattened),
69            "http://www.w3.org/ns/json-ld#frame" => Some(Self::Frame),
70            "http://www.w3.org/ns/json-ld#framed" => Some(Self::Framed),
71            "http://www.w3.org/ns/json-ld#streaming" => Some(Self::Streaming),
72            _ => None,
73        }
74    }
75
76    #[inline]
77    const fn to_bit(self) -> u64 {
78        match self {
79            JsonLdProfile::Expanded => 1,
80            JsonLdProfile::Compacted => 2,
81            JsonLdProfile::Context => 4,
82            JsonLdProfile::Flattened => 8,
83            JsonLdProfile::Frame => 16,
84            JsonLdProfile::Framed => 32,
85            JsonLdProfile::Streaming => 64,
86        }
87    }
88}
89
90/// Set of JSON-Ld profiles.
91///
92/// ```
93/// use oxjsonld::{JsonLdProfile, JsonLdProfileSet};
94/// let mut profile_set = JsonLdProfileSet::empty();
95/// profile_set |= JsonLdProfile::Expanded;
96/// profile_set |= JsonLdProfile::Streaming;
97/// assert!(profile_set.contains(JsonLdProfile::Streaming));
98/// assert_eq!(
99///     profile_set.into_iter().collect::<Vec<_>>(),
100///     vec![JsonLdProfile::Expanded, JsonLdProfile::Streaming]
101/// );
102/// ```
103#[derive(Eq, PartialEq, Debug, Clone, Copy, Hash, Default)]
104pub struct JsonLdProfileSet {
105    value: u64,
106}
107
108impl JsonLdProfileSet {
109    #[inline]
110    pub const fn empty() -> Self {
111        Self { value: 0 }
112    }
113
114    #[inline]
115    pub const fn from_profile(profile: JsonLdProfile) -> Self {
116        Self {
117            value: profile.to_bit(),
118        }
119    }
120
121    /// Checks if this profile list contains the given profile.
122    #[inline]
123    pub const fn contains(self, profile: JsonLdProfile) -> bool {
124        self.value & profile.to_bit() != 0
125    }
126}
127
128impl From<JsonLdProfile> for JsonLdProfileSet {
129    #[inline]
130    fn from(profile: JsonLdProfile) -> Self {
131        Self {
132            value: profile.to_bit(),
133        }
134    }
135}
136
137impl IntoIterator for JsonLdProfileSet {
138    type Item = JsonLdProfile;
139    type IntoIter = JsonLdProfileBagIter;
140
141    #[inline]
142    fn into_iter(self) -> JsonLdProfileBagIter {
143        JsonLdProfileBagIter {
144            set: self,
145            possible_values: [
146                JsonLdProfile::Expanded,
147                JsonLdProfile::Compacted,
148                JsonLdProfile::Context,
149                JsonLdProfile::Flattened,
150                JsonLdProfile::Frame,
151                JsonLdProfile::Framed,
152                JsonLdProfile::Streaming,
153            ]
154            .into_iter(),
155        }
156    }
157}
158
159/// Iterator output of [`JsonLdProfileSet::into_iter`].
160pub struct JsonLdProfileBagIter {
161    set: JsonLdProfileSet,
162    possible_values: std::array::IntoIter<JsonLdProfile, 7>,
163}
164
165impl Iterator for JsonLdProfileBagIter {
166    type Item = JsonLdProfile;
167
168    #[inline]
169    fn next(&mut self) -> Option<JsonLdProfile> {
170        loop {
171            let possible_value = self.possible_values.next()?;
172            if self.set.contains(possible_value) {
173                return Some(possible_value);
174            }
175        }
176    }
177
178    #[inline]
179    fn size_hint(&self) -> (usize, Option<usize>) {
180        let size = self.set.value.count_ones().try_into().unwrap();
181        (size, Some(size))
182    }
183}
184
185impl BitOr for JsonLdProfileSet {
186    type Output = Self;
187
188    #[inline]
189    fn bitor(self, rhs: Self) -> Self {
190        Self {
191            value: self.value | rhs.value,
192        }
193    }
194}
195
196impl BitOr<JsonLdProfile> for JsonLdProfileSet {
197    type Output = JsonLdProfileSet;
198
199    #[inline]
200    fn bitor(self, rhs: JsonLdProfile) -> JsonLdProfileSet {
201        self | JsonLdProfileSet::from(rhs)
202    }
203}
204
205impl BitOr<JsonLdProfileSet> for JsonLdProfile {
206    type Output = JsonLdProfileSet;
207
208    #[inline]
209    fn bitor(self, rhs: JsonLdProfileSet) -> JsonLdProfileSet {
210        JsonLdProfileSet::from(self) | rhs
211    }
212}
213
214impl BitOr for JsonLdProfile {
215    type Output = JsonLdProfileSet;
216
217    #[inline]
218    fn bitor(self, rhs: Self) -> JsonLdProfileSet {
219        JsonLdProfileSet::from(self) | JsonLdProfileSet::from(rhs)
220    }
221}
222
223impl BitOrAssign for JsonLdProfileSet {
224    #[inline]
225    fn bitor_assign(&mut self, rhs: Self) {
226        self.value |= rhs.value;
227    }
228}
229
230impl BitOrAssign<JsonLdProfile> for JsonLdProfileSet {
231    #[inline]
232    fn bitor_assign(&mut self, rhs: JsonLdProfile) {
233        *self |= JsonLdProfileSet::from(rhs);
234    }
235}