use serde::{Deserialize, Deserializer, Serialize, Serializer};
use crate::{
ConfigError,
tree::{
empty::EffectivelyUnset,
merge::{Merge, MergeContext, OriginId},
partial_value::PartialValue,
path::ConfigPath,
},
};
#[derive(Default, Debug, Clone, PartialEq, Eq)]
pub enum Section<T> {
#[default]
Unset,
Set(T),
}
impl<T> Section<T> {
pub fn is_unset(&self) -> bool {
matches!(self, Section::Unset)
}
}
impl<'de, T> Deserialize<'de> for Section<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 Section<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 Section<T>
where
T: EffectivelyUnset,
{
fn is_effectively_unset(&self) -> bool {
match self {
Section::Unset => true,
Section::Set(value) => value.is_effectively_unset(),
}
}
}
impl<T> PartialValue for Section<T>
where
T: PartialValue + Default,
{
type Resolved = T::Resolved;
fn attribute(&mut self, origin: OriginId) {
if let Section::Set(value) = self {
value.attribute(origin);
}
}
fn apply_defaults(&mut self) {
if self.is_unset() {
*self = Section::Set(T::default());
}
if let Section::Set(value) = self {
value.apply_defaults();
}
}
fn resolve(self, path: &mut ConfigPath) -> Result<Self::Resolved, ConfigError> {
match self {
Section::Set(value) => value.resolve(path),
Section::Unset => T::default().resolve(path),
}
}
}
impl<T> Merge for Section<T>
where
T: Merge,
{
fn merge(&mut self, incoming: Self, context: &mut MergeContext<'_>) -> Result<(), ConfigError> {
let Section::Set(incoming) = incoming else {
return Ok(());
};
match self {
Section::Set(existing) => existing.merge(incoming, context),
Section::Unset => {
*self = Section::Set(incoming);
Ok(())
}
}
}
}