vector_config/external/
serde_with.rs

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