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