1#![cfg_attr(docsrs, feature(doc_auto_cfg))]
8
9mod common;
10#[allow(unused)]
11mod panic;
12mod supported_validators;
13mod validator_handlers;
14
15use proc_macro::TokenStream;
16use syn::{
17 parse::{Parse, ParseStream},
18 parse_macro_input,
19 spanned::Spanned,
20 DeriveInput, Meta,
21};
22#[allow(unused)]
23use validator_handlers::ValidatorHandler;
24
25use crate::supported_validators::Validator;
26
27fn derive_input_handler(ast: DeriveInput) -> syn::Result<proc_macro2::TokenStream> {
28 let mut use_validator: Option<(Validator, Meta)> = None;
29
30 for attr in ast.attrs.iter() {
31 let path = attr.path();
32
33 if path.is_ident("validator") {
34 if let Meta::List(list) = &attr.meta {
35 let meta: Meta = list.parse_args()?;
36
37 let path = meta.path();
38
39 if let Some(validator) = Validator::from_path(path) {
40 if use_validator.is_some() {
41 return Err(panic::validator_only_one_at_a_time(path.span()));
42 }
43
44 use_validator = Some((validator, meta));
45 } else {
46 return Err(panic::unsupported_validator(path));
47 }
48 } else {
49 return Err(panic::validator_format_incorrect(path.span()));
50 }
51 }
52 }
53
54 if let Some((validator, meta)) = use_validator {
55 match validator {
56 #[cfg(feature = "base32")]
57 Validator::base32 => {
58 return validator_handlers::base32::Base32Handler::meta_handler(ast, meta);
59 },
60 #[cfg(feature = "base32_decoded")]
61 Validator::base32_decoded => {
62 return validator_handlers::base32_decoded::Base32DecodedHandler::meta_handler(
63 ast, meta,
64 );
65 },
66 #[cfg(feature = "base64")]
67 Validator::base64 => {
68 return validator_handlers::base64::Base64Handler::meta_handler(ast, meta);
69 },
70 #[cfg(feature = "base64_decoded")]
71 Validator::base64_decoded => {
72 return validator_handlers::base64_decoded::Base64DecodedHandler::meta_handler(
73 ast, meta,
74 );
75 },
76 #[cfg(feature = "base64_url")]
77 Validator::base64_url => {
78 return validator_handlers::base64_url::Base64UrlHandler::meta_handler(ast, meta);
79 },
80 #[cfg(feature = "base64_url_decoded")]
81 Validator::base64_url_decoded => {
82 return validator_handlers::base64_url_decoded::Base64UrlDecodedHandler::meta_handler(
83 ast, meta,
84 );
85 },
86 #[cfg(feature = "bit")]
87 Validator::bit => {
88 return validator_handlers::bit::BitHandler::meta_handler(ast, meta);
89 },
90 #[cfg(feature = "boolean")]
91 Validator::boolean => {
92 return validator_handlers::boolean::BooleanHandler::meta_handler(ast, meta);
93 },
94 #[cfg(feature = "byte")]
95 Validator::byte => {
96 return validator_handlers::byte::ByteHandler::meta_handler(ast, meta);
97 },
98 #[cfg(feature = "domain")]
99 Validator::domain => {
100 return validator_handlers::domain::DomainHandler::meta_handler(ast, meta);
101 },
102 #[cfg(feature = "email")]
103 Validator::email => {
104 return validator_handlers::email::EmailHandler::meta_handler(ast, meta);
105 },
106 #[cfg(feature = "host")]
107 Validator::host => {
108 return validator_handlers::host::HostHandler::meta_handler(ast, meta);
109 },
110 #[cfg(feature = "http_url")]
111 Validator::http_url => {
112 return validator_handlers::http_url::HttpUrlHandler::meta_handler(ast, meta);
113 },
114 #[cfg(feature = "http_ftp_url")]
115 Validator::http_ftp_url => {
116 return validator_handlers::http_ftp_url::HttpFtpUrlHandler::meta_handler(
117 ast, meta,
118 );
119 },
120 #[cfg(feature = "ip")]
121 Validator::ip => {
122 return validator_handlers::ip::IpHandler::meta_handler(ast, meta);
123 },
124 #[cfg(feature = "ipv4")]
125 Validator::ipv4 => {
126 return validator_handlers::ipv4::Ipv4Handler::meta_handler(ast, meta);
127 },
128 #[cfg(feature = "ipv6")]
129 Validator::ipv6 => {
130 return validator_handlers::ipv6::Ipv6Handler::meta_handler(ast, meta);
131 },
132 #[cfg(feature = "json")]
133 Validator::json => {
134 return validator_handlers::json::JsonHandler::meta_handler(ast, meta);
135 },
136 #[cfg(feature = "length")]
137 Validator::length => {
138 return validator_handlers::length::LengthHandler::meta_handler(ast, meta);
139 },
140 #[cfg(feature = "line")]
141 Validator::line => {
142 return validator_handlers::line::LineHandler::meta_handler(ast, meta);
143 },
144 #[cfg(feature = "mac_address")]
145 Validator::mac_address => {
146 return validator_handlers::mac_address::MacAddressHandler::meta_handler(ast, meta);
147 },
148 #[cfg(feature = "number")]
149 Validator::number => {
150 return validator_handlers::number::NumberHandler::meta_handler(ast, meta);
151 },
152 #[cfg(feature = "phone")]
153 Validator::phone => {
154 return validator_handlers::phone::PhoneHandler::meta_handler(ast, meta);
155 },
156 #[cfg(feature = "regex")]
157 Validator::regex => {
158 return validator_handlers::regex::RegexHandler::meta_handler(ast, meta);
159 },
160 #[cfg(feature = "semver")]
161 Validator::semver => {
162 return validator_handlers::semver::SemverHandler::meta_handler(ast, meta);
163 },
164 #[cfg(feature = "semver_req")]
165 Validator::semver_req => {
166 return validator_handlers::semver_req::SemverReqHandler::meta_handler(ast, meta);
167 },
168 #[cfg(feature = "signed_integer")]
169 Validator::signed_integer => {
170 return validator_handlers::signed_integer::SignedIntegerHandler::meta_handler(
171 ast, meta,
172 );
173 },
174 #[cfg(feature = "text")]
175 Validator::text => {
176 return validator_handlers::text::TextHandler::meta_handler(ast, meta);
177 },
178 #[cfg(feature = "unsigned_integer")]
179 Validator::unsigned_integer => {
180 return validator_handlers::unsigned_integer::UnsignedIntegerHandler::meta_handler(
181 ast, meta,
182 );
183 },
184 #[cfg(feature = "url")]
185 Validator::url => {
186 return validator_handlers::url::UrlHandler::meta_handler(ast, meta);
187 },
188 #[cfg(feature = "uuid")]
189 Validator::uuid => {
190 return validator_handlers::uuid::UuidHandler::meta_handler(ast, meta);
191 },
192 Validator::_Nothing => {
193 let _ = meta;
195 unreachable!();
196 },
197 }
198 }
199
200 Err(panic::derive_attribute_not_set_up_yet())
201}
202
203#[proc_macro_derive(Validator, attributes(validator))]
204pub fn validator_derive(input: TokenStream) -> TokenStream {
205 struct MyDeriveInput(proc_macro2::TokenStream);
206
207 impl Parse for MyDeriveInput {
208 #[inline]
209 fn parse(input: ParseStream) -> syn::Result<Self> {
210 let token_stream = derive_input_handler(input.parse::<DeriveInput>()?)?;
211
212 Ok(Self(token_stream))
213 }
214 }
215
216 let derive_input = parse_macro_input!(input as MyDeriveInput);
218
219 derive_input.0.into()
220}