sim_lib_expr_tree_server/
site.rs1use std::{any::Any, sync::Arc, time::Duration};
4
5use sim_kernel::{
6 AbiVersion, ClassRef, Cx, DefaultFactory, Dependency, Error, EvalFabric, EvalReply,
7 EvalRequest, Export, Factory, Lib, LibManifest, LibTarget, Linker, Object, ObjectCompat,
8 Result, Symbol, Value, Version,
9};
10use sim_lib_server::{
11 EvalSite, FrameKind, ServerAddress, ServerFrame, eval_request_from_frame,
12 server_frame_from_reply,
13};
14
15use crate::ExpressionTreeServer;
16
17pub fn expr_tree_server_lib_symbol() -> Symbol {
19 Symbol::qualified("lib", "expr-tree-server")
20}
21
22pub fn expr_tree_server_site_symbol() -> Symbol {
24 Symbol::new("site/sim-lib-expr-tree-server")
25}
26
27impl EvalFabric for ExpressionTreeServer {
28 fn realize(&self, cx: &mut Cx, request: EvalRequest) -> Result<EvalReply> {
29 self.realize_request(cx, request)
30 }
31}
32
33impl EvalSite for ExpressionTreeServer {
34 fn site_kind(&self) -> &'static str {
35 "expression-tree"
36 }
37
38 fn address(&self) -> &ServerAddress {
39 self.address()
40 }
41
42 fn codecs(&self) -> &[Symbol] {
43 self.codecs()
44 }
45
46 fn answer(&self, cx: &mut Cx, frame: ServerFrame) -> Result<ServerFrame> {
47 if frame.kind != FrameKind::Request {
48 return Err(Error::Eval(format!(
49 "expression-tree site cannot answer frame kind {}",
50 frame.kind.as_symbol()
51 )));
52 }
53 let correlation = frame.msg_id;
54 let consistency = frame.envelope.consistency;
55 let reply_codec = frame
56 .envelope
57 .reply_codec_hint
58 .clone()
59 .filter(|codec| self.codecs().contains(codec))
60 .unwrap_or_else(|| frame.codec.clone());
61 let request = eval_request_from_frame(cx, &frame)?;
62 let reply = self.realize(cx, request)?;
63 let mut frame = server_frame_from_reply(cx, &reply_codec, reply, consistency)?;
64 frame.correlate = correlation;
65 Ok(frame)
66 }
67
68 fn answer_with_timeout(
69 &self,
70 cx: &mut Cx,
71 frame: ServerFrame,
72 timeout: Option<Duration>,
73 ) -> Result<ServerFrame> {
74 if timeout.is_some_and(|timeout| timeout.is_zero()) {
75 return Err(Error::HostError(
76 "expression-tree server request deadline elapsed".to_owned(),
77 ));
78 }
79 self.answer(cx, frame)
80 }
81
82 fn as_eval_fabric(&self) -> Option<&dyn EvalFabric> {
83 Some(self)
84 }
85
86 fn as_any(&self) -> &dyn Any {
87 self
88 }
89}
90
91impl Object for ExpressionTreeServer {
92 fn display(&self, _cx: &mut Cx) -> Result<String> {
93 Ok(format!(
94 "#<expression-tree-server {}>",
95 expr_tree_server_site_symbol()
96 ))
97 }
98
99 fn as_any(&self) -> &dyn Any {
100 self
101 }
102}
103
104impl ObjectCompat for ExpressionTreeServer {
105 fn class(&self, cx: &mut Cx) -> Result<ClassRef> {
106 if let Some(class) = cx
107 .registry()
108 .class_by_symbol(&Symbol::qualified("core", "EvalFabric"))
109 {
110 return Ok(class.clone());
111 }
112 DefaultFactory.class_stub(
113 sim_kernel::CORE_EVAL_REQUEST_CLASS_ID,
114 Symbol::qualified("core", "EvalFabric"),
115 )
116 }
117
118 fn as_eval_fabric(&self) -> Option<&dyn EvalFabric> {
119 Some(self)
120 }
121
122 fn as_table(&self, cx: &mut Cx) -> Result<Value> {
123 cx.factory().table(vec![
124 (
125 Symbol::new("site"),
126 cx.factory().symbol(expr_tree_server_site_symbol())?,
127 ),
128 (
129 Symbol::new("max-sessions"),
130 cx.factory()
131 .string(self.limits().max_sessions.to_string())?,
132 ),
133 (
134 Symbol::new("max-idle-ticks"),
135 cx.factory()
136 .string(self.limits().max_idle_ticks.to_string())?,
137 ),
138 ])
139 }
140}
141
142#[derive(Clone)]
144pub struct ExpressionTreeServerLib {
145 server: Arc<ExpressionTreeServer>,
146}
147
148impl ExpressionTreeServerLib {
149 pub fn new(server: Arc<ExpressionTreeServer>) -> Self {
151 Self { server }
152 }
153}
154
155impl Default for ExpressionTreeServerLib {
156 fn default() -> Self {
157 Self::new(Arc::new(ExpressionTreeServer::local()))
158 }
159}
160
161impl Lib for ExpressionTreeServerLib {
162 fn manifest(&self) -> LibManifest {
163 LibManifest {
164 id: expr_tree_server_lib_symbol(),
165 version: Version(env!("CARGO_PKG_VERSION").to_owned()),
166 abi: AbiVersion { major: 0, minor: 1 },
167 target: LibTarget::HostRegistered,
168 requires: vec![Dependency {
169 id: sim_lib_expr_tree::expr_tree_lib_symbol(),
170 minimum_version: None,
171 }],
172 capabilities: Vec::new(),
173 exports: vec![Export::Site {
174 symbol: expr_tree_server_site_symbol(),
175 runtime_id: None,
176 }],
177 }
178 }
179
180 fn load(&self, _cx: &mut sim_kernel::LoadCx, linker: &mut Linker<'_>) -> Result<()> {
181 linker.site_value(
182 expr_tree_server_site_symbol(),
183 DefaultFactory.opaque(self.server.clone())?,
184 )?;
185 Ok(())
186 }
187}
188
189pub fn install_expr_tree_server_lib(cx: &mut Cx) -> Result<()> {
191 if cx.registry().lib(&expr_tree_server_lib_symbol()).is_none() {
192 cx.load_lib(&ExpressionTreeServerLib::default())?;
193 }
194 Ok(())
195}