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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
use serde::{Deserialize, Deserializer, Serialize, Serializer};

#[derive(Debug)]
pub enum Scenario {
    #[cfg(feature = "spatially-explicit-uniform-turnover-scenario")]
    SpatiallyExplicitUniformTurnover(
        rustcoalescence_scenarios::spatially_explicit::uniform::SpatiallyExplicitUniformTurnoverArguments,
    ),
    #[cfg(feature = "spatially-explicit-turnover-map-scenario")]
    SpatiallyExplicitTurnoverMap(
        rustcoalescence_scenarios::spatially_explicit::map::SpatiallyExplicitTurnoverMapArguments,
    ),
    #[cfg(feature = "non-spatial-scenario")]
    NonSpatial(rustcoalescence_scenarios::non_spatial::NonSpatialArguments),
    #[cfg(feature = "spatially-implicit-scenario")]
    SpatiallyImplicit(rustcoalescence_scenarios::spatially_implicit::SpatiallyImplicitArguments),
    #[cfg(feature = "almost-infinite-normal-dispersal-scenario")]
    AlmostInfiniteNormalDispersal(rustcoalescence_scenarios::almost_infinite::normal::AlmostInfiniteNormalDispersalArguments),
    #[cfg(feature = "almost-infinite-clark2dt-dispersal-scenario")]
    AlmostInfiniteClark2DtDispersal(rustcoalescence_scenarios::almost_infinite::clark2dt::AlmostInfiniteClark2DtDispersalArguments),
    #[cfg(feature = "wrapping-noise-scenario")]
    WrappingNoise(rustcoalescence_scenarios::wrapping_noise::WrappingNoiseArguments),
}

impl Serialize for Scenario {
    #[allow(unused_variables)]
    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
        let scenario: ScenarioRaw = match *self {
            #[cfg(feature = "spatially-explicit-uniform-turnover-scenario")]
            Self::SpatiallyExplicitUniformTurnover(ref args) => ScenarioRaw::SpatiallyExplicit(
                rustcoalescence_scenarios::spatially_explicit::SpatiallyExplicitArguments::from_uniform_rate(args),
            ),
            #[cfg(feature = "spatially-explicit-turnover-map-scenario")]
            Self::SpatiallyExplicitTurnoverMap(ref args) => ScenarioRaw::SpatiallyExplicit(
                rustcoalescence_scenarios::spatially_explicit::SpatiallyExplicitArguments::from_map(args),
            ),
            #[cfg(feature = "non-spatial-scenario")]
            Self::NonSpatial(ref args) => ScenarioRaw::NonSpatial(args.clone()),
            #[cfg(feature = "spatially-implicit-scenario")]
            Self::SpatiallyImplicit(ref args) => ScenarioRaw::SpatiallyImplicit(args.clone()),
            #[cfg(feature = "almost-infinite-normal-dispersal-scenario")]
            Self::AlmostInfiniteNormalDispersal(ref args) => ScenarioRaw::AlmostInfinite(
                rustcoalescence_scenarios::almost_infinite::AlmostInfiniteArguments::from_normal(args),
            ),
            #[cfg(feature = "almost-infinite-clark2dt-dispersal-scenario")]
            Self::AlmostInfiniteClark2DtDispersal(ref args) => ScenarioRaw::AlmostInfinite(
                rustcoalescence_scenarios::almost_infinite::AlmostInfiniteArguments::from_clark2dt(args),
            ),
            #[cfg(feature = "wrapping-noise-scenario")]
            Self::WrappingNoise(ref args) => ScenarioRaw::WrappingNoise(args.clone()),
        };

        #[allow(unreachable_code)]
        scenario.serialize(serializer)
    }
}

impl<'de> Deserialize<'de> for Scenario {
    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
        match ScenarioRaw::deserialize(deserializer)? {
            #[cfg(any(
                feature = "spatially-explicit-uniform-turnover-scenario",
                feature = "spatially-explicit-turnover-map-scenario",
            ))]
            ScenarioRaw::SpatiallyExplicit(args) => {
                match args.try_load().map_err(serde::de::Error::custom)? {
                    #[allow(clippy::match_single_binding)]
                    either::Either::Left(args) => match args {
                        #[cfg(feature = "spatially-explicit-uniform-turnover-scenario")]
                        args => Ok(Self::SpatiallyExplicitUniformTurnover(args)),
                    },
                    #[allow(clippy::match_single_binding)]
                    either::Either::Right(args) => match args {
                        #[cfg(feature = "spatially-explicit-turnover-map-scenario")]
                        args => Ok(Self::SpatiallyExplicitTurnoverMap(args)),
                    },
                }
            },
            #[cfg(feature = "non-spatial-scenario")]
            ScenarioRaw::NonSpatial(args) => Ok(Self::NonSpatial(args)),
            #[cfg(feature = "spatially-implicit-scenario")]
            ScenarioRaw::SpatiallyImplicit(args) => Ok(Self::SpatiallyImplicit(args)),
            #[cfg(any(
                feature = "almost-infinite-normal-dispersal-scenario",
                feature = "almost-infinite-clark2dt-dispersal-scenario",
            ))]
            ScenarioRaw::AlmostInfinite(args) => match args.load() {
                #[allow(clippy::match_single_binding)]
                either::Either::Left(args) => match args {
                    #[cfg(feature = "almost-infinite-normal-dispersal-scenario")]
                    args => Ok(Self::AlmostInfiniteNormalDispersal(args)),
                },
                #[allow(clippy::match_single_binding)]
                either::Either::Right(args) => match args {
                    #[cfg(feature = "almost-infinite-clark2dt-dispersal-scenario")]
                    args => Ok(Self::AlmostInfiniteClark2DtDispersal(args)),
                },
            },
            #[cfg(feature = "wrapping-noise-scenario")]
            ScenarioRaw::WrappingNoise(args) => Ok(Self::WrappingNoise(args)),
        }
    }
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename = "Scenario")]
enum ScenarioRaw {
    #[cfg(any(
        feature = "spatially-explicit-uniform-turnover-scenario",
        feature = "spatially-explicit-turnover-map-scenario",
    ))]
    SpatiallyExplicit(rustcoalescence_scenarios::spatially_explicit::SpatiallyExplicitArguments),
    #[cfg(feature = "non-spatial-scenario")]
    NonSpatial(rustcoalescence_scenarios::non_spatial::NonSpatialArguments),
    #[cfg(feature = "spatially-implicit-scenario")]
    SpatiallyImplicit(rustcoalescence_scenarios::spatially_implicit::SpatiallyImplicitArguments),
    #[cfg(any(
        feature = "almost-infinite-normal-dispersal-scenario",
        feature = "almost-infinite-clark2dt-dispersal-scenario",
    ))]
    AlmostInfinite(rustcoalescence_scenarios::almost_infinite::AlmostInfiniteArguments),
    #[cfg(feature = "wrapping-noise-scenario")]
    WrappingNoise(rustcoalescence_scenarios::wrapping_noise::WrappingNoiseArguments),
}