openrr_internal_codegen/
main.rs1mod plugin;
2mod rpc;
3
4use std::path::{Path, PathBuf};
5
6use anyhow::{Result, format_err};
7use fs_err as fs;
8use proc_macro2::TokenStream;
9
10fn main() -> Result<()> {
11 let workspace_root = workspace_root();
12 plugin::r#gen(&workspace_root)?;
13 rpc::r#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 && let Some(path) = get_ty_path(&ty.elem)
64 && path.is_ident("str")
65 {
66 return true;
67 }
68 false
69}
70
71fn get_ty_path(ty: &syn::Type) -> Option<&syn::Path> {
72 if let syn::Type::Path(ty) = ty {
73 return Some(&ty.path);
74 }
75 None
76}
77
78fn is_option(ty: &syn::Type) -> Option<&syn::Type> {
79 let path = get_ty_path(ty)?;
80 if path.segments.len() == 1
81 && path.segments[0].ident == "Option"
82 && let syn::PathArguments::AngleBracketed(args) = &path.segments.last().unwrap().arguments
83 && let syn::GenericArgument::Type(ty) = &args.args[0]
84 {
85 return Some(ty);
86 }
87 None
88}
89
90fn is_result(ty: &syn::Type) -> Option<&syn::Type> {
91 let path = get_ty_path(ty)?;
92 if path.segments.len() == 1
93 && path.segments[0].ident == "Result"
94 && let syn::PathArguments::AngleBracketed(args) = &path.segments.last().unwrap().arguments
95 && let syn::GenericArgument::Type(ty) = &args.args[0]
96 {
97 return Some(ty);
98 }
99 None
100}
101
102fn is_vec(ty: &syn::Type) -> Option<&syn::Type> {
103 let path = get_ty_path(ty)?;
104 if path.segments.len() == 1
105 && path.segments[0].ident == "Vec"
106 && let syn::PathArguments::AngleBracketed(args) = &path.segments.last().unwrap().arguments
107 && let syn::GenericArgument::Type(ty) = &args.args[0]
108 {
109 return Some(ty);
110 }
111 None
112}
113
114pub(crate) fn is_primitive(ty: &syn::Type) -> bool {
115 if let Some(path) = get_ty_path(ty)
116 && let Some(ident) = path.get_ident()
117 {
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 false
138}
139
140fn workspace_root() -> PathBuf {
141 let mut dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
142 dir.pop(); dir.pop(); dir
145}
146
147fn header() -> String {
148 concat!(
149 "// This file is @generated by ",
150 env!("CARGO_BIN_NAME"),
151 ".\n",
152 "// It is not intended for manual editing.\n",
153 "\n",
154 "#![allow(unused_variables)]\n",
155 "#![allow(clippy::useless_conversion, clippy::unit_arg)]\n",
156 "\n",
157 )
158 .into()
159}
160
161fn write(path: &Path, contents: TokenStream) -> Result<()> {
162 let mut out = header().into_bytes();
163 out.extend_from_slice(
164 prettyplease::unparse(
165 &syn::parse2(contents.clone())
166 .map_err(|e| format_err!("{e} in:\n---\n{contents}\n---"))?,
167 )
168 .as_bytes(),
169 );
170 if path.is_file() && fs::read(path)? == out {
171 return Ok(());
172 }
173 fs::write(path, out)?;
174 Ok(())
175}