1use 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#[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}