1use std::any::Any;
13use std::borrow::Cow;
14use std::cmp;
15use std::fmt;
16use std::fmt::Debug;
17use std::ops::Add;
18use std::ops::BitAnd;
19use std::ops::BitOr;
20use std::ops::Deref;
21use std::ops::Sub;
22use std::pin::Pin;
23use std::sync::Arc;
24
25use futures::future::BoxFuture;
26use futures::Stream;
27use futures::StreamExt;
28use nonblocking::non_blocking;
29
30use crate::default_impl;
31use crate::ops::DagAlgorithm;
32use crate::ops::IdConvert;
33use crate::ops::IdMapSnapshot;
34use crate::ops::Parents;
35use crate::Id;
36use crate::IdList;
37use crate::IdSet;
38use crate::Result;
39use crate::Vertex;
40
41pub mod difference;
42pub mod hints;
43pub mod id_lazy;
44pub mod id_static;
45pub mod intersection;
46pub mod lazy;
47#[cfg(any(test, feature = "indexedlog-backend"))]
48pub mod legacy;
49pub mod meta;
50pub mod reverse;
51pub mod slice;
52pub mod r#static;
53pub mod union;
54
55use self::hints::Flags;
56use self::hints::Hints;
57use self::id_static::BasicIterationOrder;
58use self::id_static::IdStaticSet;
59use self::meta::MetaSet;
60use self::reverse::ReverseSet;
61use self::r#static::StaticSet;
62
63#[derive(Clone)]
68pub struct Set(Arc<dyn AsyncSetQuery>);
69
70impl Set {
71 pub(crate) fn from_query(query: impl AsyncSetQuery) -> Self {
72 Self(Arc::new(query))
73 }
74
75 pub fn empty() -> Self {
77 Self::from_query(r#static::StaticSet::empty())
78 }
79
80 pub fn from_static_names(names: impl IntoIterator<Item = Vertex>) -> Set {
82 Self::from_query(r#static::StaticSet::from_names(names))
83 }
84
85 pub fn from_iter<I>(iter: I, hints: Hints) -> Set
87 where
88 I: IntoIterator<Item = Result<Vertex>> + 'static,
89 <I as IntoIterator>::IntoIter: Send + Sync,
90 {
91 Self::from_query(lazy::LazySet::from_iter(iter, hints))
92 }
93
94 pub fn from_stream(stream: BoxVertexStream, hints: Hints) -> Set {
96 Self::from_query(lazy::LazySet::from_stream(stream, hints))
97 }
98
99 pub fn from_id_iter_idmap_dag<I>(
101 iter: I,
102 map: Arc<dyn IdConvert + Send + Sync>,
103 dag: Arc<dyn DagAlgorithm + Send + Sync>,
104 ) -> Set
105 where
106 I: IntoIterator<Item = Result<Id>> + 'static,
107 <I as IntoIterator>::IntoIter: Send + Sync,
108 {
109 Self::from_query(id_lazy::IdLazySet::from_iter_idmap_dag(iter, map, dag))
110 }
111
112 pub fn from_id_iter_dag<I>(iter: I, dag: &(impl DagAlgorithm + IdMapSnapshot)) -> Result<Set>
114 where
115 I: IntoIterator<Item = Result<Id>> + 'static,
116 <I as IntoIterator>::IntoIter: Send + Sync,
117 {
118 let map = dag.id_map_snapshot()?;
119 let dag = dag.dag_snapshot()?;
120 Ok(Self::from_id_iter_idmap_dag(iter, map, dag))
121 }
122
123 pub fn from_id_set_idmap_dag(
127 spans: IdSet,
128 map: Arc<dyn IdConvert + Send + Sync>,
129 dag: Arc<dyn DagAlgorithm + Send + Sync>,
130 ) -> Set {
131 Self::from_id_set_idmap_dag_order(spans, map, dag, None)
132 }
133
134 pub fn from_id_set_idmap_dag_order(
137 spans: IdSet,
138 map: Arc<dyn IdConvert + Send + Sync>,
139 dag: Arc<dyn DagAlgorithm + Send + Sync>,
140 iteration_order: Option<BasicIterationOrder>,
141 ) -> Set {
142 let mut set = IdStaticSet::from_id_set_idmap_dag(spans, map, dag);
143 if let Some(order) = iteration_order {
144 set.set_iteration_order(order);
145 }
146 Self::from_query(set)
147 }
148
149 pub fn from_id_set_dag(
152 spans: IdSet,
153 dag: &(impl DagAlgorithm + IdMapSnapshot),
154 ) -> Result<Self> {
155 let map = dag.id_map_snapshot()?;
156 let dag = dag.dag_snapshot()?;
157 Ok(Self::from_id_set_idmap_dag(spans, map, dag))
158 }
159
160 pub fn from_id_list_dag(
164 list: IdList,
165 dag: &(impl DagAlgorithm + IdMapSnapshot),
166 ) -> Result<Self> {
167 let map = dag.id_map_snapshot()?;
168 let dag = dag.dag_snapshot()?;
169 let set = IdStaticSet::from_id_list_idmap_dag(list, map, dag);
170 Ok(Self::from_query(set))
171 }
172
173 pub fn from_evaluate_contains<C>(
176 evaluate: impl Fn() -> Result<Set> + Send + Sync + 'static,
177 contains: C,
178 hints: Hints,
179 ) -> Set
180 where
181 C: for<'a> Fn(&'a MetaSet, &'a Vertex) -> Result<bool>,
182 C: Send + Sync + 'static,
183 {
184 let evaluate = move || -> BoxFuture<_> {
185 let result = evaluate();
186 Box::pin(async move { result })
187 };
188 let contains = Arc::new(contains);
189 Self::from_async_evaluate_contains(
190 Box::new(evaluate),
191 Box::new(move |m, v| {
192 let contains = contains.clone();
193 Box::pin(async move { contains(m, v) })
194 }),
195 hints,
196 )
197 }
198
199 pub fn from_async_evaluate_contains(
202 evaluate: Box<dyn Fn() -> BoxFuture<'static, Result<Set>> + Send + Sync>,
203 contains: Box<
204 dyn for<'a> Fn(&'a MetaSet, &'a Vertex) -> BoxFuture<'a, Result<bool>> + Send + Sync,
205 >,
206 hints: Hints,
207 ) -> Set {
208 Self::from_query(MetaSet::from_evaluate_hints(evaluate, hints).with_contains(contains))
209 }
210
211 pub fn reverse(&self) -> Set {
213 match self.0.specialized_reverse() {
214 Some(set) => set,
215 None => Self::from_query(ReverseSet::new(self.clone())),
216 }
217 }
218
219 pub fn difference(&self, other: &Set) -> Set {
221 if other.hints().contains(Flags::FULL)
222 && other.hints().dag_version() >= self.hints().dag_version()
223 && self.hints().dag_version() > None
224 {
225 tracing::debug!(
226 target: "dag::algo::difference",
227 "difference(x={:.6?}, y={:.6?}) = () (fast path 1)",
228 self,
229 other
230 );
231 return Self::empty();
232 }
233 if self.hints().contains(Flags::EMPTY) || other.hints().contains(Flags::EMPTY) {
234 tracing::debug!(
235 target: "dag::algo::difference",
236 "difference(x={:.6?}, y={:.6?}) = x (fast path 2)",
237 self,
238 other
239 );
240 return self.clone();
241 }
242 if let (Some(this), Some(other)) = (
243 self.as_any().downcast_ref::<IdStaticSet>(),
244 other.specialized_flatten_id(),
246 ) {
247 let order = this.map.map_version().partial_cmp(other.map.map_version());
248 if let (Some(_order), Some(this_id_set)) = (order, this.id_set_try_preserving_order()) {
249 let result = Self::from_id_set_idmap_dag_order(
252 this_id_set.difference(other.id_set_losing_order()),
253 this.map.clone(),
254 this.dag.clone(),
255 this.iteration_order(),
256 );
257 tracing::debug!(
258 target: "dag::algo::difference",
259 "difference(x={:.6?}, y={:.6?}) = {:.6?} (fast path 3)",
260 self,
261 other,
262 &result
263 );
264 return result;
265 }
266 }
267 tracing::warn!(
268 target: "dag::algo::difference",
269 "difference(x={:.6?}, y={:.6?}) (slow path)", self, other);
270 Self::from_query(difference::DifferenceSet::new(self.clone(), other.clone()))
271 }
272
273 pub fn intersection(&self, other: &Set) -> Set {
275 if self.hints().contains(Flags::FULL)
276 && self.hints().dag_version() >= other.hints().dag_version()
277 && other.hints().dag_version() > None
278 {
279 tracing::debug!(
280 target: "dag::algo::intersection",
281 "intersection(x={:.6?}, y={:.6?}) = y (fast path 1)",
282 self,
283 other
284 );
285 return other.clone();
286 }
287 if other.hints().contains(Flags::FULL)
288 && other.hints().dag_version() >= self.hints().dag_version()
289 && self.hints().dag_version() > None
290 {
291 tracing::debug!(
292 target: "dag::algo::intersection",
293 "intersection(x={:.6?}, y={:.6?}) = x (fast path 2)",
294 self,
295 other
296 );
297 return self.clone();
298 }
299 if self.hints().contains(Flags::EMPTY) || other.hints().contains(Flags::EMPTY) {
300 tracing::debug!(
301 target: "dag::algo::intersection",
302 "intersection(x={:.6?}, y={:.6?}) = () (fast path 3)",
303 self,
304 other
305 );
306 return Self::empty();
307 }
308 if let (Some(this), Some(other)) = (
309 self.as_any().downcast_ref::<IdStaticSet>(),
310 other.specialized_flatten_id(),
312 ) {
313 let order = this.map.map_version().partial_cmp(other.map.map_version());
314 if let (Some(order), Some(this_id_set)) = (order, this.id_set_try_preserving_order()) {
315 let result = Self::from_id_set_idmap_dag_order(
317 this_id_set.intersection(other.id_set_losing_order()),
318 pick(order, &this.map, &other.map).clone(),
319 pick(order, &this.dag, &other.dag).clone(),
320 this.iteration_order(),
321 );
322 tracing::debug!(
323 target: "dag::algo::intersection",
324 "intersection(x={:.6?}, y={:.6?}) = {:?} (IdStatic fast path)",
325 self,
326 other,
327 &result
328 );
329 return result;
330 }
331 }
332 tracing::warn!(
333 target: "dag::algo::intersection",
334 "intersection(x={:.6?}, y={:.6?}) (slow path)", self, other);
335 Self::from_query(intersection::IntersectionSet::new(
336 self.clone(),
337 other.clone(),
338 ))
339 }
340
341 fn union_fast_paths(&self, other: &Self) -> Option<Self> {
343 if (self.hints().contains(Flags::FULL)
344 && self.hints().dag_version() >= other.hints().dag_version()
345 && other.hints().dag_version() > None)
346 || other.hints().contains(Flags::EMPTY)
347 {
348 tracing::debug!(
349 target: "dag::algo::union",
350 "union(x={:.6?}, y={:.6?}) = x (fast path 1)", self, other);
351 return Some(self.clone());
352 }
353 if self.hints().contains(Flags::EMPTY)
354 || (other.hints().contains(Flags::FULL)
355 && other.hints().dag_version() >= self.hints().dag_version()
356 && self.hints().dag_version() > None)
357 {
358 tracing::debug!(
359 target: "dag::algo::union",
360 "union(x={:.6?}, y={:.6?}) = y (fast path 2)", self, other);
361 return Some(other.clone());
362 }
363 None
364 }
365
366 pub fn union(&self, other: &Set) -> Set {
368 if let Some(set) = self.union_fast_paths(other) {
369 return set;
370 }
371
372 if let (Some(this), Some(other)) = (
374 self.specialized_flatten_id(),
375 other.specialized_flatten_id(),
376 ) {
377 let order = this.map.map_version().partial_cmp(other.map.map_version());
378 if let Some(order) = order {
379 let result = Self::from_id_set_idmap_dag_order(
381 this.id_set_losing_order()
382 .union(other.id_set_losing_order()),
383 pick(order, &this.map, &other.map).clone(),
384 pick(order, &this.dag, &other.dag).clone(),
385 this.iteration_order(),
386 );
387 tracing::debug!(
388 target: "dag::algo::union",
389 "union(x={:.6?}, y={:.6?}) = {:.6?} (fast path 3)",
390 self,
391 other,
392 &result
393 );
394 return result;
395 }
396 }
397 tracing::warn!(
398 target: "dag::algo::union",
399 "union(x={:.6?}, y={:.6?}) (slow path)", self, other);
400 Self::from_query(union::UnionSet::new(self.clone(), other.clone()))
401 }
402
403 pub fn union_preserving_order(&self, other: &Self) -> Self {
405 if let Some(set) = self.union_fast_paths(other) {
406 return set;
407 }
408 tracing::debug!(target: "dag::algo::union_preserving_order", "union(x={:.6?}, y={:.6?})", self, other);
409 Self::from_query(union::UnionSet::new(self.clone(), other.clone()))
410 }
411
412 pub fn union_zip(&self, other: &Set) -> Set {
415 tracing::debug!(
416 target: "dag::algo::union_zip",
417 "union_zip(x={:.6?}, y={:.6?}) (slow path)", self, other);
418 Self::from_query(
419 union::UnionSet::new(self.clone(), other.clone()).with_order(union::UnionOrder::Zip),
420 )
421 }
422
423 pub fn filter(
426 &self,
427 filter_func: Box<dyn Fn(&Vertex) -> BoxFuture<Result<bool>> + Send + Sync + 'static>,
428 ) -> Self {
429 let filter_func = Arc::new(filter_func);
430 let this = self.clone();
431 let hints = {
432 let hints = self.hints().clone();
434 hints.update_flags_with(|f| (f - Flags::ANCESTORS - Flags::FULL) | Flags::FILTER);
435 hints
436 };
437 let result = Self::from_async_evaluate_contains(
438 Box::new({
439 let filter_func = filter_func.clone();
440 let this = this.clone();
441 let hints = hints.clone();
442 move || {
443 let filter_func = filter_func.clone();
444 let this = this.clone();
445 let hints = hints.clone();
446 Box::pin(async move {
447 let stream = this.0.iter().await?;
448 let stream = stream.filter_map(move |v| {
449 let filter_func = filter_func.clone();
450 async move {
451 match v {
452 Ok(v) => match filter_func(&v).await {
453 Ok(true) => Some(Ok(v)),
454 Ok(false) => None,
455 Err(e) => Some(Err(e)),
456 },
457 Err(e) => Some(Err(e)),
458 }
459 }
460 });
461 Ok(Self::from_stream(Box::pin(stream), hints))
462 })
463 }
464 }),
465 Box::new(move |_, v| {
466 let filter_func = filter_func.clone();
467 let this = this.clone();
468 Box::pin(async move { Ok(this.0.contains(v).await? && filter_func(v).await?) })
469 }),
470 hints,
471 );
472 result.hints().add_flags(Flags::FILTER);
473 result
474 }
475
476 pub async fn to_parents(&self) -> Result<Option<impl Parents>> {
479 default_impl::set_to_parents(self).await
480 }
481
482 pub fn dag(&self) -> Option<Arc<dyn DagAlgorithm + Send + Sync>> {
484 self.hints().dag()
485 }
486
487 pub fn id_map(&self) -> Option<Arc<dyn IdConvert + Send + Sync>> {
489 self.hints().id_map()
490 }
491
492 pub async fn flatten(&self) -> Result<Set> {
498 match (self.id_map(), self.dag()) {
499 (Some(id_map), Some(dag)) => {
500 self.flatten_id(id_map, dag).await
502 }
503 _ => {
504 self.flatten_names().await
506 }
507 }
508 }
509
510 pub async fn flatten_id(
514 &self,
515 id_map: Arc<dyn IdConvert + Send + Sync>,
516 dag: Arc<dyn DagAlgorithm + Send + Sync>,
517 ) -> Result<Set> {
518 if self.as_any().is::<IdStaticSet>() {
519 return Ok(self.clone());
520 }
521 let mut ids = Vec::with_capacity(self.count()?.try_into()?);
522 for vertex in self.iter()? {
523 let id = id_map.vertex_id(vertex?).await?;
524 ids.push(id);
525 }
526 ids.sort_unstable_by_key(|i| u64::MAX - i.0);
527 let spans = IdSet::from_sorted_spans(ids);
528 let flat_set = Set::from_id_set_idmap_dag(spans, id_map, dag);
529 flat_set.hints().inherit_flags_min_max_id(self.hints());
530 Ok(flat_set)
531 }
532
533 pub async fn flatten_names(&self) -> Result<Set> {
535 if self.as_any().is::<StaticSet>() {
536 return Ok(self.clone());
537 }
538 let names = self.iter()?.collect::<Result<Vec<_>>>()?;
539 let flat_set = Self::from_static_names(names);
540 flat_set.hints().inherit_flags_min_max_id(self.hints());
541 Ok(flat_set)
542 }
543
544 pub fn take(&self, n: u64) -> Set {
546 if let Some(set) = self.specialized_take(n) {
547 tracing::debug!("take(x={:.6?}, {}) (specialized path)", self, n);
548 set
549 } else {
550 tracing::debug!("take(x={:.6?}, {}) (universal path)", self, n);
551 let set = slice::SliceSet::new(self.clone(), 0, Some(n));
552 Self::from_query(set)
553 }
554 }
555
556 pub fn skip(&self, n: u64) -> Set {
558 if n == 0 {
559 return self.clone();
560 }
561 if let Some(set) = self.specialized_skip(n) {
562 tracing::debug!("skip(x={:.6?}, {}) (specialized path)", self, n);
563 set
564 } else {
565 tracing::debug!("skip(x={:.6?}, {}) (universal path)", self, n);
566 let set = slice::SliceSet::new(self.clone(), n, None);
567 Self::from_query(set)
568 }
569 }
570
571 pub fn to_id_set_and_id_map_in_o1(&self) -> Option<(IdSet, Arc<dyn IdConvert + Send + Sync>)> {
577 let id_set = self.specialized_flatten_id()?.into_owned();
578 Some((id_set.id_set_losing_order().clone(), id_set.map))
579 }
580}
581
582impl BitAnd for Set {
583 type Output = Self;
584
585 fn bitand(self, other: Self) -> Self {
586 self.intersection(&other)
587 }
588}
589
590impl BitOr for Set {
591 type Output = Self;
592
593 fn bitor(self, other: Self) -> Self {
594 self.union(&other)
595 }
596}
597
598impl Add for Set {
599 type Output = Self;
600
601 fn add(self, rhs: Self) -> Self::Output {
602 self.union_preserving_order(&rhs)
603 }
604}
605
606impl Sub for Set {
607 type Output = Self;
608
609 fn sub(self, other: Self) -> Self {
610 self.difference(&other)
611 }
612}
613
614impl Deref for Set {
615 type Target = dyn AsyncSetQuery;
616
617 fn deref(&self) -> &Self::Target {
618 self.0.deref()
619 }
620}
621
622impl fmt::Debug for Set {
623 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
624 self.0.fmt(f)
625 }
626}
627
628#[async_trait::async_trait]
633pub trait AsyncSetQuery: Any + Debug + Send + Sync {
634 async fn iter(&self) -> Result<BoxVertexStream>;
636
637 async fn iter_rev(&self) -> Result<BoxVertexStream> {
639 let mut iter = self.iter().await?;
640 let mut items = Vec::new();
641 while let Some(item) = iter.next().await {
642 items.push(item);
643 }
644 Ok(Box::pin(futures::stream::iter(items.into_iter().rev())))
645 }
646
647 async fn count(&self) -> Result<u64> {
652 if let Some(flat) = self.specialized_flatten_id() {
653 return flat.count_slow().await;
654 }
655 self.count_slow().await
656 }
657
658 async fn count_slow(&self) -> Result<u64> {
663 let mut iter = self.iter().await?;
664 let mut count = 0;
665 while let Some(item) = iter.next().await {
666 item?;
667 count += 1;
668 }
669 Ok(count)
670 }
671
672 async fn size_hint(&self) -> (u64, Option<u64>) {
677 (0, None)
678 }
679
680 async fn first(&self) -> Result<Option<Vertex>> {
682 self.iter().await?.next().await.transpose()
683 }
684
685 async fn last(&self) -> Result<Option<Vertex>> {
687 self.iter_rev().await?.next().await.transpose()
688 }
689
690 async fn is_empty(&self) -> Result<bool> {
692 self.first().await.map(|n| n.is_none())
693 }
694
695 async fn contains(&self, name: &Vertex) -> Result<bool> {
697 let mut iter = self.iter().await?;
698 while let Some(item) = iter.next().await {
699 if &item? == name {
700 return Ok(true);
701 }
702 }
703 Ok(false)
704 }
705
706 async fn contains_fast(&self, name: &Vertex) -> Result<Option<bool>> {
709 let _ = name;
710 Ok(None)
711 }
712
713 fn as_any(&self) -> &dyn Any;
715
716 fn hints(&self) -> &Hints;
718
719 fn id_convert(&self) -> Option<&dyn IdConvert> {
721 None
722 }
723
724 fn specialized_reverse(&self) -> Option<Set> {
727 None
728 }
729
730 fn specialized_take(&self, n: u64) -> Option<Set> {
733 let _ = n;
734 None
735 }
736
737 fn specialized_skip(&self, n: u64) -> Option<Set> {
740 let _ = n;
741 None
742 }
743
744 fn specialized_flatten_id(&self) -> Option<Cow<IdStaticSet>> {
746 None
747 }
748}
749
750pub trait SyncSetQuery {
752 fn iter(&self) -> Result<Box<dyn NameIter>>;
754
755 fn iter_rev(&self) -> Result<Box<dyn NameIter>>;
757
758 fn count(&self) -> Result<u64>;
760
761 fn first(&self) -> Result<Option<Vertex>>;
763
764 fn last(&self) -> Result<Option<Vertex>>;
766
767 fn is_empty(&self) -> Result<bool>;
769
770 fn contains(&self, name: &Vertex) -> Result<bool>;
772
773 fn as_any(&self) -> &dyn Any;
775
776 fn hints(&self) -> &Hints;
778
779 fn id_convert(&self) -> Option<&dyn IdConvert>;
781}
782
783impl<T: AsyncSetQuery> SyncSetQuery for T {
784 fn iter(&self) -> Result<Box<dyn NameIter>> {
785 non_blocking(AsyncSetQuery::iter(self))?.map(to_iter)
786 }
787
788 fn iter_rev(&self) -> Result<Box<dyn NameIter>> {
789 non_blocking(AsyncSetQuery::iter_rev(self))?.map(to_iter)
790 }
791
792 fn count(&self) -> Result<u64> {
793 non_blocking(AsyncSetQuery::count_slow(self))?
794 }
795
796 fn first(&self) -> Result<Option<Vertex>> {
797 non_blocking(AsyncSetQuery::first(self))?
798 }
799
800 fn last(&self) -> Result<Option<Vertex>> {
801 non_blocking(AsyncSetQuery::last(self))?
802 }
803
804 fn is_empty(&self) -> Result<bool> {
805 non_blocking(AsyncSetQuery::is_empty(self))?
806 }
807
808 fn contains(&self, name: &Vertex) -> Result<bool> {
809 non_blocking(AsyncSetQuery::contains(self, name))?
810 }
811
812 fn as_any(&self) -> &dyn Any {
813 AsyncSetQuery::as_any(self)
814 }
815
816 fn hints(&self) -> &Hints {
817 AsyncSetQuery::hints(self)
818 }
819
820 fn id_convert(&self) -> Option<&dyn IdConvert> {
821 AsyncSetQuery::id_convert(self)
822 }
823}
824
825impl SyncSetQuery for Set {
826 fn iter(&self) -> Result<Box<dyn NameIter>> {
827 non_blocking(AsyncSetQuery::iter(self.0.deref()))?.map(to_iter)
828 }
829
830 fn iter_rev(&self) -> Result<Box<dyn NameIter>> {
831 non_blocking(AsyncSetQuery::iter_rev(self.0.deref()))?.map(to_iter)
832 }
833
834 fn count(&self) -> Result<u64> {
835 non_blocking(AsyncSetQuery::count_slow(self.0.deref()))?
836 }
837
838 fn first(&self) -> Result<Option<Vertex>> {
839 non_blocking(AsyncSetQuery::first(self.0.deref()))?
840 }
841
842 fn last(&self) -> Result<Option<Vertex>> {
843 non_blocking(AsyncSetQuery::last(self.0.deref()))?
844 }
845
846 fn is_empty(&self) -> Result<bool> {
847 non_blocking(AsyncSetQuery::is_empty(self.0.deref()))?
848 }
849
850 fn contains(&self, name: &Vertex) -> Result<bool> {
851 non_blocking(AsyncSetQuery::contains(self.0.deref(), name))?
852 }
853
854 fn as_any(&self) -> &dyn Any {
855 AsyncSetQuery::as_any(self.0.deref())
856 }
857
858 fn hints(&self) -> &Hints {
859 AsyncSetQuery::hints(self.0.deref())
860 }
861
862 fn id_convert(&self) -> Option<&dyn IdConvert> {
863 AsyncSetQuery::id_convert(self.0.deref())
864 }
865}
866
867pub trait NameIter: Iterator<Item = Result<Vertex>> + Send {}
871impl<T> NameIter for T where T: Iterator<Item = Result<Vertex>> + Send {}
872
873pub trait VertexStream: Stream<Item = Result<Vertex>> + Send {}
875impl<T> VertexStream for T where T: Stream<Item = Result<Vertex>> + Send {}
876
877pub type BoxVertexStream = Pin<Box<dyn VertexStream>>;
879
880struct NonblockingNameIter(BoxVertexStream);
882
883impl Iterator for NonblockingNameIter {
884 type Item = Result<Vertex>;
885
886 fn next(&mut self) -> Option<Self::Item> {
887 match non_blocking(self.0.next()) {
888 Err(e) => Some(Err(e.into())),
889 Ok(v) => v,
890 }
891 }
892}
893
894fn to_iter(stream: BoxVertexStream) -> Box<dyn NameIter> {
895 Box::new(NonblockingNameIter(stream))
896}
897
898impl From<Vertex> for Set {
899 fn from(name: Vertex) -> Set {
900 Set::from_static_names(std::iter::once(name))
901 }
902}
903
904impl From<&Vertex> for Set {
905 fn from(name: &Vertex) -> Set {
906 Set::from_static_names(std::iter::once(name.clone()))
907 }
908}
909
910fn pick<T>(order: cmp::Ordering, left: T, right: T) -> T {
913 match order {
914 cmp::Ordering::Greater | cmp::Ordering::Equal => left,
915 cmp::Ordering::Less => right,
916 }
917}
918
919#[cfg(test)]
920pub(crate) mod tests {
921 use futures::TryStreamExt;
922 use nonblocking::non_blocking_result as r;
923
924 use super::*;
925 pub(crate) use crate::tests::dbg;
926 use crate::Id;
927
928 pub(crate) fn nb<F, R>(future: F) -> R
929 where
930 F: std::future::Future<Output = R>,
931 {
932 non_blocking(future).unwrap()
933 }
934
935 pub(crate) fn ni<F>(future: F) -> Result<Box<dyn NameIter>>
937 where
938 F: std::future::Future<Output = Result<BoxVertexStream>>,
939 {
940 nb(future).map(to_iter)
941 }
942
943 impl From<&str> for Set {
945 fn from(name: &str) -> Set {
946 Set::from_static_names(
947 name.split_whitespace()
948 .map(|n| Vertex::copy_from(n.as_bytes())),
949 )
950 }
951 }
952
953 impl Set {
954 pub(crate) fn assert_eq(&self, other: Set) {
955 assert!(
956 other.count().unwrap() == self.count().unwrap()
957 && (other.clone() & self.clone()).count().unwrap() == self.count().unwrap(),
958 "set {:?} ({:?}) != {:?} ({:?})",
959 self,
960 self.iter().unwrap().map(|i| i.unwrap()).collect::<Vec<_>>(),
961 &other,
962 other
963 .iter()
964 .unwrap()
965 .map(|i| i.unwrap())
966 .collect::<Vec<_>>(),
967 );
968 }
969 }
970
971 type SizeHint = (u64, Option<u64>);
972
973 #[derive(Default, Debug)]
974 pub(crate) struct VecQuery(Vec<Vertex>, Hints, SizeHint);
975
976 #[async_trait::async_trait]
977 impl AsyncSetQuery for VecQuery {
978 async fn iter(&self) -> Result<BoxVertexStream> {
979 let iter = self.0.clone().into_iter().map(Ok);
980 Ok(Box::pin(futures::stream::iter(iter)))
981 }
982
983 fn as_any(&self) -> &dyn Any {
984 self
985 }
986
987 fn hints(&self) -> &Hints {
988 &self.1
989 }
990
991 async fn size_hint(&self) -> SizeHint {
992 self.2
993 }
994 }
995
996 impl VecQuery {
997 pub(crate) fn from_bytes(bytes: &[u8]) -> Self {
999 let mut used = [false; 256];
1000 let v: Vec<Vertex> = bytes
1001 .iter()
1002 .filter_map(|&b| {
1003 if used[b as usize] {
1004 None
1005 } else {
1006 used[b as usize] = true;
1007 Some(to_name(b))
1008 }
1009 })
1010 .collect();
1011 let size_hint: SizeHint = (v.len() as u64, Some(v.len() as u64));
1012 Self(v, Hints::default(), size_hint)
1013 }
1014
1015 pub(crate) fn adjust_size_hint(mut self, adjust: u64) -> Self {
1020 assert!(adjust <= 6);
1021 self.2.0 = self.2.0.saturating_sub(adjust & 0b1);
1022 self.2.1 = self.2.1.map(|v| v + ((adjust >> 1) & 0b1));
1023 if adjust >= 4 {
1024 self.2.1 = None;
1025 }
1026 self
1027 }
1028 }
1029
1030 pub(crate) fn to_name(value: u8) -> Vertex {
1032 Vertex::from(vec![value; 2])
1033 }
1034
1035 pub(crate) fn shorten_name(name: Vertex) -> String {
1037 name.to_hex()[..2].to_string()
1038 }
1039
1040 pub(crate) fn shorten_iter(iter: Result<Box<dyn NameIter>>) -> Vec<String> {
1042 iter.unwrap()
1043 .map(|v| shorten_name(v.unwrap()))
1044 .collect::<Vec<_>>()
1045 }
1046
1047 #[test]
1048 fn test_empty_query() -> Result<()> {
1049 let query = VecQuery::default();
1050 check_invariants(&query)?;
1051 assert_eq!(SyncSetQuery::iter(&query)?.count(), 0);
1052 assert_eq!(SyncSetQuery::iter_rev(&query)?.count(), 0);
1053 assert_eq!(SyncSetQuery::first(&query)?, None);
1054 assert_eq!(SyncSetQuery::last(&query)?, None);
1055 assert_eq!(SyncSetQuery::count(&query)?, 0);
1056 assert!(SyncSetQuery::is_empty(&query)?);
1057 assert!(!SyncSetQuery::contains(&query, &to_name(0))?);
1058 Ok(())
1059 }
1060
1061 #[test]
1062 fn test_vec_query() -> Result<()> {
1063 let query = VecQuery::from_bytes(b"\xab\xef\xcd");
1064 check_invariants(&query)?;
1065 assert_eq!(shorten_iter(SyncSetQuery::iter(&query)), ["ab", "ef", "cd"]);
1066 assert_eq!(
1067 shorten_iter(SyncSetQuery::iter_rev(&query)),
1068 ["cd", "ef", "ab"]
1069 );
1070 assert_eq!(shorten_name(SyncSetQuery::first(&query)?.unwrap()), "ab");
1071 assert_eq!(shorten_name(SyncSetQuery::last(&query)?.unwrap()), "cd");
1072 assert!(!SyncSetQuery::is_empty(&query)?);
1073 assert!(SyncSetQuery::contains(&query, &to_name(0xef))?);
1074 assert!(!SyncSetQuery::contains(&query, &to_name(0))?);
1075 Ok(())
1076 }
1077
1078 #[test]
1079 fn test_debug() {
1080 let set = Set::from_static_names(vec![to_name(2)])
1081 .union(&Set::from_static_names(vec![to_name(1)]))
1082 .difference(
1083 &Set::from_static_names(vec![to_name(3)])
1084 .intersection(&Set::from_static_names(vec![to_name(2), to_name(3)])),
1085 );
1086 assert_eq!(
1087 dbg(&set),
1088 "<diff <or <static [0202]> <static [0101]>> <and <static [0303]> <static [0202, 0303]>>>"
1089 );
1090 assert_eq!(
1091 format!("\n{:#?}", &set),
1092 r#"
1093<diff
1094 <or
1095 <static [
1096 0202,
1097 ]>
1098 <static [
1099 0101,
1100 ]>>
1101 <and
1102 <static [
1103 0303,
1104 ]>
1105 <static [
1106 0202,
1107 0303,
1108 ]>>>"#
1109 );
1110 }
1111
1112 #[test]
1113 fn test_flatten() {
1114 let set = Set::from_static_names(vec![to_name(2)])
1115 .union(&Set::from_static_names(vec![to_name(1)]))
1116 .difference(
1117 &Set::from_static_names(vec![to_name(3)])
1118 .intersection(&Set::from_static_names(vec![to_name(2), to_name(3)])),
1119 );
1120 assert_eq!(dbg(r(set.flatten()).unwrap()), "<static [0202, 0101]>");
1121 }
1122
1123 #[test]
1124 fn test_union_zip() {
1125 let set1 = Set::from_static_names(vec![to_name(1), to_name(2), to_name(3), to_name(4)]);
1126 let set2 = Set::from_static_names(vec![to_name(5), to_name(6)]);
1127 let unioned = set1.union_zip(&set2);
1128 let names = unioned.iter().unwrap().collect::<Result<Vec<_>>>().unwrap();
1129 assert_eq!(dbg(names), "[0101, 0505, 0202, 0606, 0303, 0404]");
1130 }
1131
1132 #[test]
1133 fn test_ops() {
1134 let ab: Set = "a b".into();
1135 let bc: Set = "b c".into();
1136 let s = |set: Set| -> Vec<String> { shorten_iter(set.iter()) };
1137 assert_eq!(s(ab.clone() | bc.clone()), ["61", "62", "63"]);
1138 assert_eq!(s(ab.clone() & bc.clone()), ["62"]);
1139 assert_eq!(s(ab - bc), ["61"]);
1140 }
1141
1142 #[test]
1143 fn test_skip_take_slow_path() {
1144 let s: Set = "a b c d".into();
1145 let d = |set: Set| -> String { dbg(r(set.flatten_names()).unwrap()) };
1146 assert_eq!(d(s.take(2)), "<static [a, b]>");
1147 assert_eq!(d(s.skip(2)), "<static [c, d]>");
1148 assert_eq!(d(s.skip(1).take(2)), "<static [b, c]>");
1149 }
1150
1151 #[test]
1152 fn test_hints_empty_full_fast_paths() {
1153 let partial: Set = "a".into();
1154 partial.hints().add_flags(Flags::ID_ASC);
1155 let empty: Set = "".into();
1156 let full: Set = "f".into();
1157 full.hints().add_flags(Flags::FULL | Flags::ID_DESC);
1158
1159 assert_eq!(
1160 hints_ops(&partial, &empty),
1161 [
1162 "- Hints(Flags(ID_ASC))",
1163 " Hints(Flags(EMPTY | ID_DESC | ID_ASC | TOPO_DESC | ANCESTORS))",
1164 "& Hints(Flags(EMPTY | ID_DESC | ID_ASC | TOPO_DESC | ANCESTORS))",
1165 " Hints(Flags(EMPTY | ID_DESC | ID_ASC | TOPO_DESC | ANCESTORS))",
1166 "| Hints(Flags(ID_ASC))",
1167 " Hints(Flags(ID_ASC))"
1168 ]
1169 );
1170 assert_eq!(
1172 hints_ops(&partial, &full),
1173 [
1174 "- Hints(Flags(ID_ASC))",
1175 " Hints(Flags(ID_DESC))",
1176 "& Hints(Flags(ID_ASC))",
1177 " Hints(Flags(ID_ASC))",
1178 "| Hints(Flags(0x0))",
1179 " Hints(Flags(0x0))"
1180 ]
1181 );
1182 assert_eq!(
1183 hints_ops(&empty, &full),
1184 [
1185 "- Hints(Flags(EMPTY | ID_DESC | ID_ASC | TOPO_DESC | ANCESTORS))",
1186 " Hints(Flags(FULL | ID_DESC | ANCESTORS))",
1187 "& Hints(Flags(EMPTY | ID_DESC | ID_ASC | TOPO_DESC | ANCESTORS))",
1188 " Hints(Flags(EMPTY | ID_DESC | ID_ASC | TOPO_DESC | ANCESTORS))",
1189 "| Hints(Flags(FULL | ID_DESC | ANCESTORS))",
1190 " Hints(Flags(FULL | ID_DESC | ANCESTORS))"
1191 ]
1192 );
1193 }
1194
1195 #[test]
1196 fn test_hints_full_subset() {
1197 let mut t = crate::tests::TestDag::new();
1198 let a = r(t.dag.all()).unwrap(); t.drawdag("X", &[]);
1200 let b = r(t.dag.all()).unwrap(); t.drawdag("X--Y--Z", &[]);
1202 let c = r(t.dag.all()).unwrap(); let d = r(t.dag.heads(r(t.dag.all()).unwrap())).unwrap(); let a = move || a.clone();
1206 let b = move || b.clone();
1207 let c = move || c.clone();
1208 let d = move || d.clone();
1209 let f = |set: Set| {
1210 let s = dbg(&set);
1211 let v = set
1212 .iter()
1213 .unwrap()
1214 .map(|i| String::from_utf8(i.unwrap().as_ref().to_vec()).unwrap())
1215 .collect::<Vec<String>>()
1216 .join(" ");
1217 format!("{} = [{}]", s, v)
1218 };
1219
1220 assert_eq!(f(a()), "<spans []> = []");
1221 assert_eq!(f(b()), "<spans [X+N0]> = [X]");
1222 assert_eq!(f(c()), "<spans [X:Z+N0:N2]> = [Z Y X]");
1223 assert_eq!(f(d()), "<spans [Z+N2]> = [Z]");
1224
1225 assert_eq!(f(a() - c()), "<empty> = []");
1226 assert_eq!(f(a() - d()), "<spans []> = []");
1227 assert_eq!(f(b() - c()), "<empty> = []");
1228 assert_eq!(f(b() - d()), "<spans [X+N0]> = [X]");
1229 assert_eq!(f(c() - b()), "<spans [Y:Z+N1:N2]> = [Z Y]");
1230 assert_eq!(f(c() - a()), "<spans [X:Z+N0:N2]> = [Z Y X]");
1231 assert_eq!(f(c() - d()), "<spans [X:Y+N0:N1]> = [Y X]");
1232 assert_eq!(f(d() - a()), "<spans [Z+N2]> = [Z]");
1233 assert_eq!(f(d() - b()), "<spans [Z+N2]> = [Z]");
1234 assert_eq!(f(d() - c()), "<empty> = []");
1235
1236 assert_eq!(f(a() | c()), "<spans [X:Z+N0:N2]> = [Z Y X]");
1237 assert_eq!(f(a() | b()), "<spans [X+N0]> = [X]");
1238 assert_eq!(f(a() | d()), "<spans [Z+N2]> = [Z]");
1239 assert_eq!(f(b() | a()), "<spans [X+N0]> = [X]");
1240 assert_eq!(f(b() | c()), "<spans [X:Z+N0:N2]> = [Z Y X]");
1241 assert_eq!(f(b() | d()), "<spans [Z+N2, X+N0]> = [Z X]");
1242 assert_eq!(f(c() | a()), "<spans [X:Z+N0:N2]> = [Z Y X]");
1243 assert_eq!(f(c() | b()), "<spans [X:Z+N0:N2]> = [Z Y X]");
1244 assert_eq!(f(c() | d()), "<spans [X:Z+N0:N2]> = [Z Y X]");
1245 assert_eq!(f(d() | a()), "<spans [Z+N2]> = [Z]");
1246 assert_eq!(f(d() | b()), "<spans [Z+N2, X+N0]> = [Z X]");
1247 assert_eq!(f(d() | c()), "<spans [X:Z+N0:N2]> = [Z Y X]");
1248
1249 assert_eq!(f(a() & c()), "<spans []> = []");
1250 assert_eq!(f(a() & d()), "<empty> = []");
1251 assert_eq!(f(b() & c()), "<spans [X+N0]> = [X]");
1252 assert_eq!(f(c() & a()), "<spans []> = []");
1253 assert_eq!(f(c() & b()), "<spans [X+N0]> = [X]");
1254 assert_eq!(f(c() & d()), "<spans [Z+N2]> = [Z]");
1255 assert_eq!(f(d() & a()), "<empty> = []");
1256 assert_eq!(f(d() & b()), "<spans []> = []");
1257 assert_eq!(f(d() & c()), "<spans [Z+N2]> = [Z]");
1258 }
1259
1260 #[test]
1261 fn test_hints_min_max_id() {
1262 let bc: Set = "b c".into();
1263 bc.hints().set_min_id(Id(20));
1264 bc.hints().add_flags(Flags::ID_DESC);
1265
1266 let ad: Set = "a d".into();
1267 ad.hints().set_max_id(Id(40));
1268 ad.hints().add_flags(Flags::ID_ASC);
1269
1270 assert_eq!(
1271 hints_ops(&bc, &ad),
1272 [
1273 "- Hints(Flags(ID_DESC), 20..)",
1274 " Hints(Flags(ID_ASC), ..=40)",
1275 "& Hints(Flags(ID_DESC), 20..=40)",
1276 " Hints(Flags(ID_ASC), 20..=40)",
1277 "| Hints(Flags(0x0))",
1278 " Hints(Flags(0x0))"
1279 ]
1280 );
1281
1282 ad.hints().set_min_id(Id(10));
1283 bc.hints().set_max_id(Id(30));
1284 assert_eq!(
1285 hints_ops(&bc, &ad),
1286 [
1287 "- Hints(Flags(ID_DESC), 20..=30)",
1288 " Hints(Flags(ID_ASC), 10..=40)",
1289 "& Hints(Flags(ID_DESC), 20..=30)",
1290 " Hints(Flags(ID_ASC), 20..=30)",
1291 "| Hints(Flags(0x0))",
1292 " Hints(Flags(0x0))"
1293 ]
1294 );
1295 }
1296
1297 #[test]
1298 fn test_hints_ancestors() {
1299 let a: Set = "a".into();
1300 a.hints().add_flags(Flags::ANCESTORS);
1301
1302 let b: Set = "b".into();
1303 assert_eq!(
1304 hints_ops(&a, &b),
1305 [
1306 "- Hints(Flags(0x0))",
1307 " Hints(Flags(0x0))",
1308 "& Hints(Flags(0x0))",
1309 " Hints(Flags(0x0))",
1310 "| Hints(Flags(0x0))",
1311 " Hints(Flags(0x0))"
1312 ]
1313 );
1314
1315 b.hints().add_flags(Flags::ANCESTORS);
1316 assert_eq!(
1317 hints_ops(&a, &b),
1318 [
1319 "- Hints(Flags(0x0))",
1320 " Hints(Flags(0x0))",
1321 "& Hints(Flags(ANCESTORS))",
1322 " Hints(Flags(ANCESTORS))",
1323 "| Hints(Flags(ANCESTORS))",
1324 " Hints(Flags(ANCESTORS))"
1325 ]
1326 );
1327 }
1328
1329 #[test]
1330 fn test_filter() {
1331 id_static::tests::with_dag(|dag| {
1332 let sets: Vec<Set> = vec!["C B A".into(), nb(dag.ancestors("C".into())).unwrap()];
1333 for abc in sets {
1334 let filter: Set = abc.filter(Box::new(|v: &Vertex| {
1335 Box::pin(async move { Ok(v.as_ref() != b"A") })
1336 }));
1337 check_invariants(filter.0.as_ref()).unwrap();
1338 assert_eq!(abc.hints().dag_version(), filter.hints().dag_version());
1339 assert_eq!(
1340 abc.hints().id_map_version(),
1341 filter.hints().id_map_version()
1342 );
1343 assert!(filter.hints().flags().contains(Flags::FILTER));
1344 assert!(!filter.hints().flags().contains(Flags::ANCESTORS));
1345 assert_eq!(dbg(r(filter.flatten_names())), "Ok(<static [C, B]>)");
1346 }
1347 })
1348 }
1349
1350 #[test]
1351 fn test_reverse() {
1352 let ab: Set = "a b".into();
1353 let ba = ab.reverse();
1354 check_invariants(&*ba).unwrap();
1355 let names = ba.iter().unwrap().collect::<Result<Vec<_>>>().unwrap();
1356 assert_eq!(dbg(names), "[b, a]");
1357 }
1358
1359 fn hints_ops(lhs: &Set, rhs: &Set) -> Vec<String> {
1361 vec![
1362 (lhs.clone() - rhs.clone(), rhs.clone() - lhs.clone()),
1363 (lhs.clone() & rhs.clone(), rhs.clone() & lhs.clone()),
1364 (lhs.clone() | rhs.clone(), rhs.clone() | lhs.clone()),
1365 ]
1366 .into_iter()
1367 .zip("-&|".chars())
1368 .flat_map(|((set1, set2), ch)| {
1369 vec![
1370 format!("{} {:?}", ch, set1.hints()),
1371 format!(" {:?}", set2.hints()),
1372 ]
1373 })
1374 .collect()
1375 }
1376
1377 pub(crate) fn check_invariants(query: &dyn AsyncSetQuery) -> Result<()> {
1380 let contains_fast_vec: Vec<Option<bool>> = (0..=0xff)
1383 .map(|b| {
1384 let name = Vertex::from(vec![b; 20]);
1385 nb(query.contains_fast(&name)).unwrap_or(None)
1386 })
1387 .collect();
1388 let is_empty = nb(query.is_empty())?;
1389 let count = nb(query.count_slow())?;
1390 let (size_hint_min, size_hint_max) = nb(query.size_hint());
1391 let first = nb(query.first())?;
1392 let last = nb(query.last())?;
1393 let names: Vec<Vertex> = ni(query.iter())?.collect::<Result<Vec<_>>>()?;
1394 assert_eq!(
1395 first,
1396 names.first().cloned(),
1397 "first() should match iter().first() (set: {:?})",
1398 &query
1399 );
1400 assert_eq!(
1401 last,
1402 names.last().cloned(),
1403 "last() should match iter().last() (set: {:?})",
1404 &query
1405 );
1406 assert_eq!(
1407 count,
1408 names.len() as u64,
1409 "count() should match iter().count() (set: {:?})",
1410 &query
1411 );
1412 assert!(
1413 size_hint_min <= count,
1414 "size_hint().0 ({}) must <= count ({}) (set: {:?})",
1415 size_hint_min,
1416 count,
1417 &query
1418 );
1419 if let Some(size_hint_max) = size_hint_max {
1420 assert!(
1421 size_hint_max >= count,
1422 "size_hint().1 ({}) must >= count ({}) (set: {:?})",
1423 size_hint_max,
1424 count,
1425 &query
1426 );
1427 }
1428 assert_eq!(
1429 is_empty,
1430 count == 0,
1431 "is_empty() should match count() == 0 (set: {:?})",
1432 &query
1433 );
1434 assert!(
1435 names
1436 .iter()
1437 .all(|name| nb(query.contains(name)).ok() == Some(true)),
1438 "contains() should return true for names returned by iter() (set: {:?})",
1439 &query
1440 );
1441 assert!(
1442 names
1443 .iter()
1444 .all(|name| nb(query.contains_fast(name)).unwrap_or(None) != Some(false)),
1445 "contains_fast() should not return false for names returned by iter() (set: {:?})",
1446 &query
1447 );
1448 assert!(
1449 (0..=0xff).all(|b| {
1450 let name = Vertex::from(vec![b; 20]);
1451 nb(query.contains(&name)).ok() == Some(names.contains(&name))
1452 }),
1453 "contains() should return false for names not returned by iter() (set: {:?})",
1454 &query
1455 );
1456 assert!(
1457 (0..=0xff)
1458 .zip(contains_fast_vec.into_iter())
1459 .all(|(b, old_contains)| {
1460 let name = Vertex::from(vec![b; 20]);
1461 let contains = nb(query.contains_fast(&name)).unwrap_or(None);
1462 old_contains.is_none() || contains == old_contains
1463 }),
1464 "contains_fast() should be consistent (set: {:?})",
1465 &query
1466 );
1467 assert!(
1468 (0..=0xff).all(|b| {
1469 let name = Vertex::from(vec![b; 20]);
1470 let contains = nb(query.contains_fast(&name)).unwrap_or(None);
1471 contains.is_none() || contains == Some(names.contains(&name))
1472 }),
1473 "contains_fast() should not return true for names not returned by iter() (set: {:?})",
1474 &query
1475 );
1476 if let Some(flatten_id) = query.specialized_flatten_id() {
1477 let iter = r(AsyncSetQuery::iter(&*flatten_id))?;
1478 let mut flatten_names = r(iter.try_collect::<Vec<_>>())?;
1479 flatten_names.sort_unstable();
1480 let mut sorted_names = names.clone();
1481 sorted_names.sort_unstable();
1482 assert_eq!(
1483 &sorted_names, &flatten_names,
1484 "specialized_flatten_id() should return a same set, order could be different (set: {:?})",
1485 &query
1486 );
1487 }
1488 let reversed: Vec<Vertex> = ni(query.iter_rev())?.collect::<Result<Vec<_>>>()?;
1489 if let Some(reversed_set) = query.specialized_reverse() {
1490 let iter = reversed_set.iter()?;
1491 let names = iter.collect::<Result<Vec<_>>>()?;
1492 assert_eq!(&names, &reversed);
1493 }
1494 assert_eq!(
1495 names,
1496 reversed.into_iter().rev().collect::<Vec<Vertex>>(),
1497 "iter() should match iter_rev().rev() (set: {:?})",
1498 &query
1499 );
1500 Ok(())
1501 }
1502
1503 pub(crate) fn check_size_hint_sets<Q: AsyncSetQuery>(build_set: impl Fn(Set, Set) -> Q) {
1506 let lhs = b"\x11\x22\x33";
1507 let rhs = b"\x33\x55\x77";
1508 for lhs_start in 0..lhs.len() {
1509 for lhs_end in lhs_start..lhs.len() {
1510 for rhs_start in 0..rhs.len() {
1511 for rhs_end in rhs_start..rhs.len() {
1512 for lhs_size_hint_adjust in 0..7 {
1513 for rhs_size_hint_adjust in 0..7 {
1514 let lhs_set = VecQuery::from_bytes(&lhs[lhs_start..lhs_end])
1515 .adjust_size_hint(lhs_size_hint_adjust);
1516 let rhs_set = VecQuery::from_bytes(&rhs[rhs_start..rhs_end])
1517 .adjust_size_hint(rhs_size_hint_adjust);
1518 let set =
1519 build_set(Set::from_query(lhs_set), Set::from_query(rhs_set));
1520 check_invariants(&set).unwrap();
1521 }
1522 }
1523 }
1524 }
1525 }
1526 }
1527 }
1528
1529 pub(crate) fn check_skip_take_reverse(set: Set) -> Result<()> {
1530 let names: Vec<Vertex> = set.iter()?.collect::<Result<Vec<_>>>()?;
1531 let len = names.len();
1532 for reverse in [false, true] {
1533 for skip in 0..=(len + 2) {
1534 for take in 0..=(len + 2) {
1535 for skip_first in [false, true] {
1536 let mut test_set = set.clone();
1537 let mut expected_names = names.clone();
1538 if reverse {
1539 test_set = test_set.reverse();
1540 expected_names.reverse();
1541 }
1542 if skip_first {
1543 test_set = test_set.skip(skip as _).take(take as _);
1544 expected_names =
1545 expected_names.into_iter().skip(skip).take(take).collect();
1546 } else {
1547 test_set = test_set.take(take as _).skip(skip as _);
1548 expected_names =
1549 expected_names.into_iter().take(take).skip(skip).collect();
1550 }
1551 let actual_names = test_set.iter()?.collect::<Result<Vec<_>>>()?;
1552 assert_eq!(
1553 actual_names, expected_names,
1554 "check_skip_take_reverse {:?} failed at reverse={reverse} skip={skip} take={take}",
1555 &set
1556 );
1557 }
1558 }
1559 }
1560 }
1561 Ok(())
1562 }
1563
1564 pub(crate) fn fmt_iter(set: &Set) -> String {
1565 let iter = r(AsyncSetQuery::iter(set.deref())).unwrap();
1566 let names = r(iter.try_collect::<Vec<_>>()).unwrap();
1567 dbg(names)
1568 }
1569}