Skip to content

Commit ba8c096

Browse files
authored
chore(config): Set up ConfigurableRef for schema functions (#16568)
* Reduce visibility of some pub functions, and drop unused * Set up `struct ConfigurableRef` for config schema functions The config schema functions currently dispatch which configurable type to use based on a type parameter to the functions. In order to make this dispatch dynamic, a new `struct ConfigurableRef` is set up that contains references to the functions for a given type implementing `trait Configurable`. This is then used in the schema functions to dispatch their operation, eliminating the type bound. This will be used by a follow-up change to allow for dynamically registrable transforms.
1 parent a9ba2cb commit ba8c096

File tree

15 files changed

+211
-166
lines changed

15 files changed

+211
-166
lines changed

lib/vector-common/src/datetime.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use derivative::Derivative;
66
use serde_json::Value;
77
use vector_config::{
88
schema::{
9-
apply_metadata, generate_const_string_schema, generate_one_of_schema,
9+
apply_base_metadata, generate_const_string_schema, generate_one_of_schema,
1010
get_or_generate_schema, SchemaGenerator, SchemaObject,
1111
},
1212
Configurable, GenerateError, Metadata, ToValue,
@@ -117,7 +117,7 @@ impl Configurable for TimeZone {
117117
let mut local_schema = generate_const_string_schema("local".to_string());
118118
let mut local_metadata = Metadata::with_description("System local timezone.");
119119
local_metadata.add_custom_attribute(CustomAttribute::kv("logical_name", "Local"));
120-
apply_metadata::<()>(&mut local_schema, local_metadata);
120+
apply_base_metadata(&mut local_schema, local_metadata);
121121

122122
let mut tz_metadata = Metadata::with_title("A named timezone.");
123123
tz_metadata.set_description(
@@ -126,7 +126,7 @@ impl Configurable for TimeZone {
126126
[tzdb]: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones"#,
127127
);
128128
tz_metadata.add_custom_attribute(CustomAttribute::kv("logical_name", "Named"));
129-
let tz_schema = get_or_generate_schema::<Tz>(gen, Some(tz_metadata))?;
129+
let tz_schema = get_or_generate_schema(&Tz::as_configurable_ref(), gen, Some(tz_metadata))?;
130130

131131
Ok(generate_one_of_schema(&[local_schema, tz_schema]))
132132
}

lib/vector-config-macros/src/configurable.rs

+12-4
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,11 @@ fn build_to_value_fn(_container: &Container<'_>) -> proc_macro2::TokenStream {
130130
fn build_virtual_newtype_schema_fn(virtual_ty: Type) -> proc_macro2::TokenStream {
131131
quote! {
132132
fn generate_schema(schema_gen: &::std::cell::RefCell<::vector_config::schema::SchemaGenerator>) -> std::result::Result<::vector_config::schema::SchemaObject, ::vector_config::GenerateError> {
133-
::vector_config::schema::get_or_generate_schema::<#virtual_ty>(schema_gen, None)
133+
::vector_config::schema::get_or_generate_schema(
134+
&<#virtual_ty as ::vector_config::Configurable>::as_configurable_ref(),
135+
schema_gen,
136+
None,
137+
)
134138
}
135139
}
136140
}
@@ -172,7 +176,11 @@ fn generate_struct_field(field: &Field<'_>) -> proc_macro2::TokenStream {
172176
let field_schema_ty = get_field_schema_ty(field);
173177

174178
let spanned_generate_schema = quote_spanned! {field.span()=>
175-
::vector_config::schema::get_or_generate_schema::<#field_schema_ty>(schema_gen, Some(#field_metadata_ref))?
179+
::vector_config::schema::get_or_generate_schema(
180+
&<#field_schema_ty as ::vector_config::Configurable>::as_configurable_ref(),
181+
schema_gen,
182+
Some(#field_metadata_ref),
183+
)?
176184
};
177185

178186
quote! {
@@ -928,7 +936,7 @@ fn generate_enum_variant_apply_metadata(variant: &Variant<'_>) -> proc_macro2::T
928936

929937
quote! {
930938
#variant_metadata
931-
::vector_config::schema::apply_metadata::<()>(&mut subschema, #variant_metadata_ref);
939+
::vector_config::schema::apply_base_metadata(&mut subschema, #variant_metadata_ref);
932940
}
933941
}
934942

@@ -938,7 +946,7 @@ fn generate_enum_variant_tag_apply_metadata(variant: &Variant<'_>) -> proc_macro
938946

939947
quote! {
940948
#variant_tag_metadata
941-
::vector_config::schema::apply_metadata::<()>(&mut tag_subschema, #variant_tag_metadata_ref);
949+
::vector_config::schema::apply_base_metadata(&mut tag_subschema, #variant_tag_metadata_ref);
942950
}
943951
}
944952

lib/vector-config/src/configurable.rs

+54
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,14 @@ where
6565
/// If an error occurs while generating the schema, an error variant will be returned describing
6666
/// the issue.
6767
fn generate_schema(gen: &RefCell<SchemaGenerator>) -> Result<SchemaObject, GenerateError>;
68+
69+
/// Create a new configurable reference table.
70+
fn as_configurable_ref() -> ConfigurableRef
71+
where
72+
Self: 'static,
73+
{
74+
ConfigurableRef::new::<Self>()
75+
}
6876
}
6977

7078
/// A type that can be converted directly to a `serde_json::Value`. This is used when translating
@@ -73,3 +81,49 @@ pub trait ToValue {
7381
/// Convert this value into a `serde_json::Value`. Must not fail.
7482
fn to_value(&self) -> Value;
7583
}
84+
85+
/// A pseudo-reference to a type that can be represented in a Vector configuration. This is
86+
/// composed of references to all the class trait functions.
87+
pub struct ConfigurableRef {
88+
// TODO: Turn this into a plain value once this is resolved:
89+
// https://github.com/rust-lang/rust/issues/63084
90+
type_name: fn() -> &'static str,
91+
// TODO: Turn this into a plain value once const trait functions are implemented
92+
// Ref: https://github.com/rust-lang/rfcs/pull/911
93+
referenceable_name: fn() -> Option<&'static str>,
94+
make_metadata: fn() -> Metadata,
95+
validate_metadata: fn(&Metadata) -> Result<(), GenerateError>,
96+
generate_schema: fn(&RefCell<SchemaGenerator>) -> Result<SchemaObject, GenerateError>,
97+
}
98+
99+
impl ConfigurableRef {
100+
/// Create a new configurable reference table.
101+
pub const fn new<T: Configurable + ?Sized + 'static>() -> Self {
102+
Self {
103+
type_name: std::any::type_name::<T>,
104+
referenceable_name: T::referenceable_name,
105+
make_metadata: T::metadata,
106+
validate_metadata: T::validate_metadata,
107+
generate_schema: T::generate_schema,
108+
}
109+
}
110+
111+
pub(crate) fn type_name(&self) -> &'static str {
112+
(self.type_name)()
113+
}
114+
pub(crate) fn referenceable_name(&self) -> Option<&'static str> {
115+
(self.referenceable_name)()
116+
}
117+
pub(crate) fn make_metadata(&self) -> Metadata {
118+
(self.make_metadata)()
119+
}
120+
pub(crate) fn validate_metadata(&self, metadata: &Metadata) -> Result<(), GenerateError> {
121+
(self.validate_metadata)(metadata)
122+
}
123+
pub(crate) fn generate_schema(
124+
&self,
125+
gen: &RefCell<SchemaGenerator>,
126+
) -> Result<SchemaObject, GenerateError> {
127+
(self.generate_schema)(gen)
128+
}
129+
}

lib/vector-config/src/external/indexmap.rs

+10-6
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ use crate::{
1414

1515
impl<K, V> Configurable for IndexMap<K, V>
1616
where
17-
K: ConfigurableString + ToValue + std::hash::Hash + Eq,
18-
V: Configurable + ToValue,
17+
K: ConfigurableString + ToValue + std::hash::Hash + Eq + 'static,
18+
V: Configurable + ToValue + 'static,
1919
{
2020
fn is_optional() -> bool {
2121
// A hashmap with required fields would be... an object. So if you want that, make a struct
@@ -34,9 +34,13 @@ where
3434

3535
fn generate_schema(gen: &RefCell<SchemaGenerator>) -> Result<SchemaObject, GenerateError> {
3636
// Make sure our key type is _truly_ a string schema.
37-
assert_string_schema_for_map::<K, Self>(gen)?;
37+
assert_string_schema_for_map(
38+
&K::as_configurable_ref(),
39+
gen,
40+
std::any::type_name::<Self>(),
41+
)?;
3842

39-
generate_map_schema::<V>(gen)
43+
generate_map_schema(&V::as_configurable_ref(), gen)
4044
}
4145
}
4246

@@ -56,7 +60,7 @@ where
5660

5761
impl<V> Configurable for IndexSet<V>
5862
where
59-
V: Configurable + ToValue + std::hash::Hash + Eq,
63+
V: Configurable + ToValue + std::hash::Hash + Eq + 'static,
6064
{
6165
fn metadata() -> Metadata {
6266
Metadata::with_transparent(true)
@@ -68,7 +72,7 @@ where
6872
}
6973

7074
fn generate_schema(gen: &RefCell<SchemaGenerator>) -> Result<SchemaObject, GenerateError> {
71-
generate_set_schema::<V>(gen)
75+
generate_set_schema(&V::as_configurable_ref(), gen)
7276
}
7377
}
7478

lib/vector-config/src/external/no_proxy.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ impl Configurable for no_proxy::NoProxy {
1717
fn generate_schema(gen: &RefCell<SchemaGenerator>) -> Result<SchemaObject, GenerateError> {
1818
// `NoProxy` (de)serializes itself as a vector of strings, without any constraints on the string value itself, so
1919
// we just... do that.
20-
generate_array_schema::<String>(gen)
20+
generate_array_schema(&String::as_configurable_ref(), gen)
2121
}
2222
}
2323

lib/vector-config/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ pub use serde_json;
135135

136136
pub mod component;
137137
mod configurable;
138-
pub use self::configurable::{Configurable, ToValue};
138+
pub use self::configurable::{Configurable, ConfigurableRef, ToValue};
139139
mod errors;
140140
pub use self::errors::{BoundDirection, GenerateError};
141141
mod external;

0 commit comments

Comments
 (0)