use serde::{Deserialize, Deserializer, Serialize, Serializer};
use crate::{
ConfigError, ConfigPath, Merge, MergeContext, OriginId, PartialValue, tree::EffectivelyUnset,
};
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum EnumSection<T> {
Unset,
Set(T),
}
#[allow(clippy::derivable_impls, reason = "Want this even when T not Default")]
impl<T> Default for EnumSection<T> {
fn default() -> Self {
Self::Unset
}
}
impl<T> EnumSection<T> {
pub fn is_unset(&self) -> bool {
matches!(self, EnumSection::Unset)
}
}
impl<'de, T> Deserialize<'de> for EnumSection<T>
where
T: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
T::deserialize(deserializer).map(Self::Set)
}
}
impl<T> Serialize for EnumSection<T>
where
T: Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match self {
Self::Set(value) => value.serialize(serializer),
Self::Unset => serializer.serialize_none(),
}
}
}
impl<T> EffectivelyUnset for EnumSection<T> {
fn is_effectively_unset(&self) -> bool {
matches!(self, EnumSection::Unset)
}
}
impl<T> PartialValue for EnumSection<T>
where
T: PartialValue,
{
type Resolved = T::Resolved;
fn attribute(&mut self, origin: OriginId) {
if let EnumSection::Set(value) = self {
value.attribute(origin);
}
}
fn apply_defaults(&mut self) {
if let EnumSection::Set(value) = self {
value.apply_defaults();
}
}
fn resolve(self, path: &mut ConfigPath) -> Result<Self::Resolved, ConfigError> {
match self {
EnumSection::Set(value) => value.resolve(path),
EnumSection::Unset => Err(ConfigError::MissingRequiredValue {
position: path.clone(),
}),
}
}
}
impl<T> Merge for EnumSection<T>
where
T: Merge,
{
fn merge(&mut self, incoming: Self, context: &mut MergeContext<'_>) -> Result<(), ConfigError> {
let EnumSection::Set(incoming) = incoming else {
return Ok(());
};
match self {
EnumSection::Set(existing) => existing.merge(incoming, context),
EnumSection::Unset => {
*self = EnumSection::Set(incoming);
Ok(())
}
}
}
}