tinymist_std/concepts/
query.rs1use core::fmt;
2use std::sync::OnceLock;
3
4use parking_lot::Mutex;
5
6pub struct QueryRef<Res, Err, QueryContext = ()> {
13    ctx: Mutex<Option<QueryContext>>,
14    cell: OnceLock<Result<Res, Err>>,
16}
17
18impl<T, E, QC> QueryRef<T, E, QC> {
19    pub fn with_value(value: T) -> Self {
21        let cell = OnceLock::new();
22        cell.get_or_init(|| Ok(value));
23        Self {
24            ctx: Mutex::new(None),
25            cell,
26        }
27    }
28
29    pub fn with_context(ctx: QC) -> Self {
32        Self {
33            ctx: Mutex::new(Some(ctx)),
34            cell: OnceLock::new(),
35        }
36    }
37}
38
39impl<T, E: Clone, QC> QueryRef<T, E, QC> {
40    #[inline]
42    pub fn compute<F: FnOnce() -> Result<T, E>>(&self, f: F) -> Result<&T, E> {
43        self.compute_with_context(|_| f())
44    }
45
46    #[inline]
48    pub fn compute_with_context<F: FnOnce(QC) -> Result<T, E>>(&self, f: F) -> Result<&T, E> {
49        let result = self.cell.get_or_init(|| f(self.ctx.lock().take().unwrap()));
50        result.as_ref().map_err(Clone::clone)
51    }
52
53    pub fn get_uninitialized(&self) -> Option<&Result<T, E>> {
60        self.cell.get()
61    }
62}
63
64impl<T, E> Default for QueryRef<T, E> {
65    fn default() -> Self {
66        QueryRef {
67            ctx: Mutex::new(Some(())),
68            cell: OnceLock::new(),
69        }
70    }
71}
72
73impl<T, E, QC> fmt::Debug for QueryRef<T, E, QC>
74where
75    T: fmt::Debug,
76    E: fmt::Debug,
77    QC: fmt::Debug,
78{
79    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
80        let ctx = self.ctx.lock();
81        let res = self.cell.get();
82        f.debug_struct("QueryRef")
83            .field("context", &ctx)
84            .field("result", &res)
85            .finish()
86    }
87}