1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
use super::*;

use crate::dag::WitnessSource;

use crate::gadgets::traits::castable::WitnessCastable;

pub trait Resolvable<T: 'static + Clone>: 'static {
    fn wait_for_value(self) -> Option<T>;
}

pub enum CompositeWitnessValue<
    F: SmallField,
    SRC: 'static + Send + Sync + Clone + std::fmt::Debug,
    T: WitnessCastable<F, SRC>,
    R: Resolvable<SRC>,
    S: WitnessSource<F>,
> {
    Placeholder,
    Ready(T),
    Waiting {
        resolvable: R,
        _marker: std::marker::PhantomData<(F, SRC, S)>,
    },
}

impl<
        F: SmallField,
        SRC: 'static + Send + Sync + Clone + std::fmt::Debug,
        T: WitnessCastable<F, SRC>,
        R: Resolvable<SRC>,
        S: WitnessSource<F>,
    > CompositeWitnessValue<F, SRC, T, R, S>
{
    pub fn wait(&mut self) -> Option<T> {
        match self {
            Self::Placeholder => None,
            Self::Ready(value) => Some(value.clone()),
            a => {
                let this = std::mem::replace(a, Self::Placeholder);

                let Self::Waiting { resolvable, .. } = this else {
                    unreachable!()
                };
                let resolved = resolvable.wait_for_value();
                if let Some(resolved) = resolved {
                    let as_final_type = T::cast_from_source(resolved);
                    let _ = std::mem::replace(a, Self::Ready(as_final_type.clone()));

                    Some(as_final_type)
                } else {
                    None
                }
            }
        }
    }
}

impl<
        F: SmallField,
        SRC: 'static + Send + Sync + Clone + std::fmt::Debug,
        T: WitnessCastable<F, SRC>,
        R: Resolvable<SRC>,
        S: WitnessSource<F>,
    > Resolvable<T> for CompositeWitnessValue<F, SRC, T, R, S>
{
    fn wait_for_value(mut self) -> Option<T> {
        self.wait()
    }
}