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