vector_config/external/
serde_with.rs

1use std::cell::RefCell;
2
3use vector_config_common::{attributes::CustomAttribute, constants};
4
5use crate::schema::generate_optional_schema;
6use crate::{
7    num::NumberClass,
8    schema::{generate_number_schema, SchemaGenerator, SchemaObject},
9    Configurable, GenerateError, Metadata,
10};
11
12// Blanket implementation of `Configurable` for any `serde_with` helper that is also `Configurable`.
13impl<T> Configurable for serde_with::As<T>
14where
15    T: Configurable,
16{
17    fn referenceable_name() -> Option<&'static str> {
18        // Forward to the underlying `T`.
19        T::referenceable_name()
20    }
21
22    fn metadata() -> Metadata {
23        // Forward to the underlying `T`.
24        //
25        // We have to convert from `Metadata` to `Metadata` which erases the default value,
26        // notably, but `serde_with` helpers should never actually have default values, so this is
27        // essentially a no-op.
28        T::metadata().convert()
29    }
30
31    fn validate_metadata(metadata: &Metadata) -> Result<(), GenerateError> {
32        // Forward to the underlying `T`.
33        //
34        // We have to convert from `Metadata` to `Metadata` which erases the default value,
35        // notably, but `serde_with` helpers should never actually have default values, so this is
36        // essentially a no-op.
37        let converted = metadata.convert();
38        T::validate_metadata(&converted)
39    }
40
41    fn generate_schema(gen: &RefCell<SchemaGenerator>) -> Result<SchemaObject, GenerateError> {
42        // Forward to the underlying `T`.
43        //
44        // We have to convert from `Metadata` to `Metadata` which erases the default value,
45        // notably, but `serde_with` helpers should never actually have default values, so this is
46        // essentially a no-op.
47        T::generate_schema(gen)
48    }
49}
50
51impl Configurable for serde_with::DurationSeconds<u64, serde_with::formats::Strict> {
52    fn referenceable_name() -> Option<&'static str> {
53        // We're masking the type parameters here because we only deal with whole seconds via this
54        // version, and handle fractional seconds with `DurationSecondsWithFrac<f64, Strict>`, which we
55        // expose as `serde_with::DurationFractionalSeconds`.
56        Some("serde_with::DurationSeconds")
57    }
58
59    fn metadata() -> Metadata {
60        let mut metadata = Metadata::default();
61        metadata.set_description("A span of time, in whole seconds.");
62        metadata.add_custom_attribute(CustomAttribute::kv(
63            constants::DOCS_META_NUMERIC_TYPE,
64            NumberClass::Unsigned,
65        ));
66        metadata.add_custom_attribute(CustomAttribute::kv(
67            constants::DOCS_META_TYPE_UNIT,
68            "seconds",
69        ));
70        metadata
71    }
72
73    fn generate_schema(_: &RefCell<SchemaGenerator>) -> Result<SchemaObject, GenerateError> {
74        // This boils down to a number schema, but we just need to shuttle around the metadata so
75        // that we can call the relevant schema generation function.
76        Ok(generate_number_schema::<u64>())
77    }
78}
79
80impl Configurable for serde_with::DurationSecondsWithFrac<f64, serde_with::formats::Strict> {
81    fn referenceable_name() -> Option<&'static str> {
82        // We're masking the type parameters here because we only deal with fractional seconds via this
83        // version, and handle whole seconds with `DurationSeconds<u64, Strict>`, which we
84        // expose as `serde_with::DurationSeconds`.
85        Some("serde_with::DurationFractionalSeconds")
86    }
87
88    fn metadata() -> Metadata {
89        let mut metadata = Metadata::default();
90        metadata.set_description("A span of time, in fractional seconds.");
91        metadata.add_custom_attribute(CustomAttribute::kv(
92            constants::DOCS_META_NUMERIC_TYPE,
93            NumberClass::FloatingPoint,
94        ));
95        metadata.add_custom_attribute(CustomAttribute::kv(
96            constants::DOCS_META_TYPE_UNIT,
97            "seconds",
98        ));
99        metadata
100    }
101
102    fn generate_schema(_: &RefCell<SchemaGenerator>) -> Result<SchemaObject, GenerateError> {
103        // This boils down to a number schema, but we just need to shuttle around the metadata so
104        // that we can call the relevant schema generation function.
105        Ok(generate_number_schema::<f64>())
106    }
107}
108
109impl Configurable for serde_with::DurationMilliSeconds<u64, serde_with::formats::Strict> {
110    fn referenceable_name() -> Option<&'static str> {
111        // We're masking the type parameters here because we only deal with whole milliseconds via this
112        // version.
113        Some("serde_with::DurationMilliSeconds")
114    }
115
116    fn metadata() -> Metadata {
117        let mut metadata = Metadata::default();
118        metadata.set_description("A span of time, in whole milliseconds.");
119        metadata.add_custom_attribute(CustomAttribute::kv(
120            constants::DOCS_META_NUMERIC_TYPE,
121            NumberClass::Unsigned,
122        ));
123        metadata.add_custom_attribute(CustomAttribute::kv(
124            constants::DOCS_META_TYPE_UNIT,
125            "milliseconds",
126        ));
127        metadata
128    }
129
130    fn generate_schema(_: &RefCell<SchemaGenerator>) -> Result<SchemaObject, GenerateError> {
131        // This boils down to a number schema, but we just need to shuttle around the metadata so
132        // that we can call the relevant schema generation function.
133        Ok(generate_number_schema::<u64>())
134    }
135}
136
137impl Configurable for Option<serde_with::DurationMilliSeconds<u64, serde_with::formats::Strict>> {
138    fn generate_schema(gen: &RefCell<SchemaGenerator>) -> Result<SchemaObject, GenerateError>
139    where
140        Self: Sized,
141    {
142        generate_optional_schema(&u64::as_configurable_ref(), gen)
143    }
144}