sim/classes/
lib_support.rs1use std::sync::Arc;
2
3use sim_kernel::{
4 AbiVersion, Dependency, Export, Factory, Lib, LibManifest, LibTarget, Linker, LoadCx, Result,
5 Symbol, Value, Version,
6};
7
8use crate::{classes::model::NativeClass, shapes::shape_value};
9
10pub struct NativeClassLib {
13 manifest: LibManifest,
14 class_symbol: Symbol,
15 class_value: Value,
16 constructor_symbol: Symbol,
17 constructor_value: Value,
18 constructor_shape_symbol: Option<Symbol>,
19 constructor_shape_value: Option<Value>,
20 instance_shape_symbol: Option<Symbol>,
21 instance_shape_value: Option<Value>,
22 member_values: Vec<(Symbol, Value)>,
23}
24
25impl NativeClassLib {
26 pub fn from_class(lib_symbol: Symbol, class: &NativeClass, version: impl Into<String>) -> Self {
28 let version = Version(version.into());
29 let constructor_shape_symbol = Some(Symbol::qualified(
30 class.symbol.to_string(),
31 "constructor-shape",
32 ));
33 let constructor_shape_value = class.constructor_shape_arc().map(|shape| {
34 shape_value(
35 Symbol::qualified(class.symbol.to_string(), "constructor-shape"),
36 shape,
37 )
38 });
39 let instance_shape_symbol = class
40 .instance_shape
41 .as_ref()
42 .map(|_| Symbol::qualified(class.symbol.to_string(), "instance-shape"));
43 let instance_shape_value = class.instance_shape.as_ref().map(|shape| {
44 shape_value(
45 Symbol::qualified(class.symbol.to_string(), "instance-shape"),
46 shape.clone(),
47 )
48 });
49
50 let mut exports = vec![
51 Export::Class {
52 symbol: class.symbol.clone(),
53 class_id: None,
54 },
55 Export::Function {
56 symbol: class.constructor.symbol.clone(),
57 function_id: None,
58 },
59 ];
60 if let Some(symbol) = &constructor_shape_symbol {
61 exports.push(Export::Shape {
62 symbol: symbol.clone(),
63 shape_id: None,
64 });
65 }
66 if let Some(symbol) = &instance_shape_symbol {
67 exports.push(Export::Shape {
68 symbol: symbol.clone(),
69 shape_id: None,
70 });
71 }
72 exports.extend(class.members.iter().map(|member| Export::Function {
73 symbol: member.symbol.clone(),
74 function_id: None,
75 }));
76
77 Self {
78 manifest: LibManifest {
79 id: lib_symbol,
80 version,
81 abi: AbiVersion { major: 0, minor: 1 },
82 target: LibTarget::HostRegistered,
83 requires: Vec::<Dependency>::new(),
84 capabilities: Vec::new(),
85 exports,
86 },
87 class_symbol: class.symbol.clone(),
88 class_value: sim_kernel::DefaultFactory
89 .opaque(Arc::new(class.clone()))
90 .expect("class should be boxable"),
91 constructor_symbol: class.constructor.symbol.clone(),
92 constructor_value: sim_kernel::DefaultFactory
93 .opaque(Arc::new(class.constructor.clone()))
94 .expect("constructor should be boxable"),
95 constructor_shape_symbol,
96 constructor_shape_value,
97 instance_shape_symbol,
98 instance_shape_value,
99 member_values: class
100 .members
101 .iter()
102 .map(|member| {
103 (
104 member.symbol.clone(),
105 sim_kernel::DefaultFactory
106 .opaque(Arc::new(member.clone()))
107 .expect("member function should be boxable"),
108 )
109 })
110 .collect(),
111 }
112 }
113}
114
115impl Lib for NativeClassLib {
116 fn manifest(&self) -> LibManifest {
117 self.manifest.clone()
118 }
119
120 fn load(&self, _cx: &mut LoadCx, linker: &mut Linker) -> Result<()> {
121 linker.class_value(self.class_symbol.clone(), self.class_value.clone())?;
122 linker.function_value(
123 self.constructor_symbol.clone(),
124 self.constructor_value.clone(),
125 )?;
126 if let (Some(symbol), Some(value)) = (
127 &self.constructor_shape_symbol,
128 &self.constructor_shape_value,
129 ) {
130 linker.shape_value(symbol.clone(), value.clone())?;
131 }
132 if let (Some(symbol), Some(value)) =
133 (&self.instance_shape_symbol, &self.instance_shape_value)
134 {
135 linker.shape_value(symbol.clone(), value.clone())?;
136 }
137 for (symbol, value) in &self.member_values {
138 linker.function_value(symbol.clone(), value.clone())?;
139 }
140 Ok(())
141 }
142}