wrpc_introspect/
lib.rs

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}