autd3capi_wrapper_generator/
parse.rs1use std::{fs::File, io::Read, path::Path};
15
16use anyhow::Result;
17use syn::__private::ToTokens;
18
19use crate::types::{InOut, Type};
20
21#[derive(Debug, PartialEq, Eq, Hash)]
22pub struct Arg {
23 pub name: String,
24 pub ty: Type,
25 pub inout: InOut,
26 pub pointer: usize,
27}
28
29#[derive(Debug, PartialEq, Eq, Hash)]
30pub struct Function {
31 pub docs: Vec<String>,
32 pub name: String,
33 pub return_ty: Type,
34 pub args: Vec<Arg>,
35}
36
37#[derive(Debug, PartialEq, Eq, Hash)]
38pub struct Const {
39 pub name: String,
40 pub ty: Type,
41 pub value: String,
42}
43
44#[derive(Debug, PartialEq, Eq, Hash)]
45pub struct Enum {
46 pub name: String,
47 pub ty: Type,
48 pub values: Vec<(String, String)>,
49}
50
51#[derive(Debug, PartialEq, Eq, Hash)]
52pub struct Struct {
53 pub name: String,
54 pub fields: Vec<(Type, String)>,
55}
56
57pub fn parse_func<P>(header: P, use_single: bool) -> Result<Vec<Function>>
58where
59 P: AsRef<Path>,
60{
61 let mut file = File::open(header)?;
62 let mut contents = String::new();
63 file.read_to_string(&mut contents)?;
64
65 let syntax_tree = syn::parse_file(&contents)?;
66
67 Ok(syntax_tree
68 .items
69 .into_iter()
70 .filter_map(|item| match item {
71 syn::Item::Fn(item_fn) => {
72 let docs = item_fn
73 .attrs
74 .iter()
75 .filter(|attr| attr.path().is_ident("doc"))
76 .map(|attr| {
77 attr.meta
78 .require_name_value()
79 .unwrap()
80 .value
81 .clone()
82 .into_token_stream()
83 .to_string()
84 .trim()
85 .to_string()
86 })
87 .collect();
88
89 let name = item_fn.sig.ident.to_string();
90 let return_ty = Type::parse_return(item_fn.sig.output, use_single);
91 let args = item_fn
92 .sig
93 .inputs
94 .into_iter()
95 .map(|i| Type::parse_arg(i, use_single))
96 .collect::<Vec<_>>();
97
98 Some(Function {
99 docs,
100 name,
101 return_ty,
102 args,
103 })
104 }
105 _ => None,
106 })
107 .collect())
108}
109
110pub fn parse_const<P>(header: P, use_single: bool) -> Result<Vec<Const>>
111where
112 P: AsRef<Path>,
113{
114 let mut file = File::open(header)?;
115 let mut contents = String::new();
116 file.read_to_string(&mut contents)?;
117
118 let syntax_tree = syn::parse_file(&contents)?;
119
120 Ok(syntax_tree
121 .items
122 .into_iter()
123 .filter_map(|item| match item {
124 syn::Item::Const(item_const) => {
125 let name = item_const.ident.to_string();
126 let ty =
127 Type::parse_str(&item_const.ty.into_token_stream().to_string(), use_single);
128 let mut value = item_const.expr.into_token_stream().to_string();
129 value.retain(|c| !c.is_whitespace());
130
131 Some(Const { name, ty, value })
132 }
133 _ => None,
134 })
135 .collect())
136}
137
138pub fn parse_enum<P>(header: P, use_single: bool) -> Result<Vec<Enum>>
139where
140 P: AsRef<Path>,
141{
142 let mut file = File::open(header)?;
143 let mut contents = String::new();
144 file.read_to_string(&mut contents)?;
145
146 let syntax_tree = syn::parse_file(&contents)?;
147
148 Ok(syntax_tree
149 .items
150 .into_iter()
151 .filter_map(|item| match item {
152 syn::Item::Enum(item_enum) => {
153 let name = item_enum.ident.to_string();
154 let ty = Type::parse_str(
155 item_enum.attrs[0]
156 .meta
157 .require_list()
158 .unwrap()
159 .tokens
160 .to_string()
161 .as_str(),
162 use_single,
163 );
164 let values = item_enum
165 .variants
166 .into_iter()
167 .map(|v| {
168 let name = v.ident.to_string();
169 let value = v.discriminant.unwrap().1.into_token_stream().to_string();
170 (name, value)
171 })
172 .collect();
173
174 Some(Enum { name, ty, values })
175 }
176 _ => None,
177 })
178 .collect())
179}
180
181pub fn parse_struct<P>(header: P, use_single: bool) -> Result<Vec<Struct>>
182where
183 P: AsRef<Path>,
184{
185 let mut file = File::open(header)?;
186 let mut contents = String::new();
187 file.read_to_string(&mut contents)?;
188
189 let syntax_tree = syn::parse_file(&contents)?;
190
191 Ok(syntax_tree
192 .items
193 .into_iter()
194 .filter_map(|item| match item {
195 syn::Item::Struct(item_struct) => match item_struct.vis {
196 syn::Visibility::Public(_) => {
197 let name = item_struct.ident.to_string();
198 let fields = item_struct
199 .fields
200 .iter()
201 .filter(|f| f.ident.is_some())
202 .map(|f| {
203 (
204 Type::parse_str(
205 f.ty.clone().into_token_stream().to_string().as_str(),
206 use_single,
207 ),
208 f.ident.as_ref().unwrap().to_string(),
209 )
210 })
211 .collect();
212 Some(Struct { name, fields })
213 }
214 _ => None,
215 },
216 _ => None,
217 })
218 .collect())
219}