leetcode_api/leetcode/question/
qs_detail.rs1use std::fmt::Display;
2
3use sea_orm::sea_query::{self, OnConflict};
4use serde::{Deserialize, Serialize};
5
6use self::question::*;
7use crate::{dao::InsertToDB, entities::detail};
8
9#[derive(Clone)]
10#[derive(Debug)]
11#[derive(Default)]
12#[derive(PartialEq, Eq)]
13#[derive(Serialize, Deserialize)]
14pub struct QuestionData {
15 #[serde(default)]
16 pub data: Detail,
17}
18#[derive(Clone)]
19#[derive(Debug)]
20#[derive(Default)]
21#[derive(PartialEq, Eq)]
22#[derive(Serialize, Deserialize)]
23pub struct Detail {
24 #[serde(default)]
25 pub question: Question,
26}
27
28macro_rules! my_serde {
33 ($($struct_name:ident),*) => {
34 paste::paste! {
35 $(
36 mod [<$struct_name:snake:lower _serde>] {
37 use serde::{Deserialize, Deserializer, Serializer};
38
39 use super::question::$struct_name;
40
41 pub fn deserialize<'de, D>(deserializer: D) -> Result<$struct_name, D::Error>
42 where
43 D: Deserializer<'de>,
44 {
45 let s = String::deserialize(deserializer)?;
46
47 Ok(serde_json::from_str(&s).unwrap_or_default())
48 }
49
50 pub fn serialize<S>(v: &$struct_name, serializer: S) -> Result<S::Ok, S::Error>
51 where
52 S: Serializer,
53 {
54 let a = serde_json::to_string(v).unwrap_or_default();
55
56 serializer.serialize_str(&a)
57 }
58 }
59 )*
60 }
61 };
62}
63my_serde!(MetaData, Stats, EnvInfo);
64
65#[derive(Clone)]
67#[derive(Debug)]
68#[derive(Default)]
69#[derive(PartialEq, Eq)]
70#[derive(Serialize, Deserialize)]
71pub struct Question {
72 #[serde(default)]
73 pub qs_slug: Option<String>,
74 #[serde(default)]
75 pub content: Option<String>,
76 #[serde(default, with = "stats_serde")]
77 pub stats: Stats,
78 #[serde(default, alias = "sampleTestCase")]
79 pub sample_test_case: String,
80 #[serde(default, alias = "exampleTestcases")]
81 pub example_testcases: String,
82 #[serde(default, alias = "metaData", with = "meta_data_serde")]
83 pub meta_data: MetaData,
84 #[serde(default, alias = "translatedTitle")]
85 pub translated_title: Option<String>,
86 #[serde(default, alias = "translatedContent")]
87 pub translated_content: Option<String>,
88 #[serde(default)]
89 pub hints: Vec<String>,
90 #[serde(default, alias = "mysqlSchemas")]
91 pub mysql_schemas: Vec<String>,
92 #[serde(default, alias = "dataSchemas")]
93 pub data_schemas: Vec<String>,
94 #[serde(default, alias = "questionId")]
95 pub question_id: String,
96 #[serde(default, alias = "questionTitle")]
97 pub question_title: Option<String>,
98 #[serde(default, alias = "isPaidOnly")]
99 pub is_paid_only: bool,
100 #[serde(default, alias = "codeSnippets")]
101 pub code_snippets: Option<Vec<CodeSnippet>>,
102 #[serde(default)]
103 pub title: String,
104 #[serde(default)]
105 pub difficulty: String,
106 #[serde(default, alias = "topicTags")]
107 pub topic_tags: Vec<TopicTags>,
108 #[serde(default, alias = "enableRunCode")]
109 pub enable_run_code: bool,
110 #[serde(default, alias = "envInfo", with = "env_info_serde")]
111 pub env_info: EnvInfo,
112}
113
114impl Question {
115 pub fn new_with_info<D: Display>(content: D) -> Self {
116 Self {
117 content: Some(content.to_string()),
118 ..Default::default()
119 }
120 }
121}
122
123impl InsertToDB for Question {
124 type Value = u32;
125 type Entity = detail::Entity;
126 type Model = detail::Model;
127 type ActiveModel = detail::ActiveModel;
128
129 fn to_model(&self, question_id: Self::Value) -> Self::Model {
130 Self::Model {
131 id: question_id,
132 content: serde_json::to_string(self).unwrap_or_default(),
133 }
134 }
135 fn on_conflict() -> OnConflict {
136 sea_query::OnConflict::column(detail::Column::Id)
137 .update_columns([detail::Column::Id, detail::Column::Content])
138 .to_owned()
139 }
140}
141
142pub mod question {
143 use std::fmt::Display;
144
145 use serde::{Deserialize, Serialize};
146
147 macro_rules! env_info_macro {
148 ($($lang_name:ident),*) => {
149 #[derive(Clone)]
150 #[derive(Debug)]
151 #[derive(Default)]
152 #[derive(PartialEq, Eq)]
153 #[derive(Serialize, Deserialize)]
154 pub struct EnvInfo {
155 $(
156 #[serde(default)]
157 $lang_name : Vec<String>,
158 )*
159 }
160 impl Display for EnvInfo {
161 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
162 let mut res = String::new();
163 $(
164 if !self.$lang_name.is_empty() {
165 let pat = format!("\n### {}", format_args!("{}\n", self.$lang_name.join("\n")));
166 res.push_str(&pat);
167 }
168 )*
169 res.fmt(f)
170 }
171 }
172 };
173 }
174 env_info_macro!(
175 bash, c, cpp, csharp, dart, elixir, erlang, golang, java, javascript, kotlin, mssql, mysql,
176 oraclesql, postgresql, php, python, python3, pythondata, pythonml, racket, react, ruby,
177 rust, scala, swift, typescript
178 );
179
180 #[derive(Clone)]
181 #[derive(Debug)]
182 #[derive(Default)]
183 #[derive(PartialEq, Eq)]
184 #[derive(Serialize, Deserialize)]
185 pub struct Stats {
186 #[serde(alias = "totalAccepted")]
187 pub total_accepted: String,
188 #[serde(alias = "totalSubmission")]
189 pub total_submission: String,
190 #[serde(alias = "totalAcceptedRaw")]
191 pub total_accepted_raw: usize,
192 #[serde(alias = "totalSubmissionRaw")]
193 pub total_submission_raw: usize,
194 #[serde(alias = "acRate")]
195 pub ac_rate: String,
196 }
197 #[derive(Clone)]
199 #[derive(Debug)]
200 #[derive(Default)]
201 #[derive(PartialEq, Eq)]
202 #[derive(Serialize, Deserialize)]
203 pub struct MetaData {
204 #[serde(default)]
205 pub name: String,
206 #[serde(default)]
207 pub params: Vec<Param>,
208 #[serde(default)]
209 pub r#return: Return,
210 }
211
212 #[derive(Clone)]
214 #[derive(Debug)]
215 #[derive(Default)]
216 #[derive(PartialEq, Eq)]
217 #[derive(Serialize, Deserialize)]
218 pub struct Param {
219 #[serde(default)]
220 pub name: String,
221 #[serde(default)]
222 pub r#type: String,
223 }
225
226 #[derive(Clone)]
228 #[derive(Debug)]
229 #[derive(Default)]
230 #[derive(PartialEq, Eq)]
231 #[derive(Serialize, Deserialize)]
232 pub struct Return {
233 #[serde(default)]
234 pub r#type: String,
235 }
237
238 #[derive(Clone)]
239 #[derive(Debug)]
240 #[derive(Default)]
241 #[derive(PartialEq, Eq)]
242 #[derive(Serialize, Deserialize)]
243 pub struct CodeSnippet {
245 #[serde(default)]
246 pub lang: String,
247 #[serde(default, alias = "langSlug")]
248 pub lang_slug: String,
249 #[serde(default)]
250 pub code: String,
251 }
252
253 #[derive(Clone)]
254 #[derive(Debug)]
255 #[derive(Default)]
256 #[derive(PartialEq, Eq)]
257 #[derive(Serialize, Deserialize)]
258 pub struct TopicTags {
259 #[serde(default)]
260 pub name: String,
261 #[serde(default)]
262 pub slug: String,
263 #[serde(default, alias = "translatedName")]
264 pub translated_name: Option<String>,
265 }
266}