sim_platform_ubuntu_pc/
loader.rs1use sim_kernel::{Cx, Error, LibLoader, Result, Symbol};
4use sim_run_loaders::{
5 BinaryPackLoader, LispSourceLoader, LoadOutcome, LoadRequest, LoaderKind, LoaderPort,
6 NativeDylibLoader, StaticRegistry, WasmLoader,
7};
8use std::sync::Arc;
9
10const NATIVE: &str = "native-v1";
11const WASM: &str = "wasm-v1";
12const SOURCE: &str = "source-v1";
13const STATIC: &str = "static-v1";
14fn kind(name: &str) -> LoaderKind {
15 LoaderKind::new(Symbol::qualified("loader", name))
16}
17
18pub struct UbuntuLoaderPort {
20 native: NativeDylibLoader,
21 wasm: WasmLoader,
22 source: LispSourceLoader,
23 binary: BinaryPackLoader,
24 static_registry: StaticRegistry,
25}
26
27impl Default for UbuntuLoaderPort {
28 fn default() -> Self {
29 Self {
30 native: NativeDylibLoader,
31 wasm: WasmLoader::new(Arc::new(sim_wasm_abi::WasmiRuntime::new())),
32 source: LispSourceLoader::default(),
33 binary: BinaryPackLoader,
34 static_registry: StaticRegistry::default(),
35 }
36 }
37}
38
39impl UbuntuLoaderPort {
40 pub fn register_static(
42 &self,
43 artifact: Symbol,
44 factory: impl Fn() -> Box<dyn sim_kernel::Lib> + Send + Sync + 'static,
45 ) {
46 self.static_registry.register(artifact, factory);
47 }
48 fn mechanism(&self, request: &LoadRequest) -> Result<&dyn LibLoader> {
49 if request.kind == kind(NATIVE) {
50 Ok(&self.native)
51 } else if request.kind == kind(WASM) {
52 Ok(&self.wasm)
53 } else if request.kind == kind(SOURCE) && self.source.can_load(&request.source) {
54 Ok(&self.source)
55 } else if request.kind == kind(SOURCE) && self.binary.can_load(&request.source) {
56 Ok(&self.binary)
57 } else {
58 Err(Error::HostError(format!(
59 "Ubuntu capsule rejected loader kind {} or its exact source",
60 request.kind.symbol()
61 )))
62 }
63 }
64}
65
66impl LoaderPort for UbuntuLoaderPort {
67 fn loader_kinds(&self) -> Vec<LoaderKind> {
68 [NATIVE, WASM, SOURCE, STATIC]
69 .into_iter()
70 .map(kind)
71 .collect()
72 }
73 fn realize(&self, cx: &mut Cx, request: LoadRequest) -> Result<LoadOutcome> {
74 if request.kind == kind(STATIC) {
75 let artifact = sim_run_loaders::static_artifact(&request.source)?.ok_or_else(|| {
76 Error::HostError("Ubuntu static loader rejected the exact source".into())
77 })?;
78 return self.static_registry.realize(&artifact);
79 }
80 let mechanism = self.mechanism(&request)?;
81 if !mechanism.can_load(&request.source) {
82 return Err(Error::HostError(format!(
83 "loader kind {} rejected the exact source",
84 request.kind.symbol()
85 )));
86 }
87 let library = mechanism.load(cx, request.source)?;
88 let manifest = library.manifest();
89 Ok(LoadOutcome { manifest, library })
90 }
91 fn inspect(
92 &self,
93 cx: &mut Cx,
94 request: &LoadRequest,
95 ) -> Result<Option<sim_kernel::LibManifest>> {
96 if request.kind == kind(STATIC) {
97 let artifact = sim_run_loaders::static_artifact(&request.source)?.ok_or_else(|| {
98 Error::HostError("Ubuntu static loader rejected the exact source".into())
99 })?;
100 return self
101 .static_registry
102 .realize(&artifact)
103 .map(|outcome| Some(outcome.manifest));
104 }
105 self.mechanism(request)?
106 .inspect_manifest(cx, &request.source)
107 }
108}
109
110#[cfg(test)]
111mod tests {
112 use super::*;
113 use sim_kernel::testing::bare_cx as cx;
114 use sim_kernel::{AbiVersion, Lib, LibManifest, LibSource, LibTarget, Linker, LoadCx, Version};
115 struct TestLib;
116 impl Lib for TestLib {
117 fn manifest(&self) -> LibManifest {
118 LibManifest {
119 id: Symbol::qualified("test", "ubuntu-static"),
120 version: Version("1.0.0".into()),
121 abi: AbiVersion { major: 0, minor: 1 },
122 target: LibTarget::HostRegistered,
123 requires: vec![],
124 capabilities: vec![],
125 exports: vec![],
126 }
127 }
128 fn load(&self, _: &mut LoadCx, _: &mut Linker<'_>) -> Result<()> {
129 Ok(())
130 }
131 }
132 #[test]
133 fn advertises_exact_kinds_and_fails_closed() {
134 let port = UbuntuLoaderPort::default();
135 assert_eq!(
136 port.loader_kinds(),
137 [NATIVE, WASM, SOURCE, STATIC]
138 .into_iter()
139 .map(kind)
140 .collect::<Vec<_>>()
141 );
142 let mut cx = cx();
143 assert!(
144 port.realize(
145 &mut cx,
146 LoadRequest {
147 kind: kind("invented-v1"),
148 source: sim_run_loaders::static_source(Symbol::qualified("artifact", "x"))
149 }
150 )
151 .is_err()
152 );
153 assert!(
154 port.realize(
155 &mut cx,
156 LoadRequest {
157 kind: kind(STATIC),
158 source: LibSource::open(
159 Symbol::qualified("loader", "static-artifact"),
160 sim_kernel::Datum::Bytes(vec![])
161 )
162 }
163 )
164 .is_err()
165 );
166 }
167 #[test]
168 fn static_libraries_keep_ordinary_manifest_behavior() {
169 let port = UbuntuLoaderPort::default();
170 let artifact = Symbol::qualified("artifact", "ubuntu-static");
171 port.register_static(artifact.clone(), || Box::new(TestLib));
172 let mut cx = cx();
173 let outcome = port
174 .realize(
175 &mut cx,
176 LoadRequest {
177 kind: kind(STATIC),
178 source: sim_run_loaders::static_source(artifact),
179 },
180 )
181 .unwrap();
182 assert_eq!(outcome.manifest, outcome.library.manifest());
183 }
184}