1#[cfg(feature = "rayon")]
2use rayon::prelude::*;
3
4use std::collections::HashSet;
5
6use crate::{Error, Fuse, Link};
7use data::{Flow, LinkReference, LinksConstants, ToQuery};
8
9pub type ReadHandler<'a, T> = &'a mut dyn FnMut(Link<T>) -> Flow;
11
12pub type WriteHandler<'a, T> = &'a mut dyn FnMut(Link<T>, Link<T>) -> Flow;
14
15pub trait Links<T: LinkReference>: Send + Sync {
20 fn constants(&self) -> &LinksConstants<T>;
22
23 fn count_links(&self, query: &[T]) -> T;
25
26 fn create_links(&mut self, query: &[T], handler: WriteHandler<'_, T>)
28 -> Result<Flow, Error<T>>;
29
30 fn each_links(&self, query: &[T], handler: ReadHandler<'_, T>) -> Flow;
32
33 fn update_links(
35 &mut self,
36 query: &[T],
37 change: &[T],
38 handler: WriteHandler<'_, T>,
39 ) -> Result<Flow, Error<T>>;
40
41 fn delete_links(&mut self, query: &[T], handler: WriteHandler<'_, T>)
43 -> Result<Flow, Error<T>>;
44}
45
46pub trait Doublets<T: LinkReference>: Links<T> {
50 fn count_by(&self, query: impl ToQuery<T>) -> T
52 where
53 Self: Sized,
54 {
55 self.count_links(&query.to_query()[..])
56 }
57
58 fn count(&self) -> T
60 where
61 Self: Sized,
62 {
63 self.count_by([])
64 }
65
66 fn create_by_with<F>(
68 &mut self,
69 query: impl ToQuery<T>,
70 mut handler: F,
71 ) -> Result<Flow, Error<T>>
72 where
73 F: FnMut(Link<T>, Link<T>) -> Flow,
74 Self: Sized,
75 {
76 let query = query.to_query();
77 self.create_links(&query[..], &mut handler)
78 }
79
80 fn create_by(&mut self, query: impl ToQuery<T>) -> Result<T, Error<T>>
82 where
83 Self: Sized,
84 {
85 let mut index = T::from_byte(0);
86 self.create_by_with(query, |_before, link| {
87 index = link.index;
88 Flow::Continue
89 })
90 .map(|_| index)
91 }
92
93 fn create_with<F>(&mut self, handler: F) -> Result<Flow, Error<T>>
95 where
96 F: FnMut(Link<T>, Link<T>) -> Flow,
97 Self: Sized,
98 {
99 self.create_by_with([], handler)
100 }
101
102 fn create(&mut self) -> Result<T, Error<T>>
104 where
105 Self: Sized,
106 {
107 self.create_by([])
108 }
109
110 fn each_by<F>(&self, query: impl ToQuery<T>, mut handler: F) -> Flow
112 where
113 F: FnMut(Link<T>) -> Flow,
114 Self: Sized,
115 {
116 let query = query.to_query();
117 self.each_links(&query[..], &mut handler)
118 }
119
120 fn each<F>(&self, handler: F) -> Flow
122 where
123 F: FnMut(Link<T>) -> Flow,
124 Self: Sized,
125 {
126 self.each_by([], handler)
127 }
128
129 fn update_by_with<H>(
131 &mut self,
132 query: impl ToQuery<T>,
133 change: impl ToQuery<T>,
134 mut handler: H,
135 ) -> Result<Flow, Error<T>>
136 where
137 H: FnMut(Link<T>, Link<T>) -> Flow,
138 Self: Sized,
139 {
140 let query = query.to_query();
141 let change = change.to_query();
142 self.update_links(&query[..], &change[..], &mut handler)
143 }
144
145 fn update_by(&mut self, query: impl ToQuery<T>, change: impl ToQuery<T>) -> Result<T, Error<T>>
147 where
148 Self: Sized,
149 {
150 let mut result = T::from_byte(0);
151 self.update_by_with(query, change, |_, after| {
152 result = after.index;
153 Flow::Continue
154 })
155 .map(|_| result)
156 }
157
158 fn update_with<F>(
160 &mut self,
161 index: T,
162 source: T,
163 target: T,
164 handler: F,
165 ) -> Result<Flow, Error<T>>
166 where
167 F: FnMut(Link<T>, Link<T>) -> Flow,
168 Self: Sized,
169 {
170 self.update_by_with([index], [index, source, target], handler)
171 }
172
173 fn update(&mut self, index: T, source: T, target: T) -> Result<T, Error<T>>
175 where
176 Self: Sized,
177 {
178 self.update_by([index], [index, source, target])
179 }
180
181 fn delete_by_with<F>(
183 &mut self,
184 query: impl ToQuery<T>,
185 mut handler: F,
186 ) -> Result<Flow, Error<T>>
187 where
188 F: FnMut(Link<T>, Link<T>) -> Flow,
189 Self: Sized,
190 {
191 let query = query.to_query();
192 self.delete_links(&query[..], &mut handler)
193 }
194
195 fn delete_by(&mut self, query: impl ToQuery<T>) -> Result<T, Error<T>>
197 where
198 Self: Sized,
199 {
200 let mut result = T::from_byte(0);
201 self.delete_by_with(query, |_before, after| {
202 result = after.index;
203 Flow::Continue
204 })
205 .map(|_| result)
206 }
207
208 fn delete_with<F>(&mut self, index: T, handler: F) -> Result<Flow, Error<T>>
210 where
211 F: FnMut(Link<T>, Link<T>) -> Flow,
212 Self: Sized,
213 {
214 self.delete_by_with([index], handler)
215 }
216
217 fn delete(&mut self, index: T) -> Result<T, Error<T>>
219 where
220 Self: Sized,
221 {
222 self.delete_by([index])
223 }
224
225 fn try_get_link(&self, index: T) -> Result<Link<T>, Error<T>> {
227 self.get_link(index).ok_or(Error::NotExists(index))
228 }
229
230 fn get_link(&self, index: T) -> Option<Link<T>>;
232
233 fn delete_all(&mut self) -> Result<(), Error<T>>
235 where
236 Self: Sized,
237 {
238 let mut count = self.count();
239 while count != T::from_byte(0) {
240 self.delete(count)?;
241 count = self.count();
242 }
243 Ok(())
244 }
245
246 fn delete_query_with<F>(&mut self, query: impl ToQuery<T>, handler: F) -> Result<(), Error<T>>
249 where
250 F: FnMut(Link<T>, Link<T>) -> Flow,
251 Self: Sized,
252 {
253 let query = query.to_query();
254 let len = self.count_by(query.to_query()).as_();
255 let mut vec = Vec::with_capacity(len);
256 let mut seen = HashSet::with_capacity(len);
257
258 self.each_by(query, |link| {
259 if seen.insert(link.index) {
260 vec.push(link.index);
261 }
262 Flow::Continue
263 });
264
265 let mut handler = Fuse::new(handler);
266 for index in vec.into_iter().rev() {
267 self.delete_links(&[index], &mut |before, after| handler.call(before, after))?;
268 }
269 Ok(())
270 }
271
272 fn delete_usages_with<F>(&mut self, index: T, handler: F) -> Result<(), Error<T>>
275 where
276 F: FnMut(Link<T>, Link<T>) -> Flow,
277 Self: Sized,
278 {
279 let any = self.constants().any;
280 let mut to_delete = Vec::with_capacity(
281 self.count_by([any, index, any]).as_() + self.count_by([any, any, index]).as_(),
282 );
283 self.each_by([any, index, any], |link| {
284 if link.index != index {
285 to_delete.push(link.index);
286 }
287 Flow::Continue
288 });
289
290 self.each_by([any, any, index], |link| {
291 if link.index != index && link.source != index {
292 to_delete.push(link.index);
293 }
294 Flow::Continue
295 });
296
297 let mut handler = Fuse::new(handler);
298 for index in to_delete.into_iter().rev() {
299 self.delete_links(&[index], &mut |before, after| handler.call(before, after))?;
300 }
301 Ok(())
302 }
303
304 fn delete_usages(&mut self, index: T) -> Result<(), Error<T>>
306 where
307 Self: Sized,
308 {
309 self.delete_usages_with(index, |_, _| Flow::Continue)
310 }
311
312 fn create_point(&mut self) -> Result<T, Error<T>>
314 where
315 Self: Sized,
316 {
317 let new = self.create()?;
318 self.update(new, new, new)
319 }
320
321 fn create_link_with<F>(&mut self, source: T, target: T, handler: F) -> Result<Flow, Error<T>>
323 where
324 F: FnMut(Link<T>, Link<T>) -> Flow,
325 Self: Sized,
326 {
327 let mut new = T::from_byte(0);
328 let mut handler = Fuse::new(handler);
329 self.create_with(|before, after| {
330 new = after.index;
331 handler.call(before, after);
332 Flow::Continue
333 })?;
334
335 self.update_links(&[new], &[new, source, target], &mut |before, after| {
336 handler.call(before, after)
337 })
338 }
339
340 fn create_link(&mut self, source: T, target: T) -> Result<T, Error<T>>
342 where
343 Self: Sized,
344 {
345 let mut result = T::from_byte(0);
346 self.create_link_with(source, target, |_, link| {
347 result = link.index;
348 Flow::Continue
349 })
350 .map(|_| result)
351 }
352
353 fn found(&self, query: impl ToQuery<T>) -> bool
355 where
356 Self: Sized,
357 {
358 self.count_by(query) != T::from_byte(0)
359 }
360
361 fn find(&self, query: impl ToQuery<T>) -> Option<Link<T>>
363 where
364 Self: Sized,
365 {
366 let mut result = None;
367 self.each_by(query, |link| {
368 result = Some(link);
369 Flow::Break
370 });
371 result
372 }
373
374 fn search(&self, source: T, target: T) -> Option<T>
376 where
377 Self: Sized,
378 {
379 self.find([self.constants().any, source, target])
380 .map(|link| link.index)
381 }
382
383 #[deprecated(note = "use `search` instead")]
384 fn search_or(&self, source: T, target: T, default: T) -> T
385 where
386 Self: Sized,
387 {
388 self.search(source, target).unwrap_or(default)
389 }
390
391 fn single(&self, query: impl ToQuery<T>) -> Option<Link<T>>
393 where
394 Self: Sized,
395 {
396 let mut result = None;
397 self.each_by(query, |link| {
398 if result.is_none() {
399 result = Some(link);
400 Flow::Continue
401 } else {
402 result = None;
403 Flow::Break
404 }
405 });
406 result
407 }
408
409 fn get_or_create(&mut self, source: T, target: T) -> Result<T, Error<T>>
411 where
412 Self: Sized,
413 {
414 if let Some(link) = self.search(source, target) {
415 Ok(link)
416 } else {
417 self.create_link(source, target)
418 }
419 }
420
421 fn count_usages(&self, index: T) -> Result<T, Error<T>>
423 where
424 Self: Sized,
425 {
426 let any = self.constants().any;
427
428 let link = self.try_get_link(index)?;
429
430 let usage_source = self.count_by([any, index, any]);
431 let usage_target = self.count_by([any, any, index]);
432 let usage_both = self.count_by([any, index, index]);
433 let mut usages = usage_source + (usage_target - usage_both);
435 if index == link.source || index == link.target {
436 usages = usages - T::from_byte(1);
437 }
438
439 Ok(usages)
440 }
441
442 fn usages(&self, index: T) -> Result<Vec<T>, Error<T>>
444 where
445 Self: Sized,
446 {
447 let any = self.constants().any;
448 let mut usages = Vec::with_capacity(self.count_usages(index)?.as_());
449
450 self.each_by([any, index, any], |link| {
451 if link.index != index {
452 usages.push(link.index);
453 }
454 Flow::Continue
455 });
456
457 self.each_by([any, any, index], |link| {
458 if link.index != index && link.source != index {
459 usages.push(link.index);
460 }
461 Flow::Continue
462 });
463 Ok(usages)
464 }
465
466 fn exist(&self, link: T) -> bool
468 where
469 Self: Sized,
470 {
471 let constants = self.constants();
472 if constants.is_external(link) {
473 true
474 } else {
475 constants.is_internal(link) && self.count_by([link]) != T::from_byte(0)
476 }
477 }
478
479 fn has_usages(&self, link: T) -> bool
481 where
482 Self: Sized,
483 {
484 self.count_usages(link)
485 .is_ok_and(|link| link != T::from_byte(0))
486 }
487
488 fn rebase_with<F>(&mut self, old: T, new: T, handler: F) -> Result<(), Error<T>>
493 where
494 F: FnMut(Link<T>, Link<T>) -> Flow,
495 Self: Sized,
496 {
497 let _ = self.try_get_link(old)?;
498
499 if old == new {
500 return Ok(());
501 }
502
503 let any = self.constants().any;
504
505 let mut handler = Fuse::new(handler);
506
507 let usages: Vec<_> = self
508 .each_iter([any, old, any])
509 .chain(
511 self.each_iter([any, any, old])
512 .filter(|usage| usage.source != old),
513 )
514 .filter(|usage| usage.index != old)
515 .collect();
516 for usage in usages {
517 let source = if usage.source == old {
518 new
519 } else {
520 usage.source
521 };
522 let target = if usage.target == old {
523 new
524 } else {
525 usage.target
526 };
527 self.update_links(
528 &[usage.index],
529 &[usage.index, source, target],
530 &mut |before, after| handler.call(before, after),
531 )?;
532 }
533 Ok(())
534 }
535
536 fn rebase(&mut self, old: T, new: T) -> Result<T, Error<T>>
538 where
539 Self: Sized,
540 {
541 self.rebase_with(old, new, |_, _| Flow::Continue)
542 .map(|()| new)
543 }
544
545 fn rebase_and_delete(&mut self, old: T, new: T) -> Result<T, Error<T>>
547 where
548 Self: Sized,
549 {
550 if old == new {
551 Ok(new)
552 } else {
553 self.rebase(old, new)?;
554 self.delete(old)
555 }
556 }
557}
558
559impl<T: LinkReference, All: Doublets<T> + ?Sized> Links<T> for Box<All> {
560 fn constants(&self) -> &LinksConstants<T> {
561 (**self).constants()
562 }
563
564 fn count_links(&self, query: &[T]) -> T {
565 (**self).count_links(query)
566 }
567
568 fn create_links(
569 &mut self,
570 query: &[T],
571 handler: WriteHandler<'_, T>,
572 ) -> Result<Flow, Error<T>> {
573 (**self).create_links(query, handler)
574 }
575
576 fn each_links(&self, query: &[T], handler: ReadHandler<'_, T>) -> Flow {
577 (**self).each_links(query, handler)
578 }
579
580 fn update_links(
581 &mut self,
582 query: &[T],
583 change: &[T],
584 handler: WriteHandler<'_, T>,
585 ) -> Result<Flow, Error<T>> {
586 (**self).update_links(query, change, handler)
587 }
588
589 fn delete_links(
590 &mut self,
591 query: &[T],
592 handler: WriteHandler<'_, T>,
593 ) -> Result<Flow, Error<T>> {
594 (**self).delete_links(query, handler)
595 }
596}
597
598impl<T: LinkReference, All: Doublets<T> + ?Sized> Doublets<T> for Box<All> {
599 fn get_link(&self, index: T) -> Option<Link<T>> {
600 (**self).get_link(index)
601 }
602}
603
604pub trait DoubletsExt<T: LinkReference>: Sized + Doublets<T> {
608 #[cfg(feature = "rayon")]
610 type IdxParIter: IndexedParallelIterator<Item = Link<T>>;
611
612 #[cfg(feature = "rayon")]
614 fn par_iter(&self) -> Self::IdxParIter;
615
616 #[cfg(feature = "rayon")]
618 fn par_each_iter(&self, query: impl ToQuery<T>) -> Self::IdxParIter;
619
620 fn iter(&self) -> impl Iterator<Item = Link<T>> + ExactSizeIterator + DoubleEndedIterator;
622
623 fn each_iter(
625 &self,
626 query: impl ToQuery<T>,
627 ) -> impl Iterator<Item = Link<T>> + ExactSizeIterator + DoubleEndedIterator;
628
629 #[cfg(feature = "small-search")]
631 fn iter_small(&self)
632 -> impl Iterator<Item = Link<T>> + ExactSizeIterator + DoubleEndedIterator;
633
634 #[cfg(feature = "small-search")]
636 fn each_iter_small(
637 &self,
638 query: impl ToQuery<T>,
639 ) -> impl Iterator<Item = Link<T>> + ExactSizeIterator + DoubleEndedIterator;
640}
641
642impl<T: LinkReference, All: Doublets<T> + Sized> DoubletsExt<T> for All {
643 #[cfg(feature = "rayon")]
644 type IdxParIter = rayon::vec::IntoIter<Link<T>>;
645
646 #[cfg(feature = "rayon")]
647 fn par_iter(&self) -> Self::IdxParIter {
648 self.par_each_iter([self.constants().any; 3])
649 }
650
651 #[cfg(feature = "rayon")]
652 fn par_each_iter(&self, query: impl ToQuery<T>) -> Self::IdxParIter {
653 let mut vec = Vec::with_capacity(self.count_by(query.to_query()).as_());
654 self.each_by(query, |link| {
655 vec.push(link);
656 Flow::Continue
657 });
658 vec.into_par_iter()
659 }
660
661 #[inline]
662 fn iter(&self) -> impl Iterator<Item = Link<T>> + ExactSizeIterator + DoubleEndedIterator {
663 self.each_iter([self.constants().any; 3])
664 }
665
666 #[cfg_attr(feature = "more-inline", inline)]
667 fn each_iter(
668 &self,
669 query: impl ToQuery<T>,
670 ) -> impl Iterator<Item = Link<T>> + ExactSizeIterator + DoubleEndedIterator {
671 let cap = self.count_by(query.to_query()).as_();
672
673 let mut vec = Vec::with_capacity(cap);
674 self.each_by(query, &mut |link| {
675 vec.push(link);
676 Flow::Continue
677 });
678 vec.into_iter()
679 }
680
681 #[inline]
682 #[cfg(feature = "small-search")]
683 fn iter_small(
684 &self,
685 ) -> impl Iterator<Item = Link<T>> + ExactSizeIterator + DoubleEndedIterator {
686 self.each_iter_small([self.constants().any; 3])
687 }
688
689 #[cfg(feature = "small-search")]
690 #[cfg_attr(feature = "more-inline", inline)]
691 fn each_iter_small(
692 &self,
693 query: impl ToQuery<T>,
694 ) -> impl Iterator<Item = Link<T>> + ExactSizeIterator + DoubleEndedIterator {
695 const SIZE_HINT: usize = 2;
696
697 let mut vec = smallvec::SmallVec::<[Link<_>; SIZE_HINT]>::with_capacity(
698 self.count_by(query.to_query()).as_(),
699 );
700 self.each_by(query, |link| {
701 vec.push(link);
702 Flow::Continue
703 });
704 vec.into_iter()
705 }
706}