wrpc_runtime_wasmtime/
paths.rs1use std::collections::{BTreeMap, BTreeSet, VecDeque};
16
17use wasmtime::component::types::{self, Type};
18use wasmtime::component::ResourceType;
19use wasmtime::Engine;
20
21pub fn wasi_io_stream_resources(
28 engine: &Engine,
29 component: &types::Component,
30) -> Vec<ResourceType> {
31 let mut imports = BTreeMap::new();
32 crate::collect_component_resource_imports(engine, component, &mut imports);
33 let mut out = Vec::new();
34 for (instance, resources) in imports {
35 let base = instance.split('@').next().unwrap_or(&instance);
37 if base != "wasi:io/streams" {
38 continue;
39 }
40 for (name, ty) in resources {
41 if (&*name == "input-stream" || &*name == "output-stream") && !out.contains(&ty) {
42 out.push(ty);
43 }
44 }
45 }
46 out
47}
48
49fn async_paths(ty: &Type, streams: &[ResourceType]) -> (BTreeSet<VecDeque<Option<usize>>>, bool) {
56 let mut paths = BTreeSet::new();
57 match ty {
58 Type::List(ty) => {
59 let (nested, fut) = async_paths(&ty.ty(), streams);
60 for mut path in nested {
61 path.push_front(None);
62 paths.insert(path);
63 }
64 if fut {
65 paths.insert(VecDeque::from([None]));
66 }
67 (paths, false)
68 }
69 Type::Option(ty) => async_paths(&ty.ty(), streams),
70 Type::Result(ty) => {
71 let mut is_fut = false;
72 if let Some(ty) = ty.ok() {
73 let (nested, fut) = async_paths(&ty, streams);
74 paths.extend(nested);
75 is_fut |= fut;
76 }
77 if let Some(ty) = ty.err() {
78 let (nested, fut) = async_paths(&ty, streams);
79 paths.extend(nested);
80 is_fut |= fut;
81 }
82 (paths, is_fut)
83 }
84 Type::Variant(ty) => {
85 let mut is_fut = false;
86 for case in ty.cases() {
87 if let Some(ty) = case.ty {
88 let (nested, fut) = async_paths(&ty, streams);
89 paths.extend(nested);
90 is_fut |= fut;
91 }
92 }
93 (paths, is_fut)
94 }
95 Type::Tuple(ty) => {
96 for (i, ty) in ty.types().enumerate() {
97 let (nested, fut) = async_paths(&ty, streams);
98 for mut path in nested {
99 path.push_front(Some(i));
100 paths.insert(path);
101 }
102 if fut {
103 paths.insert(VecDeque::from([Some(i)]));
104 }
105 }
106 (paths, false)
107 }
108 Type::Record(ty) => {
109 for (i, field) in ty.fields().enumerate() {
110 let (nested, fut) = async_paths(&field.ty, streams);
111 for mut path in nested {
112 path.push_front(Some(i));
113 paths.insert(path);
114 }
115 if fut {
116 paths.insert(VecDeque::from([Some(i)]));
117 }
118 }
119 (paths, false)
120 }
121 Type::Future(ty) => {
122 if let Some(ty) = ty.ty() {
123 (paths, _) = async_paths(&ty, streams);
124 }
125 (paths, true)
126 }
127 Type::Stream(ty) => {
128 if let Some(ty) = ty.ty() {
129 let (nested, fut) = async_paths(&ty, streams);
130 for mut path in nested {
131 path.push_front(None);
132 paths.insert(path);
133 }
134 if fut {
135 paths.insert(VecDeque::from([None]));
136 }
137 }
138 (paths, true)
139 }
140 Type::Own(ty) | Type::Borrow(ty) if streams.contains(ty) => {
141 (paths, true)
143 }
144 _ => (paths, false),
145 }
146}
147
148pub(crate) fn params_async_paths<'a>(
154 params: impl IntoIterator<Item = &'a Type>,
155 streams: &[ResourceType],
156) -> Vec<Box<[Option<usize>]>> {
157 let mut out = BTreeSet::new();
158 for (i, ty) in params.into_iter().enumerate() {
159 let (nested, fut) = async_paths(ty, streams);
160 for mut path in nested {
161 path.push_front(Some(i));
162 out.insert(path);
163 }
164 if fut {
165 out.insert(VecDeque::from([Some(i)]));
166 }
167 }
168 out.into_iter()
169 .map(|path| path.into_iter().collect::<Box<[_]>>())
170 .collect()
171}