prost_validate_types/
lib.rs1#[allow(clippy::len_without_is_empty)]
2mod proto;
3
4use anyhow::anyhow;
5use once_cell::sync::Lazy;
6use prost_reflect::{
7 ExtensionDescriptor, FieldDescriptor, MessageDescriptor, OneofDescriptor, Value,
8};
9pub use proto::*;
10use std::borrow::Cow;
11
12#[allow(clippy::unwrap_used)]
13static VALIDATION_DISABLED: Lazy<ExtensionDescriptor> = Lazy::new(|| {
14 DESCRIPTOR_POOL
15 .get_extension_by_name("validate.disabled")
16 .ok_or(anyhow!("validate.disabled extension not found"))
17 .unwrap()
18});
19#[allow(clippy::unwrap_used)]
20static VALIDATION_IGNORED: Lazy<ExtensionDescriptor> = Lazy::new(|| {
21 DESCRIPTOR_POOL
22 .get_extension_by_name("validate.ignored")
23 .ok_or(anyhow!("validate.ignored extension not found"))
24 .unwrap()
25});
26#[allow(clippy::unwrap_used)]
27static VALIDATION_FIELD_RULES: Lazy<ExtensionDescriptor> = Lazy::new(|| {
28 DESCRIPTOR_POOL
29 .get_extension_by_name("validate.rules")
30 .ok_or(anyhow!("validate.rules extension not found"))
31 .unwrap()
32});
33#[allow(clippy::unwrap_used)]
34static VALIDATION_ONE_OF_RULES: Lazy<ExtensionDescriptor> = Lazy::new(|| {
35 DESCRIPTOR_POOL
36 .get_extension_by_name("validate.required")
37 .ok_or(anyhow!("validate.required extension not found"))
38 .unwrap()
39});
40
41pub trait FieldRulesExt {
42 fn validation_rules(&self) -> anyhow::Result<Option<FieldRules>>;
43 fn real_oneof(&self) -> Option<OneofDescriptor>;
44 fn optional(&self) -> bool;
45}
46
47impl FieldRulesExt for FieldDescriptor {
48 fn validation_rules(&self) -> anyhow::Result<Option<FieldRules>> {
49 match self
50 .options()
51 .get_extension(&VALIDATION_FIELD_RULES)
52 .as_message()
53 {
54 Some(r) => Ok(Some(r.transcode_to::<FieldRules>()?)),
55 None => Ok(None),
56 }
57 }
58 fn real_oneof(&self) -> Option<OneofDescriptor> {
59 if let Some(oneof) = self.containing_oneof() {
60 if oneof.is_synthetic() {
61 return None;
62 }
63 return Some(oneof);
64 }
65 None
66 }
67
68 fn optional(&self) -> bool {
69 self.containing_oneof().is_some_and(|d| d.is_synthetic())
70 }
71}
72
73pub trait OneofRulesExt {
74 fn required(&self) -> bool;
75}
76
77impl OneofRulesExt for OneofDescriptor {
78 fn required(&self) -> bool {
79 self.options()
80 .get_extension(&VALIDATION_ONE_OF_RULES)
81 .is_true()
82 }
83}
84
85pub trait MessageRulesExt {
86 fn validation_disabled(&self) -> bool;
87 fn validation_ignored(&self) -> bool;
88}
89
90impl MessageRulesExt for MessageDescriptor {
91 fn validation_disabled(&self) -> bool {
92 self.options().get_extension(&VALIDATION_DISABLED).is_true()
93 }
94
95 fn validation_ignored(&self) -> bool {
96 self.options().get_extension(&VALIDATION_IGNORED).is_true()
97 }
98}
99
100trait IsTrueExt {
101 fn is_true(&self) -> bool;
102}
103
104impl IsTrueExt for Cow<'_, Value> {
105 fn is_true(&self) -> bool {
106 self.as_bool().unwrap_or(false)
107 }
108}