1use codespan::Span;
2use std::borrow::Cow;
3use std::fmt;
4use std::fmt::Debug;
5use std::fmt::Display;
6use std::ops::Deref;
7use thiserror::Error;
8use uuid::Uuid;
9
10#[derive(Debug, Clone)]
11pub struct File {
12 pub elements: Vec<Toplevel>,
13}
14
15impl File {
16 pub fn visit_type_idents<F: FnMut(&str)>(&self, mut f: F) {
17 for el in self.elements.iter() {
18 el.visit_type_idents(&mut f);
19 }
20 }
21}
22
23#[derive(Debug, Clone)]
24pub enum Toplevel {
25 Import(Vec<Sp<String>>),
26 Include(Vec<Sp<String>>),
27 Interface(Interface),
28 Typelib(Typelib),
29 Enum(Enum),
30 CppQuote(String),
31}
32
33impl Toplevel {
34 pub fn visit_type_idents<F: FnMut(&str)>(&self, mut f: F) {
35 match self {
36 Toplevel::Import(_) => {}
37 Toplevel::Include(_) => {}
38 Toplevel::Interface(el) => el.visit_type_idents(&mut f),
39 Toplevel::Typelib(_) => {}
40 Toplevel::Enum(_) => {}
41 Toplevel::CppQuote(_) => {}
42 }
43 }
44}
45
46#[derive(Debug, Clone)]
47pub struct Interface {
48 pub name: String,
49 pub attrs: Vec<ItfAttr>,
50 pub defn: Option<InterfaceDefn>,
51}
52
53#[derive(Debug, Clone)]
54pub struct InterfaceDefn {
55 pub base: Option<Sp<String>>,
56 pub elems: Vec<Function>,
57}
58
59impl Interface {
60 pub fn visit_type_idents<F: FnMut(&str)>(&self, mut f: F) {
61 let Some(InterfaceDefn { base, elems, .. }) = &self.defn else {
62 return;
63 };
64
65 if let Some(el) = base {
66 f(el);
67 }
68
69 for el in elems.iter() {
70 el.visit_type_idents(&mut f);
71 }
72 }
73
74 pub fn guid(&self) -> Option<Uuid> {
75 for a in self.attrs.iter() {
76 match a {
77 Attr::Uuid(id) => return Some(*id),
78 _ => {}
79 }
80 }
81
82 None
83 }
84}
85
86#[derive(Debug, Clone)]
87pub struct Enum {
88 pub name: String,
89}
90
91#[derive(Debug, Clone)]
92pub enum Attr {
93 Default,
94 Dual,
95 HelpString(String),
96 Local,
97 Object,
98 OleAutomation,
99 PointerDefault(PointerType),
100 Restricted,
101 Uuid(Uuid),
102 Version(u16, u16),
103}
104
105pub type ItfAttr = Attr;
106pub type TlbAttr = Attr;
107pub type ClassAttr = Attr;
108
109#[derive(Debug, Clone)]
110pub struct Typelib {
111 pub name: String,
112 pub attrs: Vec<TlbAttr>,
113 pub elems: Vec<TlbElem>,
114}
115
116#[derive(Debug, Clone)]
117pub enum TlbElem {
118 ImportLib(String),
119 Interface(Interface),
120 Class(Class),
121}
122
123#[derive(Debug, Clone)]
124pub struct Class {
125 pub name: String,
126 pub attrs: Vec<ClassAttr>,
127 pub elems: Vec<ClassElem>,
128}
129
130#[derive(Debug, Clone)]
131pub enum ClassElem {
132 Interface(Interface),
133}
134
135#[derive(Debug, Clone, Copy)]
136pub enum PointerType {
137 Unique,
138 Ref,
139 Ptr,
140}
141
142#[derive(Debug, Clone)]
143pub struct Function {
144 pub attrs: Vec<FnAttr>,
145 pub ret: Ctype,
146 pub name: String,
147 pub args: Vec<FnArg>,
148}
149
150impl Function {
151 pub fn visit_type_idents<F: FnMut(&str)>(&self, mut f: F) {
152 self.ret.visit_type_idents(&mut f);
153
154 for el in self.args.iter() {
155 el.visit_type_idents(&mut f);
156 }
157 }
158}
159
160#[derive(Debug, Clone)]
161pub enum FnAttr {
162 PointerType(PointerType),
163 PropGet,
164 PropPut,
165 PropPutRef,
166}
167
168#[derive(Debug, Clone)]
169pub struct FnArg {
170 pub attrs: Vec<Sp<ArgAttr>>,
171 pub name: Option<Sp<String>>,
172 pub ty: Sp<Ctype>,
173 pub arr: bool,
174}
175
176impl FnArg {
177 pub fn visit_type_idents<F: FnMut(&str)>(&self, f: F) {
178 self.ty.visit_type_idents(f);
179 }
180}
181
182#[derive(Debug, Clone)]
183pub enum ArgAttr {
184 In,
185 MaxIs(Vec<Option<Cexpr>>),
186 Out,
187 PointerType(PointerType),
188 Poly(String),
189 RetVal,
190 SizeIs(Vec<Option<Cexpr>>),
191}
192
193#[derive(Debug, Clone)]
194pub enum Cexpr {
195 Ident(String),
196 Deref(Box<Cexpr>),
197}
198
199#[derive(Debug, Clone, Eq, PartialEq)]
200pub struct Ctype {
201 pub typename: String,
202 pub is_const: bool,
203 pub indirection: Vec<Ptr>,
204}
205
206impl Ctype {
207 pub fn visit_type_idents<F: FnMut(&str)>(&self, mut f: F) {
208 f(&self.typename);
209 }
210
211 pub fn is_void(&self) -> bool {
212 &self.typename == "void" && self.indirection.is_empty()
213 }
214}
215
216#[derive(Debug, Clone, Copy, Eq, PartialEq)]
217pub struct Ptr {
218 pub is_const: bool,
219}
220
221#[derive(Debug, Clone)]
222pub struct Str<'a>(Vec<StrComponent<'a>>);
223
224#[derive(Debug, Clone)]
225pub enum StrComponent<'a> {
226 Literal(&'a str),
227 Esc(char),
228}
229
230impl<'a> StrComponent<'a> {
231 fn len(&self) -> usize {
232 match self {
233 StrComponent::Literal(v) => v.len(),
234 StrComponent::Esc(v) => v.len_utf8(),
235 }
236 }
237}
238
239impl<'a> Str<'a> {
240 pub fn from_str(s: &'a str) -> Result<Self, StrError> {
241 let mut state = Vec::new();
242 let mut iter = s.char_indices();
243
244 while let Some((pos, ch)) = iter.next() {
245 if ch == '\\' {
246 let (_, esc_type) = iter.next().ok_or(StrError::PartialEscape)?;
247
248 if esc_type == 'u' || esc_type == 'U' {
249 let size = if esc_type == 'u' { 4 } else { 8 };
250 let (from, _) = iter.next().ok_or(StrError::PartialEscape)?;
251
252 for _ in 2..size {
253 let _ = iter.next().ok_or(StrError::PartialEscape)?;
254 }
255
256 let (to, last) = iter.next().ok_or(StrError::PartialEscape)?;
257 let to = to + last.len_utf8();
258 let spec = &s[from..to];
259 let num = u32::from_str_radix(s, 16)
260 .map_err(|_| StrError::InvalidUnicode(from, spec.to_owned(), to))?;
261 state.push(StrComponent::Esc(
262 char::from_u32(num as u32).ok_or(StrError::InvalidUnicode(
263 from,
264 spec.to_owned(),
265 to,
266 ))?,
267 ));
268 } else if esc_type == 'n' {
269 state.push(StrComponent::Esc('\n'));
270 } else if esc_type == 'r' {
271 state.push(StrComponent::Esc('\r'));
272 } else if esc_type == 't' {
273 state.push(StrComponent::Esc('\t'));
274 } else if esc_type == '0' {
275 state.push(StrComponent::Esc('\0'));
276 }
277 } else {
278 if let Some(StrComponent::Literal(ref mut lit)) = state.last_mut() {
279 let diff = lit.as_ptr() as usize - s.as_ptr() as usize;
280 *lit = &s[diff..diff + lit.len() + ch.len_utf8()];
281 } else {
282 state.push(StrComponent::Literal(&s[pos..pos + ch.len_utf8()]));
283 }
284 }
285 }
286
287 Ok(Str(state))
288 }
289
290 fn to_string(&self) -> String {
291 let len = self.0.iter().map(|v| v.len()).sum();
292 let mut s = String::with_capacity(len);
293
294 for el in self.0.iter() {
295 match el {
296 StrComponent::Literal(v) => s.push_str(v.as_ref()),
297 StrComponent::Esc(v) => s.push(*v),
298 }
299 }
300
301 s
302 }
303
304 pub fn to_str(&self) -> Cow<str> {
305 match &*self.0 {
306 [] => Cow::Borrowed(""),
307 [StrComponent::Literal(s)] => Cow::Borrowed(s.as_ref()),
308 _ => Cow::Owned(self.to_string()),
309 }
310 }
311}
312
313impl<'a> Display for Str<'a> {
314 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
315 for el in self.0.iter() {
316 match el {
317 StrComponent::Literal(v) => write!(f, "{}", v)?,
318 StrComponent::Esc(v) => write!(f, "{}", v)?,
319 }
320 }
321
322 Ok(())
323 }
324}
325
326#[derive(Debug, Error)]
327pub enum StrError {
328 #[error("partial escape sequence")]
329 PartialEscape,
330 #[error("invalid unicode escape: {1}")]
331 InvalidUnicode(usize, String, usize),
332}
333
334#[derive(Copy, Clone, Debug, Eq, PartialEq)]
335pub struct Sp<T> {
336 inner: T,
337 span: Span,
338}
339
340impl<T> Deref for Sp<T> {
341 type Target = T;
342
343 fn deref(&self) -> &Self::Target {
344 &self.inner
345 }
346}
347
348impl<T, R> AsRef<R> for Sp<T>
349where
350 T: AsRef<R>,
351 R: ?Sized,
352{
353 fn as_ref(&self) -> &R {
354 self.inner.as_ref()
355 }
356}
357
358impl<T> Sp<T> {
359 pub fn new(inner: T, left: usize, right: usize) -> Self {
360 Self::new_from_span(inner, Span::new(left as u32, right as u32))
361 }
362
363 pub fn new_from_span(inner: T, span: Span) -> Self {
364 Self { inner, span }
365 }
366
367 pub fn inner(&self) -> &T {
368 &self.inner
369 }
370
371 pub fn into_inner(self) -> T {
372 self.inner
373 }
374
375 pub fn span(&self) -> Span {
376 self.span
377 }
378
379 pub fn map<F, R>(self, f: F) -> Sp<R>
380 where
381 F: FnOnce(T) -> R,
382 {
383 Sp {
384 inner: f(self.inner),
385 span: self.span,
386 }
387 }
388}