1use std::rc::Rc;
2
3use ahash::{HashMap, HashMapExt};
4use xee_schema_type::Xs;
5use xee_xpath_ast::ast;
6use xot::Xot;
7
8use crate::{atomic, context, error, sequence, string};
9
10#[derive(Debug, Clone, PartialEq)]
12pub enum Map {
13 Empty(EmptyMap),
14 One(OneMap),
15 Many(ManyMap),
16}
17
18impl Map {
19 pub(crate) fn new(entries: Vec<(atomic::Atomic, sequence::Sequence)>) -> error::Result<Self> {
20 match entries.len() {
21 0 => Ok(Self::Empty(EmptyMap)),
22 1 => {
23 let (key, value) = entries.into_iter().next().unwrap();
24 let map_key = atomic::MapKey::new(key.clone())?;
25 Ok(Self::One(
26 OneMapValue {
27 map_key,
28 key_value: (key, value),
29 }
30 .into(),
31 ))
32 }
33 _ => Ok(Self::Many(ManyMap::new(entries)?)),
34 }
35 }
36
37 fn from_map(map: HashMap<atomic::MapKey, (atomic::Atomic, sequence::Sequence)>) -> Self {
38 match map.len() {
39 0 => Self::Empty(EmptyMap),
40 1 => {
41 let (map_key, (key, value)) = map.into_iter().next().unwrap();
42 Self::One(
43 OneMapValue {
44 map_key,
45 key_value: (key, value),
46 }
47 .into(),
48 )
49 }
50 _ => Self::Many(ManyMap(Rc::new(map))),
51 }
52 }
53
54 pub(crate) fn combine(
55 maps: impl Iterator<Item = error::Result<Map>>,
56 combine: impl Fn(sequence::Sequence, sequence::Sequence) -> error::Result<sequence::Sequence>,
57 ) -> error::Result<Map> {
58 let mut result = HashMap::new();
59 for map in maps {
60 for (map_key, (key, value)) in map?.full_entries() {
61 let map_key = map_key.clone();
62 let entry = result.remove(&map_key);
63 let value = if let Some((_, a)) = entry {
64 combine(a, value.clone())?
65 } else {
66 value.clone()
67 };
68 result.insert(map_key, (key.clone(), value));
69 }
70 }
71 Ok(Map::from_map(result))
72 }
73
74 pub(crate) fn len(&self) -> usize {
75 match self {
76 Map::Empty(map) => map.len(),
77 Map::One(map) => map.len(),
78 Map::Many(map) => map.len(),
79 }
80 }
81 pub(crate) fn is_empty(&self) -> bool {
82 match self {
83 Map::Empty(map) => map.is_empty(),
84 Map::One(map) => map.is_empty(),
85 Map::Many(map) => map.is_empty(),
86 }
87 }
88 pub(crate) fn get(&self, key: &atomic::Atomic) -> Option<&sequence::Sequence> {
89 match self {
90 Map::Empty(map) => map.get(key),
91 Map::One(map) => map.get(key),
92 Map::Many(map) => map.get(key),
93 }
94 }
95 pub(crate) fn keys(&self) -> Box<dyn Iterator<Item = &atomic::Atomic> + '_> {
96 match self {
97 Map::Empty(map) => Box::new(map.keys()),
98 Map::One(map) => Box::new(map.keys()),
99 Map::Many(map) => Box::new(map.keys()),
100 }
101 }
102 pub(crate) fn entries(
103 &self,
104 ) -> Box<dyn Iterator<Item = (&atomic::Atomic, &sequence::Sequence)> + '_> {
105 match self {
106 Map::Empty(map) => Box::new(map.entries()),
107 Map::One(map) => Box::new(map.entries()),
108 Map::Many(map) => Box::new(map.entries()),
109 }
110 }
111
112 pub(crate) fn map_keys(&self) -> Box<dyn Iterator<Item = &'_ atomic::MapKey> + '_> {
113 match self {
114 Map::Empty(map) => Box::new(map.map_keys()),
115 Map::One(map) => Box::new(map.map_keys()),
116 Map::Many(map) => Box::new(map.map_keys()),
117 }
118 }
119
120 pub(crate) fn map_key_entries(
121 &self,
122 ) -> Box<dyn Iterator<Item = (&atomic::MapKey, &sequence::Sequence)> + '_> {
123 match self {
124 Map::Empty(map) => Box::new(map.map_key_entries()),
125 Map::One(map) => Box::new(map.map_key_entries()),
126 Map::Many(map) => Box::new(map.map_key_entries()),
127 }
128 }
129
130 pub(crate) fn full_entries(
131 &self,
132 ) -> Box<dyn Iterator<Item = (&atomic::MapKey, &(atomic::Atomic, sequence::Sequence))> + '_>
133 {
134 match self {
135 Map::Empty(map) => Box::new(map.full_entries()),
136 Map::One(map) => Box::new(map.full_entries()),
137 Map::Many(map) => Box::new(map.full_entries()),
138 }
139 }
140
141 pub(crate) fn get_as_type(
142 &self,
143 key: &atomic::Atomic,
144 occurrence: ast::Occurrence,
145 atomic_type: Xs,
146 static_context: &context::StaticContext,
147 xot: &Xot,
148 ) -> error::Result<Option<sequence::Sequence>> {
149 match self {
150 Map::Empty(map) => map.get_as_type(key, occurrence, atomic_type, static_context, xot),
151 Map::One(map) => map.get_as_type(key, occurrence, atomic_type, static_context, xot),
152 Map::Many(map) => map.get_as_type(key, occurrence, atomic_type, static_context, xot),
153 }
154 }
155
156 pub(crate) fn deep_equal(
157 &self,
158 other: &Map,
159 collation: &string::Collation,
160 default_offset: chrono::FixedOffset,
161 xot: &Xot,
162 ) -> error::Result<bool> {
163 match (self, other) {
164 (Map::Empty(_), Map::Empty(_)) => Ok(true),
165 (Map::Empty(_), _) => Ok(false),
166 (_, Map::Empty(_)) => Ok(false),
167 (Map::One(map), Map::One(other)) => {
168 map.deep_equal(other, collation, default_offset, xot)
169 }
170 (Map::One(map), Map::Many(other)) => {
171 map.deep_equal(other, collation, default_offset, xot)
172 }
173 (Map::Many(map), Map::Many(other)) => {
174 map.deep_equal(other, collation, default_offset, xot)
175 }
176 (Map::Many(map), Map::One(other)) => {
177 map.deep_equal(other, collation, default_offset, xot)
178 }
179 }
180 }
181
182 pub fn display_representation(&self, xot: &Xot, context: &context::DynamicContext) -> String {
183 match self {
184 Map::Empty(map) => map.display_representation(xot, context),
185 Map::One(map) => map.display_representation(xot, context),
186 Map::Many(map) => map.display_representation(xot, context),
187 }
188 }
189
190 pub(crate) fn put(
191 &self,
192 key: atomic::Atomic,
193 value: &sequence::Sequence,
194 ) -> error::Result<Self> {
195 Ok(match self {
196 Map::Empty(_) => {
197 let map_key = atomic::MapKey::new(key.clone())?;
199 Map::One(
200 OneMapValue {
201 map_key,
202 key_value: (key, value.clone()),
203 }
204 .into(),
205 )
206 }
207 Map::One(one) => {
208 let map_key = atomic::MapKey::new(key.clone())?;
209 if one.0.map_key == map_key {
210 Map::One(
212 OneMapValue {
213 map_key,
214 key_value: (key.clone(), value.clone()),
215 }
216 .into(),
217 )
218 } else {
219 let entries = vec![
221 (one.0.key_value.0.clone(), one.0.key_value.1.clone()),
222 (key, value.clone()),
223 ];
224 Map::Many(ManyMap::try_from(entries)?)
225 }
226 }
227 Map::Many(map) => Map::Many(map.put(key, value)?),
229 })
230 }
231
232 pub(crate) fn remove_keys(
233 &self,
234 keys: impl Iterator<Item = error::Result<atomic::Atomic>>,
235 ) -> error::Result<Self> {
236 Ok(match self {
237 Map::Empty(_) => Map::Empty(EmptyMap),
238 Map::One(map) => {
239 for key in keys {
240 let map_key = atomic::MapKey::new(key?.clone())?;
241 if map.0.map_key == map_key {
242 return Ok(Map::Empty(EmptyMap));
243 }
244 }
245 Map::One(map.clone())
246 }
247 Map::Many(map) => Map::from_map(map.remove_keys(keys)?),
248 })
249 }
250}
251
252pub(crate) trait Mappable {
253 fn len(&self) -> usize;
254 fn is_empty(&self) -> bool;
255
256 fn get_by_map_key(&self, map_key: &atomic::MapKey) -> Option<&sequence::Sequence>;
258
259 fn map_keys(&self) -> impl Iterator<Item = &'_ atomic::MapKey> + '_;
261
262 fn map_key_entries(&self) -> impl Iterator<Item = (&atomic::MapKey, &sequence::Sequence)> + '_;
264
265 fn full_entries(
266 &self,
267 ) -> impl Iterator<Item = (&atomic::MapKey, &(atomic::Atomic, sequence::Sequence))> + '_;
268
269 fn get(&self, key: &atomic::Atomic) -> Option<&sequence::Sequence> {
271 let map_key = atomic::MapKey::new(key.clone()).ok()?;
272 self.get_by_map_key(&map_key)
273 }
274
275 fn keys(&self) -> impl Iterator<Item = &atomic::Atomic> + '_;
277
278 fn entries(&self) -> impl Iterator<Item = (&atomic::Atomic, &sequence::Sequence)> + '_;
280
281 fn get_as_type(
283 &self,
284 key: &atomic::Atomic,
285 occurrence: ast::Occurrence,
286 atomic_type: Xs,
287 static_context: &context::StaticContext,
288 xot: &Xot,
289 ) -> error::Result<Option<sequence::Sequence>> {
290 let value = self.get(key);
291 let value = match value {
292 Some(value) => value,
293 None => return Ok(None),
294 };
295 let sequence_type = ast::SequenceType::Item(ast::Item {
296 occurrence,
297 item_type: ast::ItemType::AtomicOrUnionType(atomic_type),
298 });
299 Ok(Some(
301 value.clone().sequence_type_matching_function_conversion(
302 &sequence_type,
303 static_context,
304 xot,
305 &|_function| unreachable!(),
307 )?,
308 ))
309 }
310
311 fn deep_equal(
313 &self,
314 other: &impl Mappable,
315 collation: &string::Collation,
316 default_offset: chrono::FixedOffset,
317 xot: &Xot,
318 ) -> error::Result<bool> {
319 if self.len() != other.len() {
320 return Ok(false);
321 }
322 for (map_key, value) in self.map_key_entries() {
323 let other_value = other.get_by_map_key(map_key);
324 if let Some(other_value) = other_value {
325 if !value.deep_equal(other_value, collation, default_offset, xot)? {
326 return Ok(false);
327 }
328 } else {
329 return Ok(false);
330 }
331 }
332 Ok(true)
333 }
334
335 fn display_representation(&self, xot: &Xot, context: &context::DynamicContext) -> String {
336 let mut entries = self
337 .entries()
338 .map(|(key, value)| {
339 format!(
340 "{}: {}",
341 key.xpath_representation(),
342 value.display_representation(xot, context)
343 )
344 })
345 .collect::<Vec<_>>();
346 entries.sort();
347 format!("map {{\n{}\n}}", entries.join(",\n"))
348 }
349}
350
351#[derive(Debug, Clone, PartialEq)]
353pub struct EmptyMap;
354
355impl Mappable for EmptyMap {
356 fn len(&self) -> usize {
357 0
358 }
359
360 fn is_empty(&self) -> bool {
361 true
362 }
363
364 fn get_by_map_key(&self, _map_key: &atomic::MapKey) -> Option<&sequence::Sequence> {
365 None
366 }
367
368 fn map_keys(&self) -> impl Iterator<Item = &'_ atomic::MapKey> + '_ {
369 std::iter::empty()
370 }
371
372 fn map_key_entries(&self) -> impl Iterator<Item = (&atomic::MapKey, &sequence::Sequence)> + '_ {
373 std::iter::empty()
374 }
375
376 fn full_entries(
377 &self,
378 ) -> impl Iterator<Item = (&atomic::MapKey, &(atomic::Atomic, sequence::Sequence))> + '_ {
379 std::iter::empty()
380 }
381
382 fn keys(&self) -> impl Iterator<Item = &atomic::Atomic> + '_ {
383 std::iter::empty()
384 }
385
386 fn entries(&self) -> impl Iterator<Item = (&atomic::Atomic, &sequence::Sequence)> + '_ {
387 std::iter::empty()
388 }
389}
390
391#[derive(Debug, Clone, PartialEq)]
392pub struct OneMap(Box<OneMapValue>);
393
394#[derive(Debug, Clone, PartialEq)]
395struct OneMapValue {
396 map_key: atomic::MapKey,
397 key_value: (atomic::Atomic, sequence::Sequence),
398}
399
400impl From<OneMapValue> for OneMap {
401 fn from(value: OneMapValue) -> Self {
402 Self(Box::new(value))
403 }
404}
405
406impl Mappable for OneMap {
407 fn len(&self) -> usize {
408 1
409 }
410
411 fn is_empty(&self) -> bool {
412 false
413 }
414
415 fn get_by_map_key(&self, map_key: &atomic::MapKey) -> Option<&sequence::Sequence> {
416 if &self.0.map_key == map_key {
417 Some(&self.0.key_value.1)
418 } else {
419 None
420 }
421 }
422
423 fn map_keys(&self) -> impl Iterator<Item = &'_ atomic::MapKey> + '_ {
424 std::iter::once(&self.0.map_key)
425 }
426
427 fn map_key_entries(&self) -> impl Iterator<Item = (&atomic::MapKey, &sequence::Sequence)> + '_ {
428 std::iter::once((&self.0.map_key, &self.0.key_value.1))
429 }
430
431 fn full_entries(
432 &self,
433 ) -> impl Iterator<Item = (&atomic::MapKey, &(atomic::Atomic, sequence::Sequence))> + '_ {
434 std::iter::once((&self.0.map_key, &self.0.key_value))
435 }
436
437 fn keys(&self) -> impl Iterator<Item = &atomic::Atomic> + '_ {
438 std::iter::once(&self.0.key_value.0)
439 }
440
441 fn entries(&self) -> impl Iterator<Item = (&atomic::Atomic, &sequence::Sequence)> + '_ {
442 std::iter::once((&self.0.key_value.0, &self.0.key_value.1))
443 }
444}
445
446#[derive(Debug, Clone, PartialEq)]
448pub struct ManyMap(Rc<HashMap<atomic::MapKey, (atomic::Atomic, sequence::Sequence)>>);
449
450impl ManyMap {
451 fn new(entries: Vec<(atomic::Atomic, sequence::Sequence)>) -> error::Result<Self> {
452 let mut map = HashMap::new();
453 for (key, value) in entries {
454 let map_key = atomic::MapKey::new(key.clone())?;
455 if map.contains_key(&map_key) {
456 return Err(error::Error::XQDY0137);
457 }
458 map.insert(map_key, (key, value));
459 }
460 Ok(Self(Rc::new(map)))
461 }
462
463 pub(crate) fn put(
464 &self,
465 key: atomic::Atomic,
466 value: &sequence::Sequence,
467 ) -> error::Result<Self> {
468 let mut map = self.0.as_ref().clone();
469 let map_key = atomic::MapKey::new(key.clone())?;
470 map.insert(map_key, (key, value.clone()));
471 Ok(Self(Rc::new(map)))
472 }
473
474 pub(crate) fn remove_keys(
475 &self,
476 keys: impl Iterator<Item = error::Result<atomic::Atomic>>,
477 ) -> error::Result<HashMap<atomic::MapKey, (atomic::Atomic, sequence::Sequence)>> {
478 let mut map = self.0.as_ref().clone();
479 for key in keys {
480 let map_key = atomic::MapKey::new(key?.clone()).unwrap();
481 map.remove(&map_key);
482 }
483 Ok(map)
484 }
485}
486
487impl Mappable for ManyMap {
488 fn len(&self) -> usize {
489 self.0.len()
490 }
491
492 fn is_empty(&self) -> bool {
493 self.0.is_empty()
494 }
495
496 fn get_by_map_key(&self, map_key: &atomic::MapKey) -> Option<&sequence::Sequence> {
497 self.0.get(map_key).map(|(_, v)| v)
498 }
499
500 fn map_keys(&self) -> impl Iterator<Item = &'_ atomic::MapKey> + '_ {
501 self.0.keys()
502 }
503
504 fn map_key_entries(&self) -> impl Iterator<Item = (&atomic::MapKey, &sequence::Sequence)> + '_ {
505 self.0.iter().map(|(k, (_, v))| (k, v))
506 }
507
508 fn full_entries(
509 &self,
510 ) -> impl Iterator<Item = (&atomic::MapKey, &(atomic::Atomic, sequence::Sequence))> + '_ {
511 self.0.iter()
512 }
513
514 fn keys(&self) -> impl Iterator<Item = &atomic::Atomic> + '_ {
515 self.0.values().map(|(k, _)| k)
516 }
517
518 fn entries(&self) -> impl Iterator<Item = (&atomic::Atomic, &sequence::Sequence)> + '_ {
519 self.0.iter().map(|(_, (k, v))| (k, v))
520 }
521}
522
523impl TryFrom<Vec<(atomic::Atomic, sequence::Sequence)>> for ManyMap {
524 type Error = error::Error;
525 fn try_from(vec: Vec<(atomic::Atomic, sequence::Sequence)>) -> error::Result<Self> {
526 Self::new(vec)
527 }
528}