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}