1use crate::doc::Doc;
9use crate::{Cell, Executor};
10use quarb::QueryResult;
11
12pub struct LocalExecutor {
13 doc: Doc,
14 now: (i64, u32),
16 allow_shell: bool,
17 #[cfg(feature = "native")]
19 model: Option<quarb_model::Model>,
20 #[cfg(feature = "native")]
24 respec: Option<(Vec<crate::MountSpec>, crate::Options)>,
25}
26
27impl LocalExecutor {
28 pub fn new(doc: Doc, now: (i64, u32), allow_shell: bool) -> Self {
30 Self {
31 doc,
32 now,
33 allow_shell,
34 #[cfg(feature = "native")]
35 respec: None,
36 #[cfg(feature = "native")]
37 model: None,
38 }
39 }
40
41 #[cfg(feature = "native")]
44 pub fn with_model(mut self, model: Option<quarb_model::Model>) -> Self {
45 self.model = model;
46 self
47 }
48
49 #[cfg(feature = "native")]
52 pub fn with_respec(
53 doc: Doc,
54 now: (i64, u32),
55 allow_shell: bool,
56 specs: Vec<crate::MountSpec>,
57 opts: crate::Options,
58 ) -> Self {
59 Self {
60 doc,
61 now,
62 allow_shell,
63 respec: Some((specs, opts)),
64 #[cfg(feature = "native")]
65 model: None,
66 }
67 }
68}
69
70fn run_doc(doc: &Doc, query: &str, now: (i64, u32), allow_shell: bool) -> anyhow::Result<Vec<Cell>> {
72 let result = doc
73 .run(query, now, allow_shell)
74 .map_err(|e| anyhow::anyhow!("{e}"))?;
75 Ok(match result {
76 QueryResult::Nodes(nodes) => nodes.into_iter().map(|n| Cell::Node(doc.render(n))).collect(),
77 QueryResult::Values(values) => values.into_iter().map(Cell::Value).collect(),
78 })
79}
80
81#[cfg(feature = "native")]
83fn run_doc_modeled(
84 doc: &Doc,
85 query: &str,
86 now: (i64, u32),
87 allow_shell: bool,
88 model: &quarb_model::Model,
89) -> anyhow::Result<Vec<Cell>> {
90 let result = doc
91 .run_modeled(query, now, allow_shell, model)
92 .map_err(|e| anyhow::anyhow!("{e}"))?;
93 Ok(match result {
94 QueryResult::Nodes(nodes) => nodes
95 .into_iter()
96 .map(|n| Cell::Node(doc.render_modeled(n, model)))
97 .collect(),
98 QueryResult::Values(values) => values.into_iter().map(Cell::Value).collect(),
99 })
100}
101
102impl Executor for LocalExecutor {
103 fn run(&self, query: &str) -> anyhow::Result<Vec<Cell>> {
104 #[cfg(feature = "native")]
105 if let Some(model) = &self.model {
106 return run_doc_modeled(&self.doc, query, self.now, self.allow_shell, model);
107 }
108 run_doc(&self.doc, query, self.now, self.allow_shell)
109 }
110
111 fn run_fresh(&self, query: &str) -> anyhow::Result<Vec<Cell>> {
112 #[cfg(feature = "native")]
113 if let Some((specs, opts)) = &self.respec {
114 let fresh = match specs.as_slice() {
115 [one] if one.name.is_none() => Doc::open(&one.path, opts)?,
116 many => Doc::mount_specs(many, opts)?,
117 };
118 return run_doc(&fresh, query, self.now, self.allow_shell);
119 }
120 self.run(query)
121 }
122}