protocheck_core/validators/
bytes.rs1use bytes::Bytes;
2use paste::paste;
3#[cfg(feature = "regex")]
4use regex::Regex;
5
6use super::well_known_strings::{is_valid_ip, is_valid_ipv4, is_valid_ipv6};
7use crate::{
8 field_data::FieldContext,
9 protovalidate::Violation,
10 validators::static_data::{base_violations::create_violation, bytes_violations::*},
11};
12
13macro_rules! create_bytes_violation {
14 ($check:ident, $field_context:ident, $violation_name:ident, $error_message:expr) => {
15 create_violation!(
16 bytes,
17 $check,
18 $field_context,
19 $violation_name,
20 $error_message
21 )
22 };
23}
24
25macro_rules! well_known_rule {
26 (
27 $name:ident,
28 $definition:literal
29 ) => {
30 paste! {
31 pub fn $name(field_context: &FieldContext, value: &Bytes) -> Result<(), Violation> {
32 let string_val = parse_bytes_input(value, field_context)?;
33 let check = [<is_valid _ $name>](string_val);
34
35 create_bytes_violation!(check, field_context, $name, concat!("must be a valid ", $definition))
36 }
37 }
38 };
39}
40
41macro_rules! bytes_validator {
42 (
43 $mode:ident,
44 $name:ident,
45 $target_type:ty,
46 $validation_expression:expr
47 ) => {
48 macro_rules! _generate_check {
49 (string_arg, $closure:expr, $value:expr, $target:expr, $field_context:expr) => {{
50 let string_val = parse_bytes_input($value, $field_context)?;
51 $closure($target, &string_val)
52 }};
53
54 (bytes_arg, $closure:expr, $value:expr, $target:expr, $field_context:expr) => {
55 $closure($target, $value)
56 };
57 }
58
59 pub fn $name(
60 field_context: &FieldContext,
61 value: &Bytes,
62 target: $target_type,
63 error_message: &'static str,
64 ) -> Result<(), Violation> {
65 let check = _generate_check!($mode, $validation_expression, value, target, field_context);
66
67 create_bytes_violation!(check, field_context, $name, error_message)
68 }
69 };
70}
71
72well_known_rule!(ip, "ip address");
73
74well_known_rule!(ipv4, "ipv4 address");
75
76well_known_rule!(ipv6, "ipv6 address");
77
78#[cfg(feature = "regex")]
79bytes_validator!(string_arg, pattern, &Regex, |t: &Regex, s: &str| t
80 .is_match(s));
81
82bytes_validator!(bytes_arg, min_len, u64, |t: u64, v: &Bytes| v.len()
83 >= t as usize);
84
85bytes_validator!(bytes_arg, max_len, u64, |t: u64, v: &Bytes| v.len()
86 <= t as usize);
87
88bytes_validator!(bytes_arg, len, u64, |t: u64, v: &Bytes| v.len()
89 == t as usize);
90
91bytes_validator!(
92 bytes_arg,
93 contains,
94 &'static [u8],
95 |t: &'static [u8], v: &Bytes| v.windows(t.len()).any(|win| win == t)
96);
97
98bytes_validator!(
99 bytes_arg,
100 suffix,
101 &'static [u8],
102 |t: &'static [u8], v: &Bytes| v.ends_with(t)
103);
104
105bytes_validator!(
106 bytes_arg,
107 prefix,
108 &'static [u8],
109 |t: &'static [u8], v: &Bytes| v.starts_with(t)
110);