1use std::fmt::Display;
2
3use serde::{Deserialize, Serialize};
4
5const START_SLASH: &str = "// start /";
6const END_SLASH: &str = "// end /";
7const START_HASH: &str = "## start #";
8const END_HASH: &str = "## end #";
9const START_DASH: &str = "-- start -";
10const END_DASH: &str = "-- end -";
11
12macro_rules! skipfmt {
13 ($($code:tt)*) => { $($code)* }
14}
15
16macro_rules! lang_macro {
17 ($($struct_name:ident), *) => {
18 paste::paste! {
19 #[derive(Clone)]
20 #[derive(Debug)]
21 #[derive(Default)]
22 #[derive(PartialEq, Eq)]
23 #[derive(Serialize, Deserialize)]
24 pub struct SupportLang {
25 $(
26 #[serde(default)]
27 pub [<$struct_name:lower>]: $struct_name,
28 )*
29 }
30 }
31 $(
32 #[derive(Clone)]
33 #[derive(Debug)]
34 #[derive(PartialEq, Eq)]
35 #[derive(Serialize, Deserialize)]
36 pub struct $struct_name {
37 pub start: String,
38 pub end: String,
39 pub inject_start: String,
40 pub inject_end: String,
41 }
42 impl $struct_name {
43 pub fn return_info(&self) -> (String, String, String, String) {
45 (
46 self.start.to_owned(),
47 self.end.to_owned(),
48 self.inject_start.to_owned(),
49 self.inject_end.to_owned(),
50 )
51 }
52 }
53 )*
54 };
55}
56lang_macro!(
57 Bash, C, Cpp, Csharp, Dart, Elixir, Erlang, Golang, Java, Javascript, Kotlin, Mssql, Mysql,
58 Oraclesql, Postgresql, Php, Python, Python3, Racket, React, Ruby, Rust, Scala, Swift,
59 Typescript
60);
61macro_rules! defaults {
62 ($lang:ident, $start:expr, $end:expr, $inject_start:expr, $inject_end:expr) => {
63 impl Default for $lang {
64 fn default() -> Self {
65 Self {
66 start: $start.to_owned(),
67 end: $end.to_owned(),
68 inject_start: $inject_start.to_owned(),
69 inject_end: $inject_end.to_owned(),
70 }
71 }
72 }
73 };
74 ($lang:ident, $start:expr, $end:expr, $inject_start:expr) => {
75 impl Default for $lang {
76 fn default() -> Self {
77 Self {
78 start: $start.to_owned(),
79 end: $end.to_owned(),
80 inject_start: $inject_start.to_owned(),
81 inject_end: String::new(),
82 }
83 }
84 }
85 };
86 ($lang:ident, $start:expr, $end:expr, $inject_end:expr) => {
87 impl Default for $lang {
88 fn default() -> Self {
89 Self {
90 start: $start.to_owned(),
91 end: $end.to_owned(),
92 inject_start: String::new(),
93 inject_end: $inject_end.to_owned(),
94 }
95 }
96 }
97 };
98 ($lang:ident, $start:expr, $end:expr) => {
99 impl Default for $lang {
100 fn default() -> Self {
101 Self {
102 start: $start.to_owned(),
103 end: $end.to_owned(),
104 inject_start: String::new(),
105 inject_end: String::new(),
106 }
107 }
108 }
109 };
110}
111
112skipfmt!(
113defaults!(C , START_SLASH , END_SLASH);
114defaults!(Cpp , START_SLASH , END_SLASH);
115defaults!(Csharp , START_SLASH , END_SLASH);
116defaults!(Dart , START_SLASH , END_SLASH);
117defaults!(Golang , START_SLASH , END_SLASH);
118defaults!(Java , START_SLASH , END_SLASH);
119defaults!(Javascript, START_SLASH , END_SLASH);
120defaults!(Kotlin , START_SLASH , END_SLASH);
121defaults!(Php , START_SLASH , END_SLASH);
122defaults!(React , START_SLASH , END_SLASH);
123defaults!(Scala , START_SLASH , END_SLASH);
124defaults!(Swift , START_SLASH , END_SLASH);
125defaults!(Typescript, START_SLASH , END_SLASH);
126
127defaults!(Bash , START_HASH , END_HASH );
128defaults!(Elixir , START_HASH , END_HASH );
129defaults!(Python , START_HASH , END_HASH );
130defaults!(Python3 , START_HASH , END_HASH );
131defaults!(Ruby , START_HASH , END_HASH );
132
133defaults!(Mssql , START_DASH , END_DASH );
134defaults!(Mysql , START_DASH , END_DASH );
135defaults!(Oraclesql , START_DASH , END_DASH );
136defaults!(Postgresql, START_DASH , END_DASH );
137
138defaults!(Racket , ";; start ;", ";; end ;");
139defaults!(Erlang , "%% start %", "%% end %");
140);
141
142defaults!(
143 Rust,
144 START_SLASH,
145 END_SLASH,
146 "struct Solution;\n",
147 "
148fn main() {
149 let res = Solution::function(todo!());
150 dbg!(&res);
151 assert_eq!(res, todo!());
152}"
153);
154
155#[derive(Clone)]
156#[derive(Debug)]
157#[derive(PartialEq, Eq)]
158#[derive(Serialize, Deserialize)]
159pub struct Urls {
160 pub origin: String,
161 pub question_url: String,
162 pub graphql: String,
163 pub all_problem_api: String,
164 pub submit: String,
165 pub test: String,
166 pub submissions: String,
167 pub favorites: String,
168 pub points: String,
169}
170#[derive(Clone, Copy)]
171#[derive(Debug)]
172#[derive(Default)]
173#[derive(PartialEq, Eq)]
174pub enum Suffix {
175 Cn,
176 #[default]
177 Com,
178}
179
180impl Display for Suffix {
181 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
182 match self {
183 Self::Cn => "cn",
184 Self::Com => "com",
185 }
186 .fmt(f)
187 }
188}
189
190impl Urls {
191 pub fn new(suffix: Suffix) -> Self {
192 let suffix = match suffix {
193 Suffix::Cn => "cn",
194 Suffix::Com => "com",
195 };
196 Self {
197 origin: format!("https://leetcode.{}", suffix),
198 graphql: format!("https://leetcode.{}/graphql", suffix),
199 question_url: format!("https://leetcode.{}/problems/$slug/", suffix),
200 all_problem_api: format!("https://leetcode.{}/api/problems/$category", suffix),
201 submit: format!("https://leetcode.{}/problems/$slug/submit/", suffix),
202 test: format!(
203 "https://leetcode.{}/problems/$slug/interpret_solution/",
204 suffix
205 ),
206 submissions: format!("https://leetcode.{}/submissions/detail/$id/check/", suffix),
207 favorites: format!("https://leetcode.{}/list/api/questions", suffix),
208 points: format!("https://leetcode.{}/points/api/total/", suffix),
209 }
210 }
211
212 pub fn mod_all_pb_api(&self, category: &str) -> String {
213 self.all_problem_api
214 .replace("$category", category)
215 }
216
217 pub fn mod_submit(&self, slug: &str) -> String {
218 self.submit.replace("$slug", slug)
219 }
220
221 pub fn mod_test(&self, slug: &str) -> String {
222 self.test.replace("$slug", slug)
223 }
224
225 pub fn mod_submissions(&self, id: &str) -> String {
226 self.submissions.replace("$id", id)
227 }
228 pub fn get_qs_url(&self, slug: &str) -> String {
229 self.question_url.replace("$slug", slug)
230 }
231}
232
233impl Default for Urls {
234 fn default() -> Self {
235 Self::new(Suffix::default())
236 }
237}