validify_derive/
validate.rs

1use proc_macro_error::abort;
2use syn::meta::ParseNestedMeta;
3
4pub mod r#impl;
5pub mod parser;
6pub mod validation;
7
8pub trait ValidationMeta {
9    /// Returns `true` if the meta consists of an ident, code and message.
10    /// Used for simple path validators such as `email` or `phone`.
11    fn is_full_pattern(&self) -> bool;
12
13    /// Returns `true` if the meta consists of a single literal
14    fn is_single_lit(&self, id: &str) -> bool;
15
16    /// Returns `true` if the meta consists of a single path
17    fn is_single_path(&self, id: &str) -> bool;
18}
19
20impl ValidationMeta for ParseNestedMeta<'_> {
21    fn is_full_pattern(&self) -> bool {
22        self.input
23            .cursor()
24            .group(proc_macro2::Delimiter::Parenthesis)
25            .is_some()
26    }
27
28    fn is_single_lit(&self, id: &str) -> bool {
29        let group_cursor = self.input.cursor().group(proc_macro2::Delimiter::Parenthesis).unwrap_or_else(||
30            abort!(self.input.span(), format!("{id} must be specified as a list, i.e. `{id}(\"foo\")` or `{id}(parameter = \"foo\")`"))
31        ).0;
32        group_cursor.literal().is_some()
33    }
34
35    fn is_single_path(&self, id: &str) -> bool {
36        let (group_cursor, _, _) = self.input.cursor().group(proc_macro2::Delimiter::Parenthesis).unwrap_or_else(||
37            abort!(self.input.span(), format!("{id} must be specified as a list, i.e. `{id}(\"foo\")` or `{id}(parameter = \"foo\")`"))
38        );
39        let size = group_cursor.token_stream().into_iter().size_hint().0;
40        group_cursor.ident().is_some() && size == 1
41    }
42}