1use std::collections::{BTreeSet, VecDeque};
2
3use wit_parser::{
4 Case, Field, Flags, Function, FunctionKind, Handle, Int, Record, Resolve, Stream, Type,
5 TypeDefKind, TypeId,
6};
7
8#[must_use]
9pub fn flag_repr(ty: &Flags) -> Int {
10 match ty.flags.len() {
11 ..=8 => Int::U8,
12 9..=16 => Int::U16,
13 17..=32 => Int::U32,
14 33.. => Int::U64,
15 }
16}
17
18#[must_use]
19pub fn rpc_func_name(func: &Function) -> &str {
20 match &func.kind {
21 FunctionKind::Constructor(..) => func
22 .name
23 .strip_prefix("[constructor]")
24 .expect("failed to strip `[constructor]` prefix"),
25 FunctionKind::Static(..) => func
26 .name
27 .strip_prefix("[static]")
28 .expect("failed to strip `[static]` prefix"),
29 FunctionKind::Method(..) => func
30 .name
31 .strip_prefix("[method]")
32 .expect("failed to strip `[method]` prefix"),
33 FunctionKind::Freestanding => &func.name,
34 }
35}
36
37#[must_use]
38pub fn is_ty(resolve: &Resolve, expected: Type, ty: &Type) -> bool {
39 let mut ty = *ty;
40 loop {
41 if ty == expected {
42 return true;
43 }
44 if let Type::Id(id) = ty {
45 if let TypeDefKind::Type(t) = resolve.types[id].kind {
46 ty = t;
47 continue;
48 }
49 }
50 return false;
51 }
52}
53
54#[must_use]
55pub fn is_list_of(resolve: &Resolve, expected: Type, ty: &Type) -> bool {
56 let mut ty = *ty;
57 loop {
58 if let Type::Id(id) = ty {
59 match resolve.types[id].kind {
60 TypeDefKind::Type(t) => {
61 ty = t;
62 continue;
63 }
64 TypeDefKind::List(t) => return is_ty(resolve, expected, &t),
65 _ => return false,
66 }
67 }
68 return false;
69 }
70}
71
72#[must_use]
73pub fn is_tuple(resolve: &Resolve, ty: &Type) -> bool {
74 let mut ty = *ty;
75 loop {
76 if let Type::Id(id) = ty {
77 match resolve.types[id].kind {
78 TypeDefKind::Type(t) => {
79 ty = t;
80 continue;
81 }
82 TypeDefKind::Tuple(_) => return true,
83 _ => return false,
84 }
85 }
86 return false;
87 }
88}
89
90#[must_use]
91pub fn async_paths_ty(resolve: &Resolve, ty: &Type) -> (BTreeSet<VecDeque<Option<u32>>>, bool) {
92 if let Type::Id(ty) = ty {
93 async_paths_tyid(resolve, *ty)
94 } else {
95 (BTreeSet::default(), false)
96 }
97}
98
99#[must_use]
100pub fn async_paths_tyid(resolve: &Resolve, id: TypeId) -> (BTreeSet<VecDeque<Option<u32>>>, bool) {
101 match &resolve.types[id].kind {
102 TypeDefKind::List(ty) => {
103 let mut paths = BTreeSet::default();
104 let (nested, fut) = async_paths_ty(resolve, ty);
105 for mut path in nested {
106 path.push_front(None);
107 paths.insert(path);
108 }
109 if fut {
110 paths.insert(vec![None].into());
111 }
112 (paths, false)
113 }
114 TypeDefKind::Option(ty) => async_paths_ty(resolve, ty),
115 TypeDefKind::Result(ty) => {
116 let mut paths = BTreeSet::default();
117 let mut is_fut = false;
118 if let Some(ty) = ty.ok.as_ref() {
119 let (nested, fut) = async_paths_ty(resolve, ty);
120 for path in nested {
121 paths.insert(path);
122 }
123 if fut {
124 is_fut = true;
125 }
126 }
127 if let Some(ty) = ty.err.as_ref() {
128 let (nested, fut) = async_paths_ty(resolve, ty);
129 for path in nested {
130 paths.insert(path);
131 }
132 if fut {
133 is_fut = true;
134 }
135 }
136 (paths, is_fut)
137 }
138 TypeDefKind::Variant(ty) => {
139 let mut paths = BTreeSet::default();
140 let mut is_fut = false;
141 for Case { ty, .. } in &ty.cases {
142 if let Some(ty) = ty {
143 let (nested, fut) = async_paths_ty(resolve, ty);
144 for path in nested {
145 paths.insert(path);
146 }
147 if fut {
148 is_fut = true;
149 }
150 }
151 }
152 (paths, is_fut)
153 }
154 TypeDefKind::Tuple(ty) => {
155 let mut paths = BTreeSet::default();
156 for (i, ty) in ty.types.iter().enumerate() {
157 let (nested, fut) = async_paths_ty(resolve, ty);
158 for mut path in nested {
159 path.push_front(Some(i.try_into().unwrap()));
160 paths.insert(path);
161 }
162 if fut {
163 let path = vec![Some(i.try_into().unwrap())].into();
164 paths.insert(path);
165 }
166 }
167 (paths, false)
168 }
169 TypeDefKind::Record(Record { fields }) => {
170 let mut paths = BTreeSet::default();
171 for (i, Field { ty, .. }) in fields.iter().enumerate() {
172 let (nested, fut) = async_paths_ty(resolve, ty);
173 for mut path in nested {
174 path.push_front(Some(i.try_into().unwrap()));
175 paths.insert(path);
176 }
177 if fut {
178 let path = vec![Some(i.try_into().unwrap())].into();
179 paths.insert(path);
180 }
181 }
182 (paths, false)
183 }
184 TypeDefKind::Future(ty) => {
185 let mut paths = BTreeSet::default();
186 if let Some(ty) = ty {
187 (paths, _) = async_paths_ty(resolve, ty);
188 }
189 (paths, true)
190 }
191 TypeDefKind::Stream(Stream { element, .. }) => {
192 let mut paths = BTreeSet::new();
193 if let Some(ty) = element {
194 let (nested, fut) = async_paths_ty(resolve, ty);
195 for mut path in nested {
196 path.push_front(None);
197 paths.insert(path);
198 }
199 if fut {
200 paths.insert(vec![None].into());
201 }
202 }
203 (paths.into_iter().collect(), true)
204 }
205 TypeDefKind::Type(ty) => async_paths_ty(resolve, ty),
206 TypeDefKind::Resource
207 | TypeDefKind::Flags(..)
208 | TypeDefKind::Enum(..)
209 | TypeDefKind::Handle(Handle::Own(..) | Handle::Borrow(..)) => (BTreeSet::default(), false),
210 TypeDefKind::Unknown => unreachable!(),
211 }
212}