openrr_internal_codegen/
main.rs
1mod plugin;
2mod rpc;
3
4use std::path::{Path, PathBuf};
5
6use anyhow::{format_err, Result};
7use fs_err as fs;
8use proc_macro2::TokenStream;
9
10fn main() -> Result<()> {
11 let workspace_root = workspace_root();
12 plugin::gen(&workspace_root)?;
13 rpc::gen(&workspace_root)?;
14 Ok(())
15}
16
17fn arci_types(
18 workspace_root: &Path,
19) -> Result<(
20 Vec<syn::ItemTrait>,
21 Vec<syn::ItemStruct>,
22 Vec<syn::ItemEnum>,
23)> {
24 let path = &workspace_root.join("arci/src/traits");
25 let mut files: Vec<_> = fs::read_dir(path)?
26 .filter_map(Result::ok)
27 .filter_map(|entry| {
28 let path = entry.path();
29 if !path.is_file() || path.extension().is_none_or(|e| e != "rs") {
30 None
31 } else {
32 Some(path)
33 }
34 })
35 .collect();
36 files.sort_unstable();
37 let mut traits = vec![];
38 let mut structs = vec![];
39 let mut enums = vec![];
40 for path in &files {
41 let s = &fs::read_to_string(path)?;
42 let file: syn::File = syn::parse_str(s)?;
43 for item in file.items {
44 match item {
45 syn::Item::Trait(item) if matches!(item.vis, syn::Visibility::Public(_)) => {
46 traits.push(item);
47 }
48 syn::Item::Struct(item) if matches!(item.vis, syn::Visibility::Public(_)) => {
49 structs.push(item);
50 }
51 syn::Item::Enum(item) if matches!(item.vis, syn::Visibility::Public(_)) => {
52 enums.push(item);
53 }
54 _ => {}
55 }
56 }
57 }
58 Ok((traits, structs, enums))
59}
60
61fn is_str(ty: &syn::Type) -> bool {
62 if let syn::Type::Reference(ty) = ty {
63 if let Some(path) = get_ty_path(&ty.elem) {
64 if path.is_ident("str") {
65 return true;
66 }
67 }
68 }
69 false
70}
71
72fn get_ty_path(ty: &syn::Type) -> Option<&syn::Path> {
73 if let syn::Type::Path(ty) = ty {
74 return Some(&ty.path);
75 }
76 None
77}
78
79fn is_option(ty: &syn::Type) -> Option<&syn::Type> {
80 let path = get_ty_path(ty)?;
81 if path.segments.len() == 1 && path.segments[0].ident == "Option" {
82 if let syn::PathArguments::AngleBracketed(args) = &path.segments.last().unwrap().arguments {
83 if let syn::GenericArgument::Type(ty) = &args.args[0] {
84 return Some(ty);
85 }
86 }
87 }
88 None
89}
90
91fn is_result(ty: &syn::Type) -> Option<&syn::Type> {
92 let path = get_ty_path(ty)?;
93 if path.segments.len() == 1 && path.segments[0].ident == "Result" {
94 if let syn::PathArguments::AngleBracketed(args) = &path.segments.last().unwrap().arguments {
95 if let syn::GenericArgument::Type(ty) = &args.args[0] {
96 return Some(ty);
97 }
98 }
99 }
100 None
101}
102
103fn is_vec(ty: &syn::Type) -> Option<&syn::Type> {
104 let path = get_ty_path(ty)?;
105 if path.segments.len() == 1 && path.segments[0].ident == "Vec" {
106 if let syn::PathArguments::AngleBracketed(args) = &path.segments.last().unwrap().arguments {
107 if let syn::GenericArgument::Type(ty) = &args.args[0] {
108 return Some(ty);
109 }
110 }
111 }
112 None
113}
114
115pub(crate) fn is_primitive(ty: &syn::Type) -> bool {
116 if let Some(path) = get_ty_path(ty) {
117 if let Some(ident) = path.get_ident() {
118 return matches!(
119 ident.to_string().as_str(),
120 "isize"
121 | "i8"
122 | "i16"
123 | "i32"
124 | "i64"
125 | "i128"
126 | "usize"
127 | "u8"
128 | "u16"
129 | "u32"
130 | "u64"
131 | "u128"
132 | "f32"
133 | "f64"
134 | "bool"
135 );
136 }
137 }
138 false
139}
140
141fn workspace_root() -> PathBuf {
142 let mut dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
143 dir.pop(); dir.pop(); dir
146}
147
148fn header() -> String {
149 concat!(
150 "// This file is @generated by ",
151 env!("CARGO_BIN_NAME"),
152 ".\n",
153 "// It is not intended for manual editing.\n",
154 "\n",
155 "#![allow(unused_variables)]\n",
156 "#![allow(clippy::useless_conversion, clippy::unit_arg)]\n",
157 "\n",
158 )
159 .into()
160}
161
162fn write(path: &Path, contents: TokenStream) -> Result<()> {
163 let mut out = header().into_bytes();
164 out.extend_from_slice(
165 prettyplease::unparse(
166 &syn::parse2(contents.clone())
167 .map_err(|e| format_err!("{e} in:\n---\n{contents}\n---"))?,
168 )
169 .as_bytes(),
170 );
171 if path.is_file() && fs::read(path)? == out {
172 return Ok(());
173 }
174 fs::write(path, out)?;
175 Ok(())
176}