proto_types/protovalidate/
substring_rules.rs

1use proc_macro2::{Span, TokenStream};
2use quote::ToTokens;
3use syn::LitByteStr;
4
5use crate::protovalidate::{containing_rules::format_bytes, BytesRules, StringRules};
6
7pub struct SubstringRule {
8  pub val_tokens: TokenStream,
9  pub error_message: String,
10}
11
12pub struct SubstringRules {
13  pub contains: Option<SubstringRule>,
14  pub not_contains: Option<SubstringRule>,
15  pub prefix: Option<SubstringRule>,
16  pub suffix: Option<SubstringRule>,
17}
18
19impl SubstringRules {
20  pub fn has_rule(&self) -> bool {
21    self.contains.is_some()
22      || self.not_contains.is_some()
23      || self.prefix.is_some()
24      || self.suffix.is_some()
25  }
26}
27
28impl StringRules {
29  pub fn substring_rules(&self) -> SubstringRules {
30    let contains = self.contains.as_ref().map(|v| SubstringRule {
31      val_tokens: v.to_token_stream(),
32      error_message: format!("must contain the substring '{}'", v),
33    });
34    let not_contains = self.not_contains.as_ref().map(|v| SubstringRule {
35      val_tokens: v.to_token_stream(),
36      error_message: format!("must not contain the substring '{}'", v),
37    });
38
39    let prefix = self.prefix.as_ref().map(|v| SubstringRule {
40      val_tokens: v.to_token_stream(),
41      error_message: format!("must start with '{}'", v),
42    });
43    let suffix = self.suffix.as_ref().map(|v| SubstringRule {
44      val_tokens: v.to_token_stream(),
45      error_message: format!("must end with '{}'", v),
46    });
47
48    SubstringRules {
49      contains,
50      not_contains,
51      prefix,
52      suffix,
53    }
54  }
55}
56
57impl BytesRules {
58  pub fn substring_rules(&self) -> SubstringRules {
59    let contains = self.contains.as_ref().map(|v| SubstringRule {
60      val_tokens: LitByteStr::new(v, Span::call_site()).to_token_stream(),
61      error_message: format!("must contain {}", format_bytes(v)),
62    });
63    let prefix = self.prefix.as_ref().map(|v| SubstringRule {
64      val_tokens: LitByteStr::new(v, Span::call_site()).to_token_stream(),
65      error_message: format!("must start with {}", format_bytes(v)),
66    });
67    let suffix = self.suffix.as_ref().map(|v| SubstringRule {
68      val_tokens: LitByteStr::new(v, Span::call_site()).to_token_stream(),
69      error_message: format!("must end with {}", format_bytes(v)),
70    });
71
72    SubstringRules {
73      contains,
74      not_contains: None,
75      prefix,
76      suffix,
77    }
78  }
79}