Skip to main content

ferrin_spec/shared/
warning.rs

1//! Non-fatal warnings emitted by adapters.
2
3use serde::Deserialize;
4use serde::Serialize;
5
6/// A non-fatal warning produced while preparing or executing a call.
7///
8/// Adapters emit warnings instead of errors when a requested option is not
9/// supported by the provider; the option is ignored and the call proceeds.
10#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
11#[serde(tag = "type", rename_all = "kebab-case")]
12#[non_exhaustive]
13pub enum Warning {
14    /// A feature or setting is not supported by the provider or model.
15    Unsupported {
16        /// Name of the unsupported feature or setting.
17        feature: String,
18        /// Additional details.
19        #[serde(default, skip_serializing_if = "Option::is_none")]
20        details: Option<String>,
21    },
22    /// A feature is supported with reduced fidelity or via a workaround.
23    Compatibility {
24        /// Name of the affected feature.
25        feature: String,
26        /// Additional details.
27        #[serde(default, skip_serializing_if = "Option::is_none")]
28        details: Option<String>,
29    },
30    /// A setting is deprecated and will be removed.
31    Deprecated {
32        /// Name of the deprecated setting.
33        setting: String,
34        /// Migration guidance.
35        message: String,
36    },
37    /// Any other warning.
38    Other {
39        /// Human-readable message.
40        message: String,
41    },
42}
43
44impl Warning {
45    /// Creates an [`Warning::Unsupported`] warning without details.
46    #[must_use]
47    pub fn unsupported(feature: impl Into<String>) -> Self {
48        Self::Unsupported {
49            feature: feature.into(),
50            details: None,
51        }
52    }
53
54    /// Creates an [`Warning::Unsupported`] warning with details.
55    #[must_use]
56    pub fn unsupported_with_details(
57        feature: impl Into<String>,
58        details: impl Into<String>,
59    ) -> Self {
60        Self::Unsupported {
61            feature: feature.into(),
62            details: Some(details.into()),
63        }
64    }
65
66    /// Creates a [`Warning::Compatibility`] warning.
67    #[must_use]
68    pub fn compatibility(feature: impl Into<String>, details: Option<String>) -> Self {
69        Self::Compatibility {
70            feature: feature.into(),
71            details,
72        }
73    }
74
75    /// Creates a [`Warning::Deprecated`] warning.
76    #[must_use]
77    pub fn deprecated(setting: impl Into<String>, message: impl Into<String>) -> Self {
78        Self::Deprecated {
79            setting: setting.into(),
80            message: message.into(),
81        }
82    }
83
84    /// Creates a [`Warning::Other`] warning.
85    #[must_use]
86    pub fn other(message: impl Into<String>) -> Self {
87        Self::Other {
88            message: message.into(),
89        }
90    }
91}
92
93impl std::fmt::Display for Warning {
94    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
95        match self {
96            Self::Unsupported { feature, details } => match details {
97                Some(details) => write!(f, "unsupported {feature}: {details}"),
98                None => write!(f, "unsupported {feature}"),
99            },
100            Self::Compatibility { feature, details } => match details {
101                Some(details) => write!(f, "compatibility for {feature}: {details}"),
102                None => write!(f, "compatibility for {feature}"),
103            },
104            Self::Deprecated { setting, message } => {
105                write!(f, "deprecated setting {setting}: {message}")
106            }
107            Self::Other { message } => f.write_str(message),
108        }
109    }
110}