1#![allow(non_snake_case)]
7
8
9use crate::utils::none_to_empty_string;
10
11use crate::data_types::*;
12use crate::consts;
13
14mod dnspod_lib {
16 pub use crate::data_types;
17 pub use crate::serde;
18 pub use crate::consts;
19}
20
21#[macro_export]
22macro_rules! overloading_common_params {
23 (url = $expr: expr) => {
24 #[inline] fn url(&self) -> &'static str { $expr }
25 };
26 (version = $expr: expr) => {
27 #[inline] fn version(&self) -> $crate::data_types::Version { $expr }
28 };
29 (region = $expr: expr) => {
30 #[inline] fn region(&self) -> Option<$crate::data_types::Region> { Some($expr) }
31 };
32 ($($tt: tt)*) => {
33 compile_error!("This macro only accepts `url` `region` `version`");
34 };
35}
36
37#[macro_export]
38macro_rules! impl_define_action_list {
39 (
40 $(
41 $(#[$meta: meta])*
42 $(@[$($my_meta: tt)*])*
43 $vis: vis struct $name: ident $body: tt
44 )*
45 ) => {
46 $(
47 $(#[$meta])*
48 $vis struct $name $body
49
50 const _: () = {
51 use $crate::ExtractCommonParams;
52 use $crate::serde_json;
53
54 impl ExtractCommonParams for $name {
55 #[inline] fn action(&self) -> &'static str { stringify!($name) }
56 #[inline] fn body(&self) -> Vec<u8> { serde_json::to_vec(self).unwrap() }
57 $(
58 $crate::overloading_common_params! { $($my_meta)* }
59 )*
60 }
61 };
62 )*
63 };
64
65 (
66 $(#[$enum_meta: meta])*
67 $enum_vis: vis enum $enum_name: ident {}
68 ,
69 $(
70 $(#[$meta: meta])*
71 $(@[$($my_meta: tt)*])*
72 $vis: vis struct $name: ident $body: tt
73 )*
74 ) => {
75 $crate::impl_define_action_list! {
76 $(
77 $(#[$meta])*
78 $(@[$($my_meta)*])*
79 $vis struct $name $body
80 )*
81 }
82
83 $(
84 impl From<$name> for $enum_name {
85 #[inline] fn from(v: $name) -> Self { Self::$name(v) }
86 }
87 )*
88
89 $(#[$enum_meta])*
90 $enum_vis enum $enum_name {
91 $($name($name),)*
92 }
93
94 impl $crate::ExtractCommonParams for $enum_name {
95 #[inline]
96 fn action(&self) -> &'static str {
97 #[allow(unreachable_patterns)]
98 match self {
99 $(Self::$name(v) => v.action(),)*
100 _ => Default::default(),
101 }
102 }
103 #[inline]
104 fn body(&self) -> Vec<u8> {
105 #[allow(unreachable_patterns)]
106 match self {
107 $(Self::$name(v) => v.body(), )*
108 _ => Default::default(),
109 }
110 }
111 #[inline]
112 fn url(&self) -> &'static str {
113 #[allow(unreachable_patterns)]
114 match self {
115 $(Self::$name(v) => v.url(), )*
116 _ => Default::default(),
117 }
118 }
119 #[inline]
120 fn version(&self) -> $crate::data_types::Version {
121 #[allow(unreachable_patterns)]
122 match self {
123 $(Self::$name(v) => v.version(), )*
124 _ => Default::default(),
125 }
126 }
127 #[inline]
128 fn region(&self) -> Option<$crate::data_types::Region> {
129 #[allow(unreachable_patterns)]
130 match self {
131 $(Self::$name(v) => v.region(), )*
132 _ => Default::default(),
133 }
134 }
135 }
136 };
137}
138
139#[macro_export]
141macro_rules! define_action_list {
142 (
143 $($tt: tt)*
144 ) => {
145 $crate::custom_meta_struct! {
146 (
147 $crate::impl_define_action_list,
149 #[derive(Debug, Clone, $crate::serde::Serialize, $crate::serde::Deserialize)]
151 #[serde(crate = "dnspod_lib::serde")]
152 ),
153 $($tt)*
154 }
155 };
156}
157
158macro_rules! define_action_list_private {
159 (
160 $($tt: tt)*
161 ) => {
162 $crate::impl_define_action_list! {
163 #[derive(Debug, Clone)]
164 #[cfg_attr(feature = "clap", derive(clap::Subcommand))]
165 #[allow(non_snake_case)]
166 pub enum Action {}
167 ,
168 $($tt)*
169 }
170 };
171}
172
173
174crate::custom_meta_struct! {
175 (
176 define_action_list_private, #[cfg_attr(feature = "clap", derive(clap::Parser))]
180 #[derive(Debug, Clone, crate::serde::Serialize, crate::serde::Deserialize)]
181 #[serde(crate = "dnspod_lib::serde")]
182 ),
183
184 @[url = consts::DNSPOD_URL]
187 @[version = Version::Version2021_03_23]
188 pub struct DescribeDomainList {
189 #[cfg_attr(feature = "clap", arg(long, value_enum, default_value_t=Default::default()))]
191 pub Type: DomainType,
192 #[cfg_attr(feature = "clap", arg(long, default_value_t=0))]
195 pub Offset: Integer,
196 #[cfg_attr(feature = "clap", arg(long, default_value_t=3000))]
199 pub Limit: Integer,
200 #[cfg_attr(feature = "clap", arg(long, default_value_t=0))]
203 pub GroupId: Integer,
204 #[cfg_attr(feature = "clap", arg(long, default_value=""))]
207 pub Keyword: Option<String>,
208 }
209
210 pub struct CreateDomain {
212 Domain: String,
213 }
214 pub struct DeleteDomain {
216 Domain: String,
217 }
218
219 pub struct CreateRecord {
221 #[cfg_attr(feature = "clap", arg(long))]
224 pub Domain: String,
225 #[cfg_attr(feature = "clap", arg(long, default_value = "@"))]
228 pub SubDomain: String,
229 #[cfg_attr(feature = "clap", arg(long, value_enum, rename_all = "UPPER"))]
232 pub RecordType: RecordType,
233 #[cfg_attr(feature = "clap", arg(long, value_enum, default_value_t=Default::default()))]
236 pub RecordLine: RecordLine,
237 #[cfg_attr(feature = "clap", arg(long))]
240 pub Value: String,
241 }
242
243 pub struct DeleteRecord {
246 #[cfg_attr(feature = "clap", arg(long))]
249 pub Domain: String,
250 #[cfg_attr(feature = "clap", arg(long))]
253 pub RecordId: u64,
254 }
255
256 pub struct DescribeRecordList {
259 #[cfg_attr(feature = "clap", arg(long))]
262 pub Domain: String,
263 #[serde(serialize_with = "none_to_empty_string")]
266 #[cfg_attr(feature = "clap", arg(long, default_value=""))]
267 pub Subdomain: Option<String>,
268 #[serde(skip_serializing_if = "Option::is_none")]
271 #[cfg_attr(feature = "clap", arg(long, default_value=""))]
272 pub Keyword: Option<String>,
273 }
274
275 pub struct DescribeRecord {
278 #[cfg_attr(feature = "clap", arg(long))]
281 pub Domain: String,
282 #[cfg_attr(feature = "clap", arg(long))]
285 pub RecordId: u64,
286 }
287
288 pub struct DescribeRecordType {
290 #[cfg_attr(feature = "clap", arg(long))]
298 pub DomainGrade: DomainGrade,
299 }
300 pub struct DescribeRecordLineList {
302 pub Domain: String,
305 #[cfg_attr(feature = "clap", arg(long))]
306 pub DomainGrade: DomainGrade,
308 }
309
310 pub struct ModifyDynamicDNS {
313 #[cfg_attr(feature = "clap", arg(long))]
316 pub Domain: String,
317 #[cfg_attr(feature = "clap", arg(long, default_value="@"))]
320 pub SubDomain: String,
321 #[cfg_attr(feature = "clap", arg(long))]
324 pub RecordId: u64,
325 #[cfg_attr(feature = "clap", arg(value_enum, default_value_t=Default::default()))]
328 pub RecordLine: RecordLine,
329 #[cfg_attr(feature = "clap", arg(long))]
332 pub Value: String,
333 #[cfg_attr(feature = "clap", arg(long, default_value_t=600))]
336 pub Ttl: Integer,
337 }
338
339 pub struct ModifyRecord {
342 #[cfg_attr(feature = "clap", arg(long))]
345 pub Domain: String,
346 #[cfg_attr(feature = "clap", arg(long, default_value="@"))]
349 pub SubDomain: String,
350 #[cfg_attr(feature = "clap", arg(long))]
353 pub RecordId: u64,
354 #[cfg_attr(feature = "clap", arg(long))]
357 pub RecordType: RecordType,
358 #[cfg_attr(feature = "clap", arg(long, value_enum, default_value_t=Default::default()))]
361 pub RecordLine: RecordLine,
362 #[cfg_attr(feature = "clap", arg(long))]
365 pub Value: String,
366 }
367}
368
369
370
371#[cfg(test)]
372mod tests {
373 use super::*;
374
375 super::super::define_action_list! {}
376
377 crate::define_action_list! {
378 @[url = "https://hangj.cnblogs.com"]
380 struct A;
381 struct B;
383 }
384
385 crate::define_action_list! {
386 @[url = "https://example.com"] pub struct DescribeDomain {
390 #[serde(rename = "Domain")]
392 pub domain: String,
393 }
394
395 @[version = dnspod_lib::data_types::Version::Version2021_03_23]
396 #[allow(non_snake_case)]
397 pub struct CustomAction {
398 pub Domain: String,
400 }
401 }
402}