1use std::{ffi::OsString, path::PathBuf};
40
41mod c_interfaces;
42mod client_gen;
43mod common;
44mod interfaces;
45mod parse;
46mod protocol;
47mod server_gen;
48mod token;
49mod util;
50
51#[proc_macro]
53pub fn generate_interfaces(stream: proc_macro::TokenStream) -> proc_macro::TokenStream {
54 let path: OsString = token::parse_lit_str_token(stream).into();
55 let path = if let Some(manifest_dir) = std::env::var_os("CARGO_MANIFEST_DIR") {
56 let mut buf = PathBuf::from(manifest_dir);
57 buf.push(path);
58 buf
59 } else {
60 path.into()
61 };
62 let file = match std::fs::File::open(&path) {
63 Ok(file) => file,
64 Err(e) => panic!("Failed to open protocol file {}: {}", path.display(), e),
65 };
66 let protocol = parse::parse(file);
67 interfaces::generate(&protocol, true).into()
68}
69
70#[proc_macro]
72pub fn generate_client_code(stream: proc_macro::TokenStream) -> proc_macro::TokenStream {
73 let path: OsString = token::parse_lit_str_token(stream).into();
74 let path = if let Some(manifest_dir) = std::env::var_os("CARGO_MANIFEST_DIR") {
75 let mut buf = PathBuf::from(manifest_dir);
76 buf.push(path);
77 buf
78 } else {
79 path.into()
80 };
81 let file = match std::fs::File::open(&path) {
82 Ok(file) => file,
83 Err(e) => panic!("Failed to open protocol file {}: {}", path.display(), e),
84 };
85 let protocol = parse::parse(file);
86 client_gen::generate_client_objects(&protocol).into()
87}
88
89#[proc_macro]
91pub fn generate_server_code(stream: proc_macro::TokenStream) -> proc_macro::TokenStream {
92 let path: OsString = token::parse_lit_str_token(stream).into();
93 let path = if let Some(manifest_dir) = std::env::var_os("CARGO_MANIFEST_DIR") {
94 let mut buf = PathBuf::from(manifest_dir);
95 buf.push(path);
96 buf
97 } else {
98 path.into()
99 };
100 let file = match std::fs::File::open(&path) {
101 Ok(file) => file,
102 Err(e) => panic!("Failed to open protocol file {}: {}", path.display(), e),
103 };
104 let protocol = parse::parse(file);
105 server_gen::generate_server_objects(&protocol).into()
106}
107
108#[cfg(test)]
109fn format_rust_code(code: &str) -> String {
110 use std::{
111 io::Write,
112 process::{Command, Stdio},
113 };
114 if let Ok(mut proc) = Command::new("rustfmt")
115 .arg("--emit=stdout")
116 .arg("--edition=2018")
117 .stdin(Stdio::piped())
118 .stdout(Stdio::piped())
119 .spawn()
121 {
122 {
123 let stdin = proc.stdin.as_mut().unwrap();
124 stdin.write_all(code.as_bytes()).unwrap();
125 }
126 if let Ok(output) = proc.wait_with_output() {
127 if output.status.success() {
128 return std::str::from_utf8(&output.stdout).unwrap().to_owned();
129 }
130 }
131 }
132 panic!("Rustfmt failed!");
133}
134
135#[derive(Copy, Clone, PartialEq, Eq, Debug)]
136enum Side {
137 Client,
139 Server,
141}