1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
use std::fmt::{self, Display, Formatter};
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
/// Policy applied when unknown configuration paths are discovered.
pub enum UnknownFieldPolicy {
/// Accept unknown fields silently.
Allow,
/// Accept unknown fields but emit warnings.
Warn,
#[default]
/// Reject unknown fields with an error.
Deny,
}
impl Display for UnknownFieldPolicy {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
Self::Allow => write!(f, "allow"),
Self::Warn => write!(f, "warn"),
Self::Deny => write!(f, "deny"),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
/// Migration action applied when upgrading older configuration payloads.
pub enum ConfigMigrationKind {
/// Renames one configuration path to another.
Rename {
/// Original path used by older configs.
from: String,
/// Replacement path used by newer configs.
to: String,
},
/// Removes a configuration path that is no longer supported.
Remove {
/// Path removed from newer configs.
path: String,
},
}
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
/// Declarative migration rule applied to loaded configuration values.
pub struct ConfigMigration {
/// Version introduced by this migration rule.
pub since_version: u32,
/// Concrete migration action.
pub kind: ConfigMigrationKind,
/// Optional operator-facing migration note.
pub note: Option<String>,
}
impl ConfigMigration {
/// Creates a rename migration from `from` to `to`.
#[must_use]
pub fn rename(from: impl Into<String>, to: impl Into<String>, since_version: u32) -> Self {
Self {
since_version,
kind: ConfigMigrationKind::Rename {
from: from.into(),
to: to.into(),
},
note: None,
}
}
/// Creates a removal migration for `path`.
#[must_use]
pub fn remove(path: impl Into<String>, since_version: u32) -> Self {
Self {
since_version,
kind: ConfigMigrationKind::Remove { path: path.into() },
note: None,
}
}
/// Attaches an operator-facing migration note.
#[must_use]
pub fn with_note(mut self, note: impl Into<String>) -> Self {
self.note = Some(note.into());
self
}
}