sim_lib_auto_core/
runtime.rs1use sim_citizen::CitizenInfo;
4use sim_kernel::{
5 AbiVersion, Cx, Export, Lib, LibManifest, LibTarget, Linker, LoadCx, Result, Symbol, Version,
6};
7
8use crate::auto_capability_texts;
9
10const AUTO_CITIZENS: &[&str] = &[
11 "auto/VehicleId",
12 "auto/Dtc",
13 "auto/DtcStatus",
14 "auto/BrandCaps",
15 "auto/AutoLane",
16 "auto/EffectClass",
17 "auto/OpCap",
18 "auto/TransportSpec",
19 "auto/SiteManifest",
20];
21
22const AUTO_LANES: &[&str] = &[
23 "diagnostics",
24 "telemetry",
25 "manifest",
26 "read",
27 "info",
28 "parts",
29 "service",
30 "control",
31 "flash",
32];
33
34#[derive(Clone, Copy, Debug, Default)]
36pub struct AutoCoreLib;
37
38impl Lib for AutoCoreLib {
39 fn manifest(&self) -> LibManifest {
40 let mut exports = auto_citizen_symbols()
41 .into_iter()
42 .map(|symbol| Export::Class {
43 symbol,
44 class_id: None,
45 })
46 .collect::<Vec<_>>();
47 exports.extend([
48 Export::Value {
49 symbol: auto_caps_symbol(),
50 },
51 Export::Value {
52 symbol: auto_lanes_symbol(),
53 },
54 Export::Value {
55 symbol: manifest_shape_symbol(),
56 },
57 ]);
58 LibManifest {
59 id: Symbol::qualified("auto", "core"),
60 version: Version(env!("CARGO_PKG_VERSION").to_owned()),
61 abi: AbiVersion { major: 0, minor: 1 },
62 target: LibTarget::HostRegistered,
63 requires: Vec::new(),
64 capabilities: Vec::new(),
65 exports,
66 }
67 }
68
69 fn load(&self, cx: &mut LoadCx, linker: &mut Linker<'_>) -> Result<()> {
70 sim_citizen::install_namespace(linker, "auto")?;
71 linker.value(
72 auto_caps_symbol(),
73 string_list(cx, auto_capability_texts())?,
74 )?;
75 linker.value(auto_lanes_symbol(), string_list(cx, AUTO_LANES)?)?;
76 linker.value(
77 manifest_shape_symbol(),
78 cx.factory().string(
79 "auto/SiteManifest v0 site vehicle brand makes lanes transports operations op-caps ceiling"
80 .to_owned(),
81 )?,
82 )?;
83 Ok(())
84 }
85}
86
87pub fn install_auto_core_lib(cx: &mut Cx) -> Result<()> {
89 if cx
90 .registry()
91 .lib(&Symbol::qualified("auto", "core"))
92 .is_some()
93 {
94 return Ok(());
95 }
96 cx.load_lib(&AutoCoreLib).map(|_| ())
97}
98
99pub fn auto_citizen_registry() -> Vec<&'static CitizenInfo> {
101 sim_citizen::registered_citizens()
102 .filter(|info| AUTO_CITIZENS.contains(&info.symbol))
103 .collect()
104}
105
106pub fn auto_citizen_symbols() -> Vec<Symbol> {
108 AUTO_CITIZENS
109 .iter()
110 .map(|symbol| parse_symbol(symbol))
111 .collect()
112}
113
114pub fn auto_caps_symbol() -> Symbol {
116 Symbol::qualified("auto", "caps")
117}
118
119pub fn auto_lanes_symbol() -> Symbol {
121 Symbol::qualified("auto", "lanes")
122}
123
124pub fn manifest_shape_symbol() -> Symbol {
126 Symbol::qualified("auto", "manifest-shape")
127}
128
129fn string_list(cx: &mut LoadCx, items: &[&str]) -> Result<sim_kernel::Value> {
130 cx.factory().list(
131 items
132 .iter()
133 .map(|item| cx.factory().string((*item).to_owned()))
134 .collect::<Result<Vec<_>>>()?,
135 )
136}
137
138fn parse_symbol(text: &str) -> Symbol {
139 if let Some((namespace, name)) = text.split_once('/') {
140 Symbol::qualified(namespace, name)
141 } else {
142 Symbol::new(text)
143 }
144}