scopegraphs/containers/
scope.rs

1use std::fmt::Debug;
2use std::hash::Hash;
3
4use crate::resolve::Path;
5use crate::Scope;
6use crate::{future_wrapper::FutureWrapper, resolve::ResolvedPath};
7
8use super::{PathContainer, PathContainerWf};
9
10/// Interface for scope containers that support the operations required for query resolution.
11pub trait ScopeContainer<'sg, 'rslv, LABEL: Debug + 'sg, DATA: 'sg>: Debug {
12    /// The type containing paths obtained after stepping to this scope.
13    type PathContainer;
14
15    /// Lift the [`Path::step`] operation into this container.
16    ///
17    /// Should retain the contract that for all scopes `s` in `self`, `prefix.step(lbl, s)` is
18    /// included in the resulting path container (except cyclic paths).
19    fn lift_step(self, lbl: LABEL, prefix: Path<LABEL>) -> Self::PathContainer;
20}
21
22/// Trait that is auto-implemented for any [ScopeContainer] implementation that yields a valid [PathContainer].
23///
24/// This trait is implemented for:
25/// - `Vec<Scope>`,
26/// - [Result] of scope containers, and
27/// - [FutureWrapper] of scope containers.
28/// ```
29/// # use scopegraphs::containers::ScopeContainerWf;
30/// # use scopegraphs::future_wrapper::FutureWrapper;
31/// # use scopegraphs::Scope;
32/// # use std::fmt::Debug;
33/// # use std::hash::Hash;
34///
35/// # trait LBound<'sg>: Copy + Hash + Eq + Debug + 'sg {}
36/// # trait DBound<'sg>: Hash + Eq + 'sg {}
37///
38/// fn test<'sg, 'rslv, LABEL: LBound<'sg>, DATA: DBound<'sg>, DWFO>(
39///     cont: impl ScopeContainerWf<'sg, 'rslv, LABEL, DATA, DWFO, DWFO>
40/// ) { }
41///
42/// # fn scope_vec<'sg, 'rslv, LABEL: LBound<'sg>, DATA: DBound<'sg>>() {
43///     let vec: Vec<Scope> = todo!();
44///     test::<'_, '_, LABEL, DATA, bool>(vec);
45/// # }
46///
47/// # fn result<'sg, 'rslv, LABEL: LBound<'sg>, DATA: DBound<'sg>, E: Debug + Clone>() {
48///     let result: Result<Vec<Scope>, E> = todo!();
49///     test::<'_, '_, LABEL, DATA, bool>(result);
50///     test::<'_, '_, LABEL, DATA, Result<bool, E>>(result);
51/// # }
52///
53/// # fn future<'sg, 'rslv, LABEL: LBound<'sg>, DATA: DBound<'sg>>() {
54///     let future: FutureWrapper<Vec<Scope>> = todo!();
55///     test::<'_, '_, LABEL, DATA, bool>(future);
56///     test::<'_, '_, LABEL, DATA, FutureWrapper<'_, bool>>(future);
57/// # }
58/// ```
59///
60/// ```no_run
61/// # use scopegraphs::containers::ScopeContainerWf;
62/// # use scopegraphs::Scope;
63/// # use std::fmt::Debug;
64/// # use std::hash::Hash;
65///
66///
67/// fn test<'sg, 'rslv, LABEL: Clone + Hash + Eq + Debug + 'sg, DATA: Hash + Eq + 'sg, DWFO>(
68///     cont: impl ScopeContainerWf<'sg, 'rslv, LABEL, DATA, DWFO, DWFO>
69/// ) { }
70/// ```
71///
72/// ```no_run
73/// # use scopegraphs::containers::ScopeContainerWf;
74/// # use scopegraphs::Scope;
75/// # use std::fmt::Debug;
76/// # use std::hash::Hash;
77///
78/// test::<'_, '_, (), (), bool>(Result::<_, ()>::Ok(Vec::<Scope>::new()));
79/// test::<'_, '_, (), (), Result<bool, ()>>(Result::<_, ()>::Ok(Vec::<Scope>::new()));
80///
81/// fn test<'sg, 'rslv, LABEL: Clone + Hash + Eq + Debug + 'sg, DATA: Hash + Eq + 'sg, DWFO>(
82///     cont: impl ScopeContainerWf<'sg, 'rslv, LABEL, DATA, DWFO, DWFO>
83/// ) { }
84/// ```
85///
86pub trait ScopeContainerWf<'sg, 'rslv, LABEL, DATA, DWFO, DEQO>:
87    ScopeContainer<'sg, 'rslv, LABEL, DATA, PathContainer = Self::PathContainerWf>
88where
89    LABEL: Debug + 'sg,
90    DATA: 'sg,
91    ResolvedPath<'sg, LABEL, DATA>: Eq + Hash + Clone,
92{
93    /// Refinement of `Self::PathContainer`, carrying proof that this scope container resolves to valid path containers.
94    type PathContainerWf: PathContainerWf<'sg, 'rslv, LABEL, DATA, DWFO, DEQO>;
95}
96
97impl<'sg, 'rslv, LABEL, DATA, DWFO, DEQO, T> ScopeContainerWf<'sg, 'rslv, LABEL, DATA, DWFO, DEQO>
98    for T
99where
100    LABEL: Debug + 'sg,
101    DATA: 'sg,
102    T: ScopeContainer<'sg, 'rslv, LABEL, DATA>,
103    Self::PathContainer: PathContainerWf<'sg, 'rslv, LABEL, DATA, DWFO, DEQO>,
104    ResolvedPath<'sg, LABEL, DATA>: Eq + Hash + Clone,
105{
106    type PathContainerWf = Self::PathContainer;
107}
108
109impl<'sg: 'rslv, 'rslv, LABEL: Debug + Copy + Eq + Hash + 'sg, DATA: Eq + Hash + 'sg>
110    ScopeContainer<'sg, 'rslv, LABEL, DATA> for Vec<Scope>
111where
112    Vec<Path<LABEL>>: PathContainer<'sg, 'rslv, LABEL, DATA>,
113{
114    type PathContainer = Vec<Path<LABEL>>;
115
116    fn lift_step(self, lbl: LABEL, prefix: Path<LABEL>) -> Self::PathContainer {
117        self.into_iter()
118            .filter_map(move |s| prefix.step(lbl, s))
119            .collect()
120    }
121}
122
123impl<
124        'sg: 'rslv,
125        'rslv,
126        LABEL: Debug + Copy + Eq + Hash + 'sg,
127        DATA: Eq + Hash + 'sg,
128        SC: ScopeContainer<'sg, 'rslv, LABEL, DATA>,
129        E: Debug,
130    > ScopeContainer<'sg, 'rslv, LABEL, DATA> for Result<SC, E>
131where
132    Result<SC::PathContainer, E>: PathContainer<'sg, 'rslv, LABEL, DATA>,
133{
134    type PathContainer = Result<SC::PathContainer, E>;
135
136    fn lift_step(self, lbl: LABEL, prefix: Path<LABEL>) -> Self::PathContainer {
137        self.map(|sc| sc.lift_step(lbl, prefix))
138    }
139}
140
141impl<
142        'sg: 'rslv,
143        'rslv,
144        LABEL: Debug + Copy + Eq + Hash + 'sg,
145        DATA: Eq + Hash + 'sg,
146        SC: ScopeContainer<'sg, 'rslv, LABEL, DATA> + Clone,
147    > ScopeContainer<'sg, 'rslv, LABEL, DATA> for FutureWrapper<'rslv, SC>
148where
149    LABEL: Copy,
150    Self: 'rslv,
151    LABEL: 'rslv,
152    SC::PathContainer: Clone,
153{
154    type PathContainer = FutureWrapper<'rslv, SC::PathContainer>;
155
156    fn lift_step(self, lbl: LABEL, prefix: Path<LABEL>) -> Self::PathContainer {
157        FutureWrapper::new(async move { self.0.await.lift_step(lbl, prefix.clone()) })
158    }
159}