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
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
use super::Merge;
use serde::{Deserialize, Serialize};

/// Note: `{}` (empty object) is treated as `true`.
#[derive(Clone, Serialize, Debug)]
#[serde(untagged)]
pub enum BoolOrObject<T> {
    Bool(bool),
    Obj(T),
}

impl<T> From<bool> for BoolOrObject<T> {
    fn from(v: bool) -> Self {
        BoolOrObject::Bool(v)
    }
}

impl<T> Default for BoolOrObject<T> {
    fn default() -> Self {
        Self::Bool(false)
    }
}

impl<T> BoolOrObject<T> {
    pub fn into_obj(self) -> Option<T>
    where
        T: Default,
    {
        match self {
            BoolOrObject::Bool(true) => Some(Default::default()),
            BoolOrObject::Bool(false) => None,
            BoolOrObject::Obj(o) => Some(o),
        }
    }
}

impl<T> Merge for BoolOrObject<T>
where
    T: Clone + Merge + Default,
{
    fn merge(&mut self, from: &Self) {
        match self {
            BoolOrObject::Bool(l) => match from {
                BoolOrObject::Bool(r) => {
                    *l |= *r;
                }
                BoolOrObject::Obj(_) => *self = from.clone(),
            },
            BoolOrObject::Obj(o) => match from {
                BoolOrObject::Bool(r) => {
                    if *r {
                        o.merge(&Default::default())
                    }
                }
                BoolOrObject::Obj(r) => o.merge(r),
            },
        }
    }
}

impl<'de, T> Deserialize<'de> for BoolOrObject<T>
where
    T: Deserialize<'de>,
{
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        #[derive(Deserialize)]
        #[serde(untagged)]
        enum Deser<T> {
            Bool(bool),
            Obj(T),
            EmptyObject(EmptyStruct),
        }

        #[derive(Deserialize)]
        #[serde(deny_unknown_fields)]
        struct EmptyStruct {}

        let content = swc_common::private::serde::de::Content::deserialize(deserializer)?;

        let deserializer =
            swc_common::private::serde::de::ContentRefDeserializer::<D::Error>::new(&content);

        let res = Deser::deserialize(deserializer);

        match res {
            Ok(v) => Ok(match v {
                Deser::Bool(v) => BoolOrObject::Bool(v),
                Deser::Obj(v) => BoolOrObject::Obj(v),
                Deser::EmptyObject(_) => BoolOrObject::Bool(true),
            }),
            Err(..) => {
                let d =
                    swc_common::private::serde::de::ContentDeserializer::<D::Error>::new(content);
                Ok(BoolOrObject::Obj(T::deserialize(d)?))
            }
        }
    }
}