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