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}