Skip to main content

dag/set/
reverse.rs

1/*
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 */
7
8use std::any::Any;
9use std::borrow::Cow;
10use std::fmt;
11
12use super::hints::Flags;
13use super::id_static::IdStaticSet;
14use super::AsyncSetQuery;
15use super::BoxVertexStream;
16use super::Hints;
17use super::Set;
18use crate::Result;
19use crate::Vertex;
20
21/// Set with a reversed iteration order.
22#[derive(Clone)]
23pub struct ReverseSet {
24    inner: Set,
25    hints: Hints,
26}
27
28impl ReverseSet {
29    pub fn new(set: Set) -> Self {
30        let hints = set.hints().clone();
31        hints.update_flags_with(|flags| {
32            let mut new_flags = flags - (Flags::TOPO_DESC | Flags::ID_DESC | Flags::ID_ASC);
33            if flags.contains(Flags::ID_DESC) {
34                new_flags |= Flags::ID_ASC;
35            }
36            if flags.contains(Flags::ID_ASC) {
37                new_flags |= Flags::ID_DESC;
38            }
39            new_flags
40        });
41        Self { inner: set, hints }
42    }
43}
44
45#[async_trait::async_trait]
46impl AsyncSetQuery for ReverseSet {
47    async fn iter(&self) -> Result<BoxVertexStream> {
48        self.inner.iter_rev().await
49    }
50
51    async fn iter_rev(&self) -> Result<BoxVertexStream> {
52        self.inner.iter().await
53    }
54
55    async fn count(&self) -> Result<u64> {
56        self.inner.count().await
57    }
58
59    async fn size_hint(&self) -> (u64, Option<u64>) {
60        self.inner.size_hint().await
61    }
62
63    async fn contains(&self, name: &Vertex) -> Result<bool> {
64        self.inner.contains(name).await
65    }
66
67    async fn contains_fast(&self, name: &Vertex) -> Result<Option<bool>> {
68        self.inner.contains_fast(name).await
69    }
70
71    async fn first(&self) -> Result<Option<Vertex>> {
72        self.inner.last().await
73    }
74
75    async fn last(&self) -> Result<Option<Vertex>> {
76        self.inner.first().await
77    }
78
79    async fn is_empty(&self) -> Result<bool> {
80        self.inner.is_empty().await
81    }
82
83    fn as_any(&self) -> &dyn Any {
84        self
85    }
86
87    fn hints(&self) -> &Hints {
88        &self.hints
89    }
90
91    fn id_convert(&self) -> Option<&dyn crate::ops::IdConvert> {
92        self.inner.id_convert()
93    }
94
95    fn specialized_reverse(&self) -> Option<Set> {
96        Some(self.inner.clone())
97    }
98
99    fn specialized_flatten_id(&self) -> Option<Cow<IdStaticSet>> {
100        let inner = self.inner.specialized_flatten_id()?;
101        let result = inner.into_owned().reversed();
102        Some(Cow::Owned(result))
103    }
104}
105
106impl fmt::Debug for ReverseSet {
107    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
108        f.write_str("<reverse ")?;
109        self.inner.fmt(f)?;
110        f.write_str(">")
111    }
112}
113
114#[cfg(test)]
115#[allow(clippy::redundant_clone)]
116mod tests {
117    use futures::TryStreamExt;
118
119    use super::super::tests::*;
120    use super::*;
121
122    #[test]
123    fn test_basic() -> Result<()> {
124        let orig = Set::from("a b c d");
125        let set = ReverseSet::new(orig);
126        check_invariants(&set)?;
127
128        let iter = nb(set.iter())?;
129        assert_eq!(dbg(nb(iter.try_collect::<Vec<_>>())?), "[d, c, b, a]");
130
131        Ok(())
132    }
133}