alef_e2e/codegen/rust/
cargo_toml.rs1use alef_core::hash::{self, CommentStyle};
4use alef_core::template_versions as tv;
5
6#[allow(clippy::too_many_arguments)]
11pub fn render_cargo_toml(
12 crate_name: &str,
13 dep_name: &str,
14 crate_path: &str,
15 needs_serde_json: bool,
16 needs_mock_server: bool,
17 needs_http_tests: bool,
18 needs_tokio: bool,
19 needs_tower_http: bool,
20 dep_mode: crate::config::DependencyMode,
21 version: Option<&str>,
22 features: &[String],
23) -> String {
24 let e2e_name = format!("{dep_name}-e2e-rust");
25 let effective_features: Vec<&str> = features.iter().map(|s| s.as_str()).collect();
29 let features_str = if effective_features.is_empty() {
30 String::new()
31 } else {
32 format!(", default-features = false, features = {:?}", effective_features)
33 };
34 let dep_spec = match dep_mode {
35 crate::config::DependencyMode::Registry => {
36 let ver = version.unwrap_or("0.1.0");
37 if crate_name != dep_name {
38 format!("{dep_name} = {{ package = \"{crate_name}\", version = \"{ver}\"{features_str} }}")
39 } else if effective_features.is_empty() {
40 format!("{dep_name} = \"{ver}\"")
41 } else {
42 format!("{dep_name} = {{ version = \"{ver}\"{features_str} }}")
43 }
44 }
45 crate::config::DependencyMode::Local => {
46 if crate_name != dep_name {
47 format!("{dep_name} = {{ package = \"{crate_name}\", path = \"{crate_path}\"{features_str} }}")
48 } else if effective_features.is_empty() {
49 format!("{dep_name} = {{ path = \"{crate_path}\" }}")
50 } else {
51 format!("{dep_name} = {{ path = \"{crate_path}\"{features_str} }}")
52 }
53 }
54 };
55 let effective_needs_serde_json = needs_serde_json || needs_mock_server || needs_http_tests;
59 let serde_line = if effective_needs_serde_json {
60 "\nserde_json = \"1\""
61 } else {
62 ""
63 };
64 let needs_axum = needs_mock_server || needs_http_tests;
73 let mock_lines = if needs_axum {
74 let mut lines = format!(
75 "\naxum = \"{axum}\"\nserde = {{ version = \"1\", features = [\"derive\"] }}\nwalkdir = \"{walkdir}\"",
76 axum = tv::cargo::AXUM,
77 walkdir = tv::cargo::WALKDIR,
78 );
79 if needs_mock_server {
80 lines.push_str(&format!(
81 "\ntokio-stream = \"{tokio_stream}\"",
82 tokio_stream = tv::cargo::TOKIO_STREAM
83 ));
84 }
85 if needs_http_tests {
86 lines.push_str("\naxum-test = \"20\"\nbytes = \"1\"");
87 }
88 if needs_tower_http {
89 lines.push_str(&format!(
90 "\ntower-http = {{ version = \"{tower_http}\", features = [\"cors\", \"fs\"] }}\ntempfile = \"{tempfile}\"",
91 tower_http = tv::cargo::TOWER_HTTP,
92 tempfile = tv::cargo::TEMPFILE,
93 ));
94 }
95 lines
96 } else {
97 String::new()
98 };
99 let mut machete_ignored: Vec<&str> = Vec::new();
100 if effective_needs_serde_json {
101 machete_ignored.push("\"serde_json\"");
102 }
103 if needs_axum {
104 machete_ignored.push("\"axum\"");
105 machete_ignored.push("\"serde\"");
106 machete_ignored.push("\"walkdir\"");
107 }
108 if needs_mock_server {
109 machete_ignored.push("\"tokio-stream\"");
110 }
111 if needs_http_tests {
112 machete_ignored.push("\"axum-test\"");
113 machete_ignored.push("\"bytes\"");
114 }
115 if needs_tower_http {
116 machete_ignored.push("\"tower-http\"");
117 machete_ignored.push("\"tempfile\"");
118 }
119 let machete_section = if machete_ignored.is_empty() {
120 String::new()
121 } else {
122 format!(
123 "\n[package.metadata.cargo-machete]\nignored = [{}]\n",
124 machete_ignored.join(", ")
125 )
126 };
127 let tokio_line = if needs_tokio {
128 "\ntokio = { version = \"1\", features = [\"full\"] }"
129 } else {
130 ""
131 };
132 let bin_section = if needs_mock_server || needs_http_tests {
133 "\n[[bin]]\nname = \"mock-server\"\npath = \"src/main.rs\"\n"
134 } else {
135 ""
136 };
137 let header = hash::header(CommentStyle::Hash);
138 format!(
139 r#"{header}
140[workspace]
141
142[package]
143name = "{e2e_name}"
144version = "0.1.0"
145edition = "2021"
146license = "MIT"
147publish = false
148{bin_section}
149[dependencies]
150{dep_spec}{serde_line}{mock_lines}{tokio_line}
151{machete_section}"#
152 )
153}
154
155#[cfg(test)]
156mod tests {
157 use super::*;
158 use crate::config::DependencyMode;
159
160 #[test]
161 fn render_cargo_toml_local_no_features_produces_path_dep() {
162 let out = render_cargo_toml(
165 "my-crate",
166 "my_crate",
167 "../../crates/my-crate",
168 false,
169 false,
170 false,
171 false,
172 false,
173 DependencyMode::Local,
174 None,
175 &[],
176 );
177 assert!(
178 out.contains("my_crate = { package = \"my-crate\", path = \"../../crates/my-crate\" }"),
179 "got:\n{out}"
180 );
181 assert!(out.contains("edition = \"2021\""));
182 }
183
184 #[test]
185 fn render_cargo_toml_local_same_name_produces_simple_path_dep() {
186 let out = render_cargo_toml(
188 "my_crate",
189 "my_crate",
190 "../../crates/my_crate",
191 false,
192 false,
193 false,
194 false,
195 false,
196 DependencyMode::Local,
197 None,
198 &[],
199 );
200 assert!(
201 out.contains("my_crate = { path = \"../../crates/my_crate\" }"),
202 "got:\n{out}"
203 );
204 }
205}