1
1
use anyhow:: Context ;
2
2
use indexmap:: IndexMap ;
3
3
use semver:: Version ;
4
- use spin_app:: locked:: { self , InheritConfiguration , LockedComponent , LockedComponentDependency } ;
4
+ use spin_app:: locked:: InheritConfiguration as LockedInheritConfiguration ;
5
5
use spin_serde:: { DependencyName , KebabId } ;
6
6
use std:: collections:: BTreeMap ;
7
7
use thiserror:: Error ;
@@ -28,18 +28,68 @@ use wac_graph::{CompositionGraph, NodeId};
28
28
/// composition graph into a byte array and return it.
29
29
pub async fn compose < ' a , L : ComponentSourceLoader > (
30
30
loader : & ' a L ,
31
- component : & LockedComponent ,
31
+ component : & L :: Component ,
32
32
) -> Result < Vec < u8 > , ComposeError > {
33
33
Composer :: new ( loader) . compose ( component) . await
34
34
}
35
35
36
+ #[ async_trait:: async_trait]
37
+ pub trait DependencyLike {
38
+ fn inherit ( & self ) -> InheritConfiguration ;
39
+ fn export ( & self ) -> & Option < String > ;
40
+ }
41
+
42
+ pub enum InheritConfiguration {
43
+ All ,
44
+ Some ( Vec < String > ) ,
45
+ }
46
+
47
+ #[ async_trait:: async_trait]
48
+ pub trait ComponentLike {
49
+ type Dependency : DependencyLike ;
50
+
51
+ fn dependencies (
52
+ & self ,
53
+ ) -> impl std:: iter:: ExactSizeIterator < Item = ( & DependencyName , & Self :: Dependency ) > ;
54
+ fn id ( & self ) -> & str ;
55
+ }
56
+
57
+ #[ async_trait:: async_trait]
58
+ impl ComponentLike for spin_app:: locked:: LockedComponent {
59
+ type Dependency = spin_app:: locked:: LockedComponentDependency ;
60
+
61
+ fn dependencies (
62
+ & self ,
63
+ ) -> impl std:: iter:: ExactSizeIterator < Item = ( & DependencyName , & Self :: Dependency ) > {
64
+ self . dependencies . iter ( )
65
+ }
66
+
67
+ fn id ( & self ) -> & str {
68
+ & self . id
69
+ }
70
+ }
71
+
72
+ #[ async_trait:: async_trait]
73
+ impl DependencyLike for spin_app:: locked:: LockedComponentDependency {
74
+ fn inherit ( & self ) -> InheritConfiguration {
75
+ match & self . inherit {
76
+ LockedInheritConfiguration :: All => InheritConfiguration :: All ,
77
+ LockedInheritConfiguration :: Some ( cfgs) => InheritConfiguration :: Some ( cfgs. clone ( ) ) ,
78
+ }
79
+ }
80
+
81
+ fn export ( & self ) -> & Option < String > {
82
+ & self . export
83
+ }
84
+ }
85
+
36
86
/// This trait is used to load component source code from a locked component source across various embdeddings.
37
87
#[ async_trait:: async_trait]
38
88
pub trait ComponentSourceLoader {
39
- async fn load_component_source (
40
- & self ,
41
- source : & locked :: LockedComponentSource ,
42
- ) -> anyhow:: Result < Vec < u8 > > ;
89
+ type Component : ComponentLike < Dependency = Self :: Dependency > ;
90
+ type Dependency : DependencyLike ;
91
+ async fn load_component_source ( & self , source : & Self :: Component ) -> anyhow :: Result < Vec < u8 > > ;
92
+ async fn load_dependency_source ( & self , source : & Self :: Dependency ) -> anyhow:: Result < Vec < u8 > > ;
43
93
}
44
94
45
95
/// Represents an error that can occur when composing dependencies.
@@ -98,19 +148,19 @@ struct Composer<'a, L> {
98
148
}
99
149
100
150
impl < ' a , L : ComponentSourceLoader > Composer < ' a , L > {
101
- async fn compose ( mut self , component : & LockedComponent ) -> Result < Vec < u8 > , ComposeError > {
151
+ async fn compose ( mut self , component : & L :: Component ) -> Result < Vec < u8 > , ComposeError > {
102
152
let source = self
103
153
. loader
104
- . load_component_source ( & component. source )
154
+ . load_component_source ( component)
105
155
. await
106
156
. map_err ( ComposeError :: PrepareError ) ?;
107
157
108
- if component. dependencies . is_empty ( ) {
158
+ if component. dependencies ( ) . len ( ) == 0 {
109
159
return Ok ( source) ;
110
160
}
111
161
112
162
let ( world_id, instantiation_id) = self
113
- . register_package ( & component. id , None , source)
163
+ . register_package ( component. id ( ) , None , source)
114
164
. map_err ( ComposeError :: PrepareError ) ?;
115
165
116
166
let prepared = self . prepare_dependencies ( world_id, component) . await ?;
@@ -150,15 +200,15 @@ impl<'a, L: ComponentSourceLoader> Composer<'a, L> {
150
200
async fn prepare_dependencies (
151
201
& mut self ,
152
202
world_id : WorldId ,
153
- component : & LockedComponent ,
203
+ component : & L :: Component ,
154
204
) -> Result < IndexMap < String , DependencyInfo > , ComposeError > {
155
205
let imports = self . graph . types ( ) [ world_id] . imports . clone ( ) ;
156
206
157
207
let import_keys = imports. keys ( ) . cloned ( ) . collect :: < Vec < _ > > ( ) ;
158
208
159
209
let mut mappings: BTreeMap < String , Vec < DependencyInfo > > = BTreeMap :: new ( ) ;
160
210
161
- for ( dependency_name, dependency) in & component. dependencies {
211
+ for ( dependency_name, dependency) in component. dependencies ( ) {
162
212
let mut matched = Vec :: new ( ) ;
163
213
164
214
for import_name in & import_keys {
@@ -171,7 +221,7 @@ impl<'a, L: ComponentSourceLoader> Composer<'a, L> {
171
221
172
222
if matched. is_empty ( ) {
173
223
return Err ( ComposeError :: UnmatchedDependencyName {
174
- component_id : component. id . clone ( ) ,
224
+ component_id : component. id ( ) . to_owned ( ) ,
175
225
dependency_name : dependency_name. clone ( ) ,
176
226
} ) ;
177
227
}
@@ -195,7 +245,7 @@ impl<'a, L: ComponentSourceLoader> Composer<'a, L> {
195
245
196
246
if !conflicts. is_empty ( ) {
197
247
return Err ( ComposeError :: DependencyConflicts {
198
- component_id : component. id . clone ( ) ,
248
+ component_id : component. id ( ) . to_owned ( ) ,
199
249
conflicts : conflicts
200
250
. into_iter ( )
201
251
. map ( |( import_name, infos) | {
@@ -300,19 +350,16 @@ impl<'a, L: ComponentSourceLoader> Composer<'a, L> {
300
350
async fn register_dependency (
301
351
& mut self ,
302
352
dependency_name : DependencyName ,
303
- dependency : & LockedComponentDependency ,
353
+ dependency : & L :: Dependency ,
304
354
) -> anyhow:: Result < DependencyInfo > {
305
- let mut dependency_source = self
306
- . loader
307
- . load_component_source ( & dependency. source )
308
- . await ?;
355
+ let mut dependency_source = self . loader . load_dependency_source ( dependency) . await ?;
309
356
310
357
let package_name = match & dependency_name {
311
358
DependencyName :: Package ( name) => name. package . to_string ( ) ,
312
359
DependencyName :: Plain ( name) => name. to_string ( ) ,
313
360
} ;
314
361
315
- match & dependency. inherit {
362
+ match dependency. inherit ( ) {
316
363
InheritConfiguration :: Some ( configurations) => {
317
364
if configurations. is_empty ( ) {
318
365
// Configuration inheritance is disabled, apply deny_all adapter
@@ -333,7 +380,7 @@ impl<'a, L: ComponentSourceLoader> Composer<'a, L> {
333
380
manifest_name : dependency_name,
334
381
instantiation_id,
335
382
world_id,
336
- export_name : dependency. export . clone ( ) ,
383
+ export_name : dependency. export ( ) . clone ( ) ,
337
384
} )
338
385
}
339
386
0 commit comments