1use std::any::Any;
13use std::cmp;
14use std::fmt;
15use std::fmt::Debug;
16use std::ops::BitAnd;
17use std::ops::BitOr;
18use std::ops::Deref;
19use std::ops::Sub;
20use std::pin::Pin;
21use std::sync::Arc;
22
23use futures::future::BoxFuture;
24use futures::Stream;
25use futures::StreamExt;
26use nonblocking::non_blocking;
27
28use crate::default_impl;
29use crate::ops::DagAlgorithm;
30use crate::ops::IdConvert;
31use crate::ops::IdMapSnapshot;
32use crate::ops::Parents;
33use crate::Id;
34use crate::IdSet;
35use crate::Result;
36use crate::VertexName;
37
38pub mod difference;
39pub mod hints;
40pub mod id_lazy;
41pub mod id_static;
42pub mod intersection;
43pub mod lazy;
44#[cfg(any(test, feature = "indexedlog-backend"))]
45pub mod legacy;
46pub mod meta;
47pub mod slice;
48pub mod r#static;
49pub mod union;
50
51use self::hints::Flags;
52use self::hints::Hints;
53use self::id_static::IdStaticSet;
54use self::meta::MetaSet;
55use self::r#static::StaticSet;
56
57#[derive(Clone)]
62pub struct NameSet(Arc<dyn AsyncNameSetQuery>);
63
64impl NameSet {
65 pub(crate) fn from_query(query: impl AsyncNameSetQuery) -> Self {
66 Self(Arc::new(query))
67 }
68
69 pub fn empty() -> Self {
71 Self::from_query(r#static::StaticSet::empty())
72 }
73
74 pub fn from_static_names(names: impl IntoIterator<Item = VertexName>) -> NameSet {
76 Self::from_query(r#static::StaticSet::from_names(names))
77 }
78
79 pub fn from_iter<I>(iter: I, hints: Hints) -> NameSet
81 where
82 I: IntoIterator<Item = Result<VertexName>> + 'static,
83 <I as IntoIterator>::IntoIter: Send + Sync,
84 {
85 Self::from_query(lazy::LazySet::from_iter(iter, hints))
86 }
87
88 pub fn from_stream(stream: BoxVertexStream, hints: Hints) -> NameSet {
90 Self::from_query(lazy::LazySet::from_stream(stream, hints))
91 }
92
93 pub fn from_id_iter_idmap_dag<I>(
95 iter: I,
96 map: Arc<dyn IdConvert + Send + Sync>,
97 dag: Arc<dyn DagAlgorithm + Send + Sync>,
98 ) -> NameSet
99 where
100 I: IntoIterator<Item = Result<Id>> + 'static,
101 <I as IntoIterator>::IntoIter: Send + Sync,
102 {
103 Self::from_query(id_lazy::IdLazySet::from_iter_idmap_dag(iter, map, dag))
104 }
105
106 pub fn from_id_iter_dag<I>(
108 iter: I,
109 dag: &(impl DagAlgorithm + IdMapSnapshot),
110 ) -> Result<NameSet>
111 where
112 I: IntoIterator<Item = Result<Id>> + 'static,
113 <I as IntoIterator>::IntoIter: Send + Sync,
114 {
115 let map = dag.id_map_snapshot()?;
116 let dag = dag.dag_snapshot()?;
117 Ok(Self::from_id_iter_idmap_dag(iter, map, dag))
118 }
119
120 pub fn from_spans_idmap_dag(
122 spans: IdSet,
123 map: Arc<dyn IdConvert + Send + Sync>,
124 dag: Arc<dyn DagAlgorithm + Send + Sync>,
125 ) -> NameSet {
126 Self::from_query(IdStaticSet::from_spans_idmap_dag(spans, map, dag))
127 }
128
129 pub fn from_spans_dag(spans: IdSet, dag: &(impl DagAlgorithm + IdMapSnapshot)) -> Result<Self> {
131 let map = dag.id_map_snapshot()?;
132 let dag = dag.dag_snapshot()?;
133 Ok(Self::from_spans_idmap_dag(spans, map, dag))
134 }
135
136 pub fn from_evaluate_contains<C>(
139 evaluate: impl Fn() -> Result<NameSet> + Send + Sync + 'static,
140 contains: C,
141 hints: Hints,
142 ) -> NameSet
143 where
144 C: for<'a> Fn(&'a MetaSet, &'a VertexName) -> Result<bool>,
145 C: Send + Sync + 'static,
146 {
147 let evaluate = move || -> BoxFuture<_> {
148 let result = evaluate();
149 Box::pin(async move { result })
150 };
151 let contains = Arc::new(contains);
152 Self::from_async_evaluate_contains(
153 Box::new(evaluate),
154 Box::new(move |m, v| {
155 let contains = contains.clone();
156 Box::pin(async move { contains(m, v) })
157 }),
158 hints,
159 )
160 }
161
162 pub fn from_async_evaluate_contains(
165 evaluate: Box<dyn Fn() -> BoxFuture<'static, Result<NameSet>> + Send + Sync>,
166 contains: Box<
167 dyn for<'a> Fn(&'a MetaSet, &'a VertexName) -> BoxFuture<'a, Result<bool>>
168 + Send
169 + Sync,
170 >,
171 hints: Hints,
172 ) -> NameSet {
173 Self::from_query(MetaSet::from_evaluate_hints(evaluate, hints).with_contains(contains))
174 }
175
176 pub fn difference(&self, other: &NameSet) -> NameSet {
178 if other.hints().contains(Flags::FULL)
179 && other.hints().dag_version() >= self.hints().dag_version()
180 && self.hints().dag_version() > None
181 {
182 tracing::debug!(
183 "difference(x={:.6?}, y={:.6?}) = () (fast path 1)",
184 self,
185 other
186 );
187 return Self::empty();
188 }
189 if self.hints().contains(Flags::EMPTY) || other.hints().contains(Flags::EMPTY) {
190 tracing::debug!(
191 "difference(x={:.6?}, y={:.6?}) = x (fast path 2)",
192 self,
193 other
194 );
195 return self.clone();
196 }
197 if let (Some(this), Some(other)) = (
198 self.as_any().downcast_ref::<IdStaticSet>(),
199 other.as_any().downcast_ref::<IdStaticSet>(),
200 ) {
201 let order = this.map.map_version().partial_cmp(other.map.map_version());
202 if order.is_some() {
203 let result = Self::from_spans_idmap_dag(
205 this.spans.difference(&other.spans),
206 this.map.clone(),
207 this.dag.clone(),
208 );
209 tracing::debug!(
210 "difference(x={:.6?}, y={:.6?}) = {:.6?} (fast path 3)",
211 self,
212 other,
213 &result
214 );
215 return result;
216 }
217 }
218 tracing::debug!("difference(x={:.6?}, y={:.6?}) (slow path)", self, other);
219 Self::from_query(difference::DifferenceSet::new(self.clone(), other.clone()))
220 }
221
222 pub fn intersection(&self, other: &NameSet) -> NameSet {
224 if self.hints().contains(Flags::FULL)
225 && self.hints().dag_version() >= other.hints().dag_version()
226 && other.hints().dag_version() > None
227 {
228 tracing::debug!(
229 "intersection(x={:.6?}, y={:.6?}) = y (fast path 1)",
230 self,
231 other
232 );
233 return other.clone();
234 }
235 if other.hints().contains(Flags::FULL)
236 && other.hints().dag_version() >= self.hints().dag_version()
237 && self.hints().dag_version() > None
238 {
239 tracing::debug!(
240 "intersection(x={:.6?}, y={:.6?}) = x (fast path 2)",
241 self,
242 other
243 );
244 return self.clone();
245 }
246 if self.hints().contains(Flags::EMPTY) || other.hints().contains(Flags::EMPTY) {
247 tracing::debug!(
248 "intersection(x={:.6?}, y={:.6?}) = () (fast path 3)",
249 self,
250 other
251 );
252 return Self::empty();
253 }
254 if let (Some(this), Some(other)) = (
255 self.as_any().downcast_ref::<IdStaticSet>(),
256 other.as_any().downcast_ref::<IdStaticSet>(),
257 ) {
258 let order = this.map.map_version().partial_cmp(other.map.map_version());
259 if let Some(order) = order {
260 let result = Self::from_spans_idmap_dag(
262 this.spans.intersection(&other.spans),
263 pick(order, &this.map, &other.map).clone(),
264 pick(order, &this.dag, &other.dag).clone(),
265 );
266 tracing::debug!(
267 "intersection(x={:.6?}, y={:.6?}) = {:?} (IdStatic fast path)",
268 self,
269 other,
270 &result
271 );
272 return result;
273 }
274 }
275 tracing::debug!("intersection(x={:.6?}, y={:.6?}) (slow path)", self, other,);
276 Self::from_query(intersection::IntersectionSet::new(
277 self.clone(),
278 other.clone(),
279 ))
280 }
281
282 pub fn union(&self, other: &NameSet) -> NameSet {
284 if (self.hints().contains(Flags::FULL)
285 && self.hints().dag_version() >= other.hints().dag_version()
286 && other.hints().dag_version() > None)
287 || other.hints().contains(Flags::EMPTY)
288 {
289 tracing::debug!("union(x={:.6?}, y={:.6?}) = x (fast path 1)", self, other);
290 return self.clone();
291 }
292 if self.hints().contains(Flags::EMPTY)
293 || (other.hints().contains(Flags::FULL)
294 && other.hints().dag_version() >= self.hints().dag_version()
295 && self.hints().dag_version() > None)
296 {
297 tracing::debug!("union(x={:.6?}, y={:.6?}) = y (fast path 2)", self, other);
298 return other.clone();
299 }
300 if let (Some(this), Some(other)) = (
301 self.as_any().downcast_ref::<IdStaticSet>(),
302 other.as_any().downcast_ref::<IdStaticSet>(),
303 ) {
304 let order = this.map.map_version().partial_cmp(other.map.map_version());
305 if let Some(order) = order {
306 let result = Self::from_spans_idmap_dag(
308 this.spans.union(&other.spans),
309 pick(order, &this.map, &other.map).clone(),
310 pick(order, &this.dag, &other.dag).clone(),
311 );
312 tracing::debug!(
313 "union(x={:.6?}, y={:.6?}) = {:.6?} (fast path 3)",
314 self,
315 other,
316 &result
317 );
318 return result;
319 }
320 }
321 tracing::debug!("union(x={:.6?}, y={:.6?}) (slow path)", self, other);
322 Self::from_query(union::UnionSet::new(self.clone(), other.clone()))
323 }
324
325 pub fn filter(
328 &self,
329 filter_func: Box<dyn Fn(&VertexName) -> BoxFuture<Result<bool>> + Send + Sync + 'static>,
330 ) -> Self {
331 let filter_func = Arc::new(filter_func);
332 let this = self.clone();
333 let hints = {
334 let hints = self.hints().clone();
336 hints.update_flags_with(|f| (f - Flags::ANCESTORS - Flags::FULL) | Flags::FILTER);
337 hints
338 };
339 let result = Self::from_async_evaluate_contains(
340 Box::new({
341 let filter_func = filter_func.clone();
342 let this = this.clone();
343 let hints = hints.clone();
344 move || {
345 let filter_func = filter_func.clone();
346 let this = this.clone();
347 let hints = hints.clone();
348 Box::pin(async move {
349 let stream = this.0.iter().await?;
350 let stream = stream.filter_map(move |v| {
351 let filter_func = filter_func.clone();
352 async move {
353 match v {
354 Ok(v) => match (&filter_func)(&v).await {
355 Ok(true) => Some(Ok(v)),
356 Ok(false) => None,
357 Err(e) => Some(Err(e)),
358 },
359 Err(e) => Some(Err(e)),
360 }
361 }
362 });
363 Ok(Self::from_stream(Box::pin(stream), hints))
364 })
365 }
366 }),
367 Box::new(move |_, v| {
368 let filter_func = filter_func.clone();
369 let this = this.clone();
370 Box::pin(async move { Ok(this.0.contains(v).await? && (&filter_func)(v).await?) })
371 }),
372 hints,
373 );
374 result.hints().add_flags(Flags::FILTER);
375 result
376 }
377
378 pub async fn to_parents(&self) -> Result<Option<impl Parents>> {
381 default_impl::set_to_parents(self).await
382 }
383
384 pub fn dag(&self) -> Option<Arc<dyn DagAlgorithm + Send + Sync>> {
386 self.hints().dag()
387 }
388
389 pub fn id_map(&self) -> Option<Arc<dyn IdConvert + Send + Sync>> {
391 self.hints().id_map()
392 }
393
394 pub async fn flatten(&self) -> Result<NameSet> {
398 match (self.id_map(), self.dag()) {
399 (Some(id_map), Some(dag)) => {
400 self.flatten_id(id_map, dag).await
402 }
403 _ => {
404 self.flatten_names().await
406 }
407 }
408 }
409
410 pub async fn flatten_id(
412 &self,
413 id_map: Arc<dyn IdConvert + Send + Sync>,
414 dag: Arc<dyn DagAlgorithm + Send + Sync>,
415 ) -> Result<NameSet> {
416 if self.as_any().is::<IdStaticSet>() {
417 return Ok(self.clone());
418 }
419 let mut ids = Vec::with_capacity(self.count()?);
420 for vertex in self.iter()? {
421 let id = id_map.vertex_id(vertex?).await?;
422 ids.push(id);
423 }
424 ids.sort_unstable_by_key(|i| u64::MAX - i.0);
425 let spans = IdSet::from_sorted_spans(ids);
426 let flat_set = NameSet::from_spans_idmap_dag(spans, id_map, dag);
427 flat_set.hints().inherit_flags_min_max_id(self.hints());
428 Ok(flat_set)
429 }
430
431 pub async fn flatten_names(&self) -> Result<NameSet> {
433 if self.as_any().is::<StaticSet>() {
434 return Ok(self.clone());
435 }
436 let names = self.iter()?.collect::<Result<Vec<_>>>()?;
437 let flat_set = Self::from_static_names(names);
438 flat_set.hints().inherit_flags_min_max_id(self.hints());
439 Ok(flat_set)
440 }
441
442 pub fn take(&self, n: u64) -> NameSet {
444 if let Some(set) = self.as_any().downcast_ref::<IdStaticSet>() {
445 tracing::debug!("take(x={:.6?}, {}) (fast path)", self, n);
446 Self::from_spans_idmap_dag(set.spans.take(n), set.map.clone(), set.dag.clone())
447 } else {
448 tracing::debug!("take(x={:.6?}, {}) (slow path)", self, n);
449 let set = slice::SliceSet::new(self.clone(), 0, Some(n));
450 Self::from_query(set)
451 }
452 }
453
454 pub fn skip(&self, n: u64) -> NameSet {
456 if n == 0 {
457 return self.clone();
458 }
459 if let Some(set) = self.as_any().downcast_ref::<IdStaticSet>() {
460 tracing::debug!("skip(x={:.6?}, {}) (fast path)", self, n);
461 Self::from_spans_idmap_dag(set.spans.skip(n), set.map.clone(), set.dag.clone())
462 } else {
463 tracing::debug!("skip(x={:.6?}, {}) (slow path)", self, n);
464 let set = slice::SliceSet::new(self.clone(), n, None);
465 Self::from_query(set)
466 }
467 }
468
469 pub fn to_id_set_and_id_map_in_o1(&self) -> Option<(IdSet, Arc<dyn IdConvert + Send + Sync>)> {
475 let id_map = self.id_map()?;
476 let id_set = self.as_any().downcast_ref::<IdStaticSet>()?.spans.clone();
477 Some((id_set, id_map))
478 }
479}
480
481impl BitAnd for NameSet {
482 type Output = Self;
483
484 fn bitand(self, other: Self) -> Self {
485 self.intersection(&other)
486 }
487}
488
489impl BitOr for NameSet {
490 type Output = Self;
491
492 fn bitor(self, other: Self) -> Self {
493 self.union(&other)
494 }
495}
496
497impl Sub for NameSet {
498 type Output = Self;
499
500 fn sub(self, other: Self) -> Self {
501 self.difference(&other)
502 }
503}
504
505impl Deref for NameSet {
506 type Target = dyn AsyncNameSetQuery;
507
508 fn deref(&self) -> &Self::Target {
509 self.0.deref()
510 }
511}
512
513impl fmt::Debug for NameSet {
514 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
515 self.0.fmt(f)
516 }
517}
518
519#[async_trait::async_trait]
524pub trait AsyncNameSetQuery: Any + Debug + Send + Sync {
525 async fn iter(&self) -> Result<BoxVertexStream>;
527
528 async fn iter_rev(&self) -> Result<BoxVertexStream> {
530 let mut iter = self.iter().await?;
531 let mut items = Vec::new();
532 while let Some(item) = iter.next().await {
533 items.push(item);
534 }
535 Ok(Box::pin(futures::stream::iter(items.into_iter().rev())))
536 }
537
538 async fn count(&self) -> Result<usize> {
540 let mut iter = self.iter().await?;
541 let mut count = 0;
542 while let Some(item) = iter.next().await {
543 item?;
544 count += 1;
545 }
546 Ok(count)
547 }
548
549 async fn first(&self) -> Result<Option<VertexName>> {
551 self.iter().await?.next().await.transpose()
552 }
553
554 async fn last(&self) -> Result<Option<VertexName>> {
556 self.iter_rev().await?.next().await.transpose()
557 }
558
559 async fn is_empty(&self) -> Result<bool> {
561 self.first().await.map(|n| n.is_none())
562 }
563
564 async fn contains(&self, name: &VertexName) -> Result<bool> {
566 let mut iter = self.iter().await?;
567 while let Some(item) = iter.next().await {
568 if &item? == name {
569 return Ok(true);
570 }
571 }
572 Ok(false)
573 }
574
575 async fn contains_fast(&self, name: &VertexName) -> Result<Option<bool>> {
578 let _ = name;
579 Ok(None)
580 }
581
582 fn as_any(&self) -> &dyn Any;
584
585 fn hints(&self) -> &Hints;
587
588 fn id_convert(&self) -> Option<&dyn IdConvert> {
590 None
591 }
592}
593
594pub trait SyncNameSetQuery {
596 fn iter(&self) -> Result<Box<dyn NameIter>>;
598
599 fn iter_rev(&self) -> Result<Box<dyn NameIter>>;
601
602 fn count(&self) -> Result<usize>;
604
605 fn first(&self) -> Result<Option<VertexName>>;
607
608 fn last(&self) -> Result<Option<VertexName>>;
610
611 fn is_empty(&self) -> Result<bool>;
613
614 fn contains(&self, name: &VertexName) -> Result<bool>;
616
617 fn as_any(&self) -> &dyn Any;
619
620 fn hints(&self) -> &Hints;
622
623 fn id_convert(&self) -> Option<&dyn IdConvert>;
625}
626
627impl<T: AsyncNameSetQuery> SyncNameSetQuery for T {
628 fn iter(&self) -> Result<Box<dyn NameIter>> {
629 non_blocking(AsyncNameSetQuery::iter(self))?.map(to_iter)
630 }
631
632 fn iter_rev(&self) -> Result<Box<dyn NameIter>> {
633 non_blocking(AsyncNameSetQuery::iter_rev(self))?.map(to_iter)
634 }
635
636 fn count(&self) -> Result<usize> {
637 non_blocking(AsyncNameSetQuery::count(self))?
638 }
639
640 fn first(&self) -> Result<Option<VertexName>> {
641 non_blocking(AsyncNameSetQuery::first(self))?
642 }
643
644 fn last(&self) -> Result<Option<VertexName>> {
645 non_blocking(AsyncNameSetQuery::last(self))?
646 }
647
648 fn is_empty(&self) -> Result<bool> {
649 non_blocking(AsyncNameSetQuery::is_empty(self))?
650 }
651
652 fn contains(&self, name: &VertexName) -> Result<bool> {
653 non_blocking(AsyncNameSetQuery::contains(self, name))?
654 }
655
656 fn as_any(&self) -> &dyn Any {
657 AsyncNameSetQuery::as_any(self)
658 }
659
660 fn hints(&self) -> &Hints {
661 AsyncNameSetQuery::hints(self)
662 }
663
664 fn id_convert(&self) -> Option<&dyn IdConvert> {
665 AsyncNameSetQuery::id_convert(self)
666 }
667}
668
669impl SyncNameSetQuery for NameSet {
670 fn iter(&self) -> Result<Box<dyn NameIter>> {
671 non_blocking(AsyncNameSetQuery::iter(self.0.deref()))?.map(to_iter)
672 }
673
674 fn iter_rev(&self) -> Result<Box<dyn NameIter>> {
675 non_blocking(AsyncNameSetQuery::iter_rev(self.0.deref()))?.map(to_iter)
676 }
677
678 fn count(&self) -> Result<usize> {
679 non_blocking(AsyncNameSetQuery::count(self.0.deref()))?
680 }
681
682 fn first(&self) -> Result<Option<VertexName>> {
683 non_blocking(AsyncNameSetQuery::first(self.0.deref()))?
684 }
685
686 fn last(&self) -> Result<Option<VertexName>> {
687 non_blocking(AsyncNameSetQuery::last(self.0.deref()))?
688 }
689
690 fn is_empty(&self) -> Result<bool> {
691 non_blocking(AsyncNameSetQuery::is_empty(self.0.deref()))?
692 }
693
694 fn contains(&self, name: &VertexName) -> Result<bool> {
695 non_blocking(AsyncNameSetQuery::contains(self.0.deref(), name))?
696 }
697
698 fn as_any(&self) -> &dyn Any {
699 AsyncNameSetQuery::as_any(self.0.deref())
700 }
701
702 fn hints(&self) -> &Hints {
703 AsyncNameSetQuery::hints(self.0.deref())
704 }
705
706 fn id_convert(&self) -> Option<&dyn IdConvert> {
707 AsyncNameSetQuery::id_convert(self.0.deref())
708 }
709}
710
711pub trait NameIter: Iterator<Item = Result<VertexName>> + Send {}
715impl<T> NameIter for T where T: Iterator<Item = Result<VertexName>> + Send {}
716
717pub trait VertexStream: Stream<Item = Result<VertexName>> + Send {}
719impl<T> VertexStream for T where T: Stream<Item = Result<VertexName>> + Send {}
720
721pub type BoxVertexStream = Pin<Box<dyn VertexStream>>;
723
724struct NonblockingNameIter(BoxVertexStream);
726
727impl Iterator for NonblockingNameIter {
728 type Item = Result<VertexName>;
729
730 fn next(&mut self) -> Option<Self::Item> {
731 match non_blocking(self.0.next()) {
732 Err(e) => Some(Err(e.into())),
733 Ok(v) => v,
734 }
735 }
736}
737
738fn to_iter(stream: BoxVertexStream) -> Box<dyn NameIter> {
739 Box::new(NonblockingNameIter(stream))
740}
741
742impl From<VertexName> for NameSet {
743 fn from(name: VertexName) -> NameSet {
744 NameSet::from_static_names(std::iter::once(name))
745 }
746}
747
748impl From<&VertexName> for NameSet {
749 fn from(name: &VertexName) -> NameSet {
750 NameSet::from_static_names(std::iter::once(name.clone()))
751 }
752}
753
754fn pick<T>(order: cmp::Ordering, left: T, right: T) -> T {
757 match order {
758 cmp::Ordering::Greater | cmp::Ordering::Equal => left,
759 cmp::Ordering::Less => right,
760 }
761}
762
763#[cfg(test)]
764pub(crate) mod tests {
765 use nonblocking::non_blocking_result as r;
766
767 use super::*;
768 use crate::Id;
769
770 pub(crate) fn nb<F, R>(future: F) -> R
771 where
772 F: std::future::Future<Output = R>,
773 {
774 non_blocking(future).unwrap()
775 }
776
777 pub(crate) fn ni<F>(future: F) -> Result<Box<dyn NameIter>>
779 where
780 F: std::future::Future<Output = Result<BoxVertexStream>>,
781 {
782 nb(future).map(to_iter)
783 }
784
785 impl From<&str> for NameSet {
787 fn from(name: &str) -> NameSet {
788 NameSet::from_static_names(
789 name.split_whitespace()
790 .map(|n| VertexName::copy_from(n.as_bytes())),
791 )
792 }
793 }
794
795 impl NameSet {
796 pub(crate) fn assert_eq(&self, other: NameSet) {
797 assert!(
798 other.count().unwrap() == self.count().unwrap()
799 && (other.clone() & self.clone()).count().unwrap() == self.count().unwrap(),
800 "set {:?} ({:?}) != {:?} ({:?})",
801 self,
802 self.iter().unwrap().map(|i| i.unwrap()).collect::<Vec<_>>(),
803 &other,
804 other
805 .iter()
806 .unwrap()
807 .map(|i| i.unwrap())
808 .collect::<Vec<_>>(),
809 );
810 }
811 }
812
813 #[derive(Default, Debug)]
814 pub(crate) struct VecQuery(Vec<VertexName>, Hints);
815
816 #[async_trait::async_trait]
817 impl AsyncNameSetQuery for VecQuery {
818 async fn iter(&self) -> Result<BoxVertexStream> {
819 let iter = self.0.clone().into_iter().map(Ok);
820 Ok(Box::pin(futures::stream::iter(iter)))
821 }
822
823 fn as_any(&self) -> &dyn Any {
824 self
825 }
826
827 fn hints(&self) -> &Hints {
828 &self.1
829 }
830 }
831
832 impl VecQuery {
833 pub(crate) fn from_bytes(bytes: &[u8]) -> Self {
835 let mut used = [false; 256];
836 Self(
837 bytes
838 .iter()
839 .filter_map(|&b| {
840 if used[b as usize] {
841 None
842 } else {
843 used[b as usize] = true;
844 Some(to_name(b))
845 }
846 })
847 .collect(),
848 Hints::default(),
849 )
850 }
851 }
852
853 pub(crate) fn to_name(value: u8) -> VertexName {
855 VertexName::from(vec![value; 2])
856 }
857
858 pub(crate) fn shorten_name(name: VertexName) -> String {
860 name.to_hex()[..2].to_string()
861 }
862
863 pub(crate) fn shorten_iter(iter: Result<Box<dyn NameIter>>) -> Vec<String> {
865 iter.unwrap()
866 .map(|v| shorten_name(v.unwrap()))
867 .collect::<Vec<_>>()
868 }
869
870 #[test]
871 fn test_empty_query() -> Result<()> {
872 let query = VecQuery::default();
873 check_invariants(&query)?;
874 assert_eq!(SyncNameSetQuery::iter(&query)?.count(), 0);
875 assert_eq!(SyncNameSetQuery::iter_rev(&query)?.count(), 0);
876 assert_eq!(SyncNameSetQuery::first(&query)?, None);
877 assert_eq!(SyncNameSetQuery::last(&query)?, None);
878 assert_eq!(SyncNameSetQuery::count(&query)?, 0);
879 assert!(SyncNameSetQuery::is_empty(&query)?);
880 assert!(!SyncNameSetQuery::contains(&query, &to_name(0))?);
881 Ok(())
882 }
883
884 #[test]
885 fn test_vec_query() -> Result<()> {
886 let query = VecQuery::from_bytes(b"\xab\xef\xcd");
887 check_invariants(&query)?;
888 assert_eq!(
889 shorten_iter(SyncNameSetQuery::iter(&query)),
890 ["ab", "ef", "cd"]
891 );
892 assert_eq!(
893 shorten_iter(SyncNameSetQuery::iter_rev(&query)),
894 ["cd", "ef", "ab"]
895 );
896 assert_eq!(
897 shorten_name(SyncNameSetQuery::first(&query)?.unwrap()),
898 "ab"
899 );
900 assert_eq!(shorten_name(SyncNameSetQuery::last(&query)?.unwrap()), "cd");
901 assert!(!SyncNameSetQuery::is_empty(&query)?);
902 assert!(SyncNameSetQuery::contains(&query, &to_name(0xef))?);
903 assert!(!SyncNameSetQuery::contains(&query, &to_name(0))?);
904 Ok(())
905 }
906
907 #[test]
908 fn test_debug() {
909 let set = NameSet::from_static_names(vec![to_name(2)])
910 .union(&NameSet::from_static_names(vec![to_name(1)]))
911 .difference(
912 &NameSet::from_static_names(vec![to_name(3)])
913 .intersection(&NameSet::from_static_names(vec![to_name(2), to_name(3)])),
914 );
915 assert_eq!(
916 format!("{:?}", &set),
917 "<diff <or <static [0202]> <static [0101]>> <and <static [0303]> <static [0202, 0303]>>>"
918 );
919 assert_eq!(
920 format!("\n{:#?}", &set),
921 r#"
922<diff
923 <or
924 <static [
925 0202,
926 ]>
927 <static [
928 0101,
929 ]>>
930 <and
931 <static [
932 0303,
933 ]>
934 <static [
935 0202,
936 0303,
937 ]>>>"#
938 );
939 }
940
941 #[test]
942 fn test_flatten() {
943 let set = NameSet::from_static_names(vec![to_name(2)])
944 .union(&NameSet::from_static_names(vec![to_name(1)]))
945 .difference(
946 &NameSet::from_static_names(vec![to_name(3)])
947 .intersection(&NameSet::from_static_names(vec![to_name(2), to_name(3)])),
948 );
949 assert_eq!(
950 format!("{:?}", r(set.flatten()).unwrap()),
951 "<static [0202, 0101]>"
952 );
953 }
954
955 #[test]
956 fn test_ops() {
957 let ab: NameSet = "a b".into();
958 let bc: NameSet = "b c".into();
959 let s = |set: NameSet| -> Vec<String> { shorten_iter(set.iter()) };
960 assert_eq!(s(ab.clone() | bc.clone()), ["61", "62", "63"]);
961 assert_eq!(s(ab.clone() & bc.clone()), ["62"]);
962 assert_eq!(s(ab.clone() - bc.clone()), ["61"]);
963 }
964
965 #[test]
966 fn test_skip_take_slow_path() {
967 let s: NameSet = "a b c d".into();
968 let d = |set: NameSet| -> String { format!("{:?}", r(set.flatten_names()).unwrap()) };
969 assert_eq!(d(s.take(2)), "<static [a, b]>");
970 assert_eq!(d(s.skip(2)), "<static [c, d]>");
971 assert_eq!(d(s.skip(1).take(2)), "<static [b, c]>");
972 }
973
974 #[test]
975 fn test_hints_empty_full_fast_paths() {
976 let partial: NameSet = "a".into();
977 partial.hints().add_flags(Flags::ID_ASC);
978 let empty: NameSet = "".into();
979 let full: NameSet = "f".into();
980 full.hints().add_flags(Flags::FULL | Flags::ID_DESC);
981
982 assert_eq!(
983 hints_ops(&partial, &empty),
984 [
985 "- Hints(ID_ASC)",
986 " Hints(EMPTY | ID_DESC | ID_ASC | TOPO_DESC | ANCESTORS)",
987 "& Hints(EMPTY | ID_DESC | ID_ASC | TOPO_DESC | ANCESTORS)",
988 " Hints(EMPTY | ID_DESC | ID_ASC | TOPO_DESC | ANCESTORS)",
989 "| Hints(ID_ASC)",
990 " Hints(ID_ASC)"
991 ]
992 );
993 assert_eq!(
995 hints_ops(&partial, &full),
996 [
997 "- Hints(ID_ASC)",
998 " Hints(ID_DESC)",
999 "& Hints(ID_ASC)",
1000 " Hints(ID_ASC)",
1001 "| Hints((empty))",
1002 " Hints((empty))"
1003 ]
1004 );
1005 assert_eq!(
1006 hints_ops(&empty, &full),
1007 [
1008 "- Hints(EMPTY | ID_DESC | ID_ASC | TOPO_DESC | ANCESTORS)",
1009 " Hints(FULL | ID_DESC | ANCESTORS)",
1010 "& Hints(EMPTY | ID_DESC | ID_ASC | TOPO_DESC | ANCESTORS)",
1011 " Hints(EMPTY | ID_DESC | ID_ASC | TOPO_DESC | ANCESTORS)",
1012 "| Hints(FULL | ID_DESC | ANCESTORS)",
1013 " Hints(FULL | ID_DESC | ANCESTORS)"
1014 ]
1015 );
1016 }
1017
1018 #[test]
1019 fn test_hints_full_subset() {
1020 let mut t = crate::tests::TestDag::new();
1021 let a = r(t.dag.all()).unwrap(); t.drawdag("X", &[]);
1023 let b = r(t.dag.all()).unwrap(); t.drawdag("X--Y--Z", &[]);
1025 let c = r(t.dag.all()).unwrap(); let d = r(t.dag.heads(r(t.dag.all()).unwrap())).unwrap(); let a = move || a.clone();
1029 let b = move || b.clone();
1030 let c = move || c.clone();
1031 let d = move || d.clone();
1032 let f = |set: NameSet| {
1033 let s = format!("{:?}", &set);
1034 let v = set
1035 .iter()
1036 .unwrap()
1037 .map(|i| String::from_utf8(i.unwrap().as_ref().to_vec()).unwrap())
1038 .collect::<Vec<String>>()
1039 .join(" ");
1040 format!("{} = [{}]", s, v)
1041 };
1042
1043 assert_eq!(f(a()), "<spans []> = []");
1044 assert_eq!(f(b()), "<spans [X+N0]> = [X]");
1045 assert_eq!(f(c()), "<spans [X:Z+N0:N2]> = [Z Y X]");
1046 assert_eq!(f(d()), "<spans [Z+N2]> = [Z]");
1047
1048 assert_eq!(f(a() - c()), "<empty> = []");
1049 assert_eq!(f(a() - d()), "<spans []> = []");
1050 assert_eq!(f(b() - c()), "<empty> = []");
1051 assert_eq!(f(b() - d()), "<spans [X+N0]> = [X]");
1052 assert_eq!(f(c() - b()), "<spans [Y:Z+N1:N2]> = [Z Y]");
1053 assert_eq!(f(c() - a()), "<spans [X:Z+N0:N2]> = [Z Y X]");
1054 assert_eq!(f(c() - d()), "<spans [X:Y+N0:N1]> = [Y X]");
1055 assert_eq!(f(d() - a()), "<spans [Z+N2]> = [Z]");
1056 assert_eq!(f(d() - b()), "<spans [Z+N2]> = [Z]");
1057 assert_eq!(f(d() - c()), "<empty> = []");
1058
1059 assert_eq!(f(a() | c()), "<spans [X:Z+N0:N2]> = [Z Y X]");
1060 assert_eq!(f(a() | b()), "<spans [X+N0]> = [X]");
1061 assert_eq!(f(a() | d()), "<spans [Z+N2]> = [Z]");
1062 assert_eq!(f(b() | a()), "<spans [X+N0]> = [X]");
1063 assert_eq!(f(b() | c()), "<spans [X:Z+N0:N2]> = [Z Y X]");
1064 assert_eq!(f(b() | d()), "<spans [Z+N2, X+N0]> = [Z X]");
1065 assert_eq!(f(c() | a()), "<spans [X:Z+N0:N2]> = [Z Y X]");
1066 assert_eq!(f(c() | b()), "<spans [X:Z+N0:N2]> = [Z Y X]");
1067 assert_eq!(f(c() | d()), "<spans [X:Z+N0:N2]> = [Z Y X]");
1068 assert_eq!(f(d() | a()), "<spans [Z+N2]> = [Z]");
1069 assert_eq!(f(d() | b()), "<spans [Z+N2, X+N0]> = [Z X]");
1070 assert_eq!(f(d() | c()), "<spans [X:Z+N0:N2]> = [Z Y X]");
1071
1072 assert_eq!(f(a() & c()), "<spans []> = []");
1073 assert_eq!(f(a() & d()), "<empty> = []");
1074 assert_eq!(f(b() & c()), "<spans [X+N0]> = [X]");
1075 assert_eq!(f(c() & a()), "<spans []> = []");
1076 assert_eq!(f(c() & b()), "<spans [X+N0]> = [X]");
1077 assert_eq!(f(c() & d()), "<spans [Z+N2]> = [Z]");
1078 assert_eq!(f(d() & a()), "<empty> = []");
1079 assert_eq!(f(d() & b()), "<spans []> = []");
1080 assert_eq!(f(d() & c()), "<spans [Z+N2]> = [Z]");
1081 }
1082
1083 #[test]
1084 fn test_hints_min_max_id() {
1085 let bc: NameSet = "b c".into();
1086 bc.hints().set_min_id(Id(20));
1087 bc.hints().add_flags(Flags::ID_DESC);
1088
1089 let ad: NameSet = "a d".into();
1090 ad.hints().set_max_id(Id(40));
1091 ad.hints().add_flags(Flags::ID_ASC);
1092
1093 assert_eq!(
1094 hints_ops(&bc, &ad),
1095 [
1096 "- Hints(ID_DESC, 20..)",
1097 " Hints(ID_ASC, ..=40)",
1098 "& Hints(ID_DESC, 20..=40)",
1099 " Hints(ID_ASC, 20..=40)",
1100 "| Hints((empty))",
1101 " Hints((empty))"
1102 ]
1103 );
1104
1105 ad.hints().set_min_id(Id(10));
1106 bc.hints().set_max_id(Id(30));
1107 assert_eq!(
1108 hints_ops(&bc, &ad),
1109 [
1110 "- Hints(ID_DESC, 20..=30)",
1111 " Hints(ID_ASC, 10..=40)",
1112 "& Hints(ID_DESC, 20..=30)",
1113 " Hints(ID_ASC, 20..=30)",
1114 "| Hints((empty))",
1115 " Hints((empty))"
1116 ]
1117 );
1118 }
1119
1120 #[test]
1121 fn test_hints_ancestors() {
1122 let a: NameSet = "a".into();
1123 a.hints().add_flags(Flags::ANCESTORS);
1124
1125 let b: NameSet = "b".into();
1126 assert_eq!(
1127 hints_ops(&a, &b),
1128 [
1129 "- Hints((empty))",
1130 " Hints((empty))",
1131 "& Hints((empty))",
1132 " Hints((empty))",
1133 "| Hints((empty))",
1134 " Hints((empty))"
1135 ]
1136 );
1137
1138 b.hints().add_flags(Flags::ANCESTORS);
1139 assert_eq!(
1140 hints_ops(&a, &b),
1141 [
1142 "- Hints((empty))",
1143 " Hints((empty))",
1144 "& Hints(ANCESTORS)",
1145 " Hints(ANCESTORS)",
1146 "| Hints(ANCESTORS)",
1147 " Hints(ANCESTORS)"
1148 ]
1149 );
1150 }
1151
1152 #[test]
1153 fn test_filter() {
1154 id_static::tests::with_dag(|dag| {
1155 let sets: Vec<NameSet> = vec!["C B A".into(), nb(dag.ancestors("C".into())).unwrap()];
1156 for abc in sets {
1157 let filter: NameSet = abc.filter(Box::new(|v: &VertexName| {
1158 Box::pin(async move { Ok(v.as_ref() != b"A") })
1159 }));
1160 check_invariants(filter.0.as_ref()).unwrap();
1161 assert_eq!(abc.hints().dag_version(), filter.hints().dag_version());
1162 assert_eq!(
1163 abc.hints().id_map_version(),
1164 filter.hints().id_map_version()
1165 );
1166 assert!(filter.hints().flags().contains(Flags::FILTER));
1167 assert!(!filter.hints().flags().contains(Flags::ANCESTORS));
1168 assert_eq!(
1169 format!("{:?}", r(filter.flatten_names())),
1170 "Ok(<static [C, B]>)"
1171 );
1172 }
1173 })
1174 }
1175
1176 fn hints_ops(lhs: &NameSet, rhs: &NameSet) -> Vec<String> {
1178 vec![
1179 (lhs.clone() - rhs.clone(), rhs.clone() - lhs.clone()),
1180 (lhs.clone() & rhs.clone(), rhs.clone() & lhs.clone()),
1181 (lhs.clone() | rhs.clone(), rhs.clone() | lhs.clone()),
1182 ]
1183 .into_iter()
1184 .zip("-&|".chars())
1185 .flat_map(|((set1, set2), ch)| {
1186 vec![
1187 format!("{} {:?}", ch, set1.hints()),
1188 format!(" {:?}", set2.hints()),
1189 ]
1190 })
1191 .collect()
1192 }
1193
1194 pub(crate) fn check_invariants(query: &dyn AsyncNameSetQuery) -> Result<()> {
1197 let contains_fast_vec: Vec<Option<bool>> = (0..=0xff)
1200 .map(|b| {
1201 let name = VertexName::from(vec![b; 20]);
1202 nb(query.contains_fast(&name)).unwrap_or(None)
1203 })
1204 .collect();
1205 let is_empty = nb(query.is_empty())?;
1206 let count = nb(query.count())?;
1207 let first = nb(query.first())?;
1208 let last = nb(query.last())?;
1209 let names: Vec<VertexName> = ni(query.iter())?.collect::<Result<Vec<_>>>()?;
1210 assert_eq!(
1211 first,
1212 names.first().cloned(),
1213 "first() should match iter().first() (set: {:?})",
1214 &query
1215 );
1216 assert_eq!(
1217 last,
1218 names.last().cloned(),
1219 "last() should match iter().last() (set: {:?})",
1220 &query
1221 );
1222 assert_eq!(
1223 count,
1224 names.len(),
1225 "count() should match iter().count() (set: {:?})",
1226 &query
1227 );
1228 assert_eq!(
1229 is_empty,
1230 count == 0,
1231 "is_empty() should match count() == 0 (set: {:?})",
1232 &query
1233 );
1234 assert!(
1235 names
1236 .iter()
1237 .all(|name| nb(query.contains(name)).ok() == Some(true)),
1238 "contains() should return true for names returned by iter() (set: {:?})",
1239 &query
1240 );
1241 assert!(
1242 names
1243 .iter()
1244 .all(|name| nb(query.contains_fast(name)).unwrap_or(None) != Some(false)),
1245 "contains_fast() should not return false for names returned by iter() (set: {:?})",
1246 &query
1247 );
1248 assert!(
1249 (0..=0xff).all(|b| {
1250 let name = VertexName::from(vec![b; 20]);
1251 nb(query.contains(&name)).ok() == Some(names.contains(&name))
1252 }),
1253 "contains() should return false for names not returned by iter() (set: {:?})",
1254 &query
1255 );
1256 assert!(
1257 (0..=0xff)
1258 .zip(contains_fast_vec.into_iter())
1259 .all(|(b, old_contains)| {
1260 let name = VertexName::from(vec![b; 20]);
1261 let contains = nb(query.contains_fast(&name)).unwrap_or(None);
1262 old_contains == None || contains == old_contains
1263 }),
1264 "contains_fast() should be consistent (set: {:?})",
1265 &query
1266 );
1267 assert!(
1268 (0..=0xff).all(|b| {
1269 let name = VertexName::from(vec![b; 20]);
1270 let contains = nb(query.contains_fast(&name)).unwrap_or(None);
1271 contains == None || contains == Some(names.contains(&name))
1272 }),
1273 "contains_fast() should not return true for names not returned by iter() (set: {:?})",
1274 &query
1275 );
1276 let reversed: Vec<VertexName> = ni(query.iter_rev())?.collect::<Result<Vec<_>>>()?;
1277 assert_eq!(
1278 names,
1279 reversed.into_iter().rev().collect::<Vec<VertexName>>(),
1280 "iter() should match iter_rev().rev() (set: {:?})",
1281 &query
1282 );
1283 Ok(())
1284 }
1285}