Skip to main content

protocheck_core/
field_data.rs

1use proto_types::FieldType;
2
3use crate::{
4  protovalidate::{field_path_element::Subscript, FieldPathElement},
5  ProtoType,
6};
7
8/// The context for the field being validated.
9#[derive(Clone, Debug)]
10pub struct FieldContext<'a> {
11  pub proto_name: &'a str,
12  pub tag: u32,
13  pub parent_elements: &'a [FieldPathElement],
14  pub subscript: Option<Subscript>,
15  pub key_type: Option<ProtoType>,
16  pub value_type: Option<ProtoType>,
17  pub field_kind: FieldKind,
18}
19
20/// The kind of field being validated. This extra context helps generating more precise violation reports.
21#[derive(Clone, Debug, Copy, PartialEq, Eq)]
22pub enum FieldKind {
23  Map(FieldType),
24  MapKey(FieldType),
25  MapValue(FieldType),
26  Repeated(FieldType),
27  RepeatedItem(FieldType),
28  Single(FieldType),
29}
30
31impl FieldKind {
32  pub fn inner_type(&self) -> FieldType {
33    match self {
34      FieldKind::Map(field_type) => *field_type,
35      FieldKind::MapKey(field_type) => *field_type,
36      FieldKind::MapValue(field_type) => *field_type,
37      FieldKind::Repeated(field_type) => *field_type,
38      FieldKind::RepeatedItem(field_type) => *field_type,
39      FieldKind::Single(field_type) => *field_type,
40    }
41  }
42
43  pub fn is_copy(&self) -> bool {
44    !matches!(
45      self.inner_type(),
46      FieldType::String | FieldType::Message | FieldType::Bytes | FieldType::Any
47    )
48  }
49
50  pub fn is_map_key(&self) -> bool {
51    matches!(self, FieldKind::MapKey(_))
52  }
53
54  pub fn is_map_value(&self) -> bool {
55    matches!(self, FieldKind::MapValue(_))
56  }
57
58  pub fn is_repeated_item(&self) -> bool {
59    matches!(self, FieldKind::RepeatedItem(_))
60  }
61}
62
63#[cfg(feature = "totokens")]
64use proc_macro2::TokenStream;
65#[cfg(feature = "totokens")]
66use quote::{quote, ToTokens};
67
68#[cfg(feature = "totokens")]
69impl ToTokens for FieldKind {
70  fn to_tokens(&self, tokens: &mut TokenStream) {
71    let field_kind_path = quote! { ::protocheck::field_data::FieldKind };
72
73    let variant_tokens = match self {
74      FieldKind::Map(v) => quote! { Map(#v) },
75      FieldKind::MapKey(v) => quote! { MapKey(#v) },
76      FieldKind::MapValue(v) => quote! { MapValue(#v) },
77      FieldKind::Repeated(v) => quote! { Repeated(#v) },
78      FieldKind::RepeatedItem(v) => quote! { RepeatedItem(#v) },
79      FieldKind::Single(v) => quote! { Single(#v) },
80    };
81
82    tokens.extend(quote! { #field_kind_path::#variant_tokens });
83  }
84}